OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
OpenCVによる乱数生成とテキスト描画

前のチュートリアル: 基本的な描画
次のチュートリアル: 画像の平滑化

原著者Ana Huamán
互換性OpenCV >= 3.0

目的

このチュートリアルでは、以下の方法を学ぶ:

  • 乱数生成クラスcv::RNG )を使用し、一様分布から乱数を取得する方法。
  • cv::putText 関数を使用してOpenCVウィンドウにテキストを表示する。

コード

  • 前のチュートリアル(基本的な描画)では、座標(cv::Point の形式)、色、太さなどの入力引数を与えて、さまざまな幾何学的図形を描画した。これらの引数に対して具体的な値を与えていたことに気づいたかもしれない。
  • このチュートリアルでは、描画引数に ランダムな 値を使用する。また、多数の幾何学的図形を画像に描き込む。それらをランダムに初期化するため、この処理は ループ を使って自動的に行われる。
  • このコードはOpenCVのサンプルフォルダ内にある。あるいは ここ から入手できる

解説

  1. まず main 関数を見てみよう。最初に行うのは 乱数生成器 オブジェクト(RNG)の作成であることがわかる:
    RNG rng( 0xFFFFFFFF );
    RNGは乱数生成器を実装する。この例では、rng は値 0xFFFFFFFF で初期化されたRNG要素である。
  2. 次に、zeros(黒として表示されることを意味する)に初期化した行列を作成し、その高さ・幅・型を指定する:
    Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );
    imshow( window_name, image );
    #define CV_8UC3
    Definition interface.h:79
  3. それから、奇抜なものを描画していく。コードを見ると、主に8つのセクションに分かれており、それぞれが関数として定義されていることがわかる:
    c = Drawing_Random_Lines(image, window_name, rng);
    if( c != 0 ) return 0;
    c = Drawing_Random_Rectangles(image, window_name, rng);
    if( c != 0 ) return 0;
    c = Drawing_Random_Ellipses( image, window_name, rng );
    if( c != 0 ) return 0;
    c = Drawing_Random_Polylines( image, window_name, rng );
    if( c != 0 ) return 0;
    c = Drawing_Random_Filled_Polygons( image, window_name, rng );
    if( c != 0 ) return 0;
    c = Drawing_Random_Circles( image, window_name, rng );
    if( c != 0 ) return 0;
    c = Displaying_Random_Text( image, window_name, rng );
    if( c != 0 ) return 0;
    c = Displaying_Big_End( image, window_name, rng );
    これらの関数はすべて同じパターンに従っているため、同じ説明がすべてに当てはまることから、ここでは2つだけを分析する。
  4. Checking out the function Drawing_Random_Lines:
    int Drawing_Random_Lines( Mat image, char* window_name, RNG rng )
    {
    int lineType = 8;
    Point pt1, pt2;
    for( int i = 0; i < NUMBER; i++ )
    {
    pt1.x = rng.uniform( x_1, x_2 );
    pt1.y = rng.uniform( y_1, y_2 );
    pt2.x = rng.uniform( x_1, x_2 );
    pt2.y = rng.uniform( y_1, y_2 );
    line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 );
    imshow( window_name, image );
    if( waitKey( DELAY ) >= 0 )
    { return -1; }
    }
    return 0;
    }
    We can observe the following:
    • for ループは NUMBER 回繰り返される。cv::line 関数がこのループ内にあるため、NUMBER 本の線が生成されることを意味する。
    • The line extremes are given by pt1 and pt2. For pt1 we can see that:
      pt1.x = rng.uniform( x_1, x_2 );
      pt1.y = rng.uniform( y_1, y_2 );
      • rng乱数生成器 オブジェクトであることはわかっている。上記のコードでは rng.uniform(a,b) を呼び出している。これは値 ab の間で一様分布する乱数を生成する(a は含み、b は含まない)。
      • 上記の説明から、端点 pt1pt2 はランダムな値になると推測でき、そのため線の位置はかなり予測不可能になり、良い視覚効果が得られる(下の結果セクションを参照)。
      • もう一つの観察として、cv::line の引数で、color 入力に次のものを入力していることに気づく:
        randomColor(rng)
        この関数の実装を確認してみよう:
        static Scalar randomColor( RNG& rng )
        {
        int icolor = (unsigned) rng;
        return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
        }
        見てのとおり、戻り値は3つのランダムに初期化された値を持つ Scalar であり、これらは線の色の RGB 引数として使用される。したがって、線の色もランダムになる!
  5. 上記の説明は、円、楕円、多角形などを生成する他の関数にも当てはまる。centervertices といった引数もランダムに生成される。
  6. 終える前に、Display_Random_TextDisplaying_Big_End の関数も見ておくべきである。どちらにも興味深い特徴がいくつかあるからだ:
  7. Display_Random_Text:

    int Displaying_Random_Text( Mat image, char* window_name, RNG rng )
    {
    int lineType = 8;
    for ( int i = 1; i < NUMBER; i++ )
    {
    Point org;
    org.x = rng.uniform(x_1, x_2);
    org.y = rng.uniform(y_1, y_2);
    putText( image, "Testing text rendering", org, rng.uniform(0,8),
    rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType);
    imshow( window_name, image );
    if( waitKey(DELAY) >= 0 )
    { return -1; }
    }
    return 0;
    }
    _Tp x
    x coordinate of the point
    Definition types.hpp:201

    次の式を除けば、すべて見覚えのあるものである:

    putText( image, "Testing text rendering", org, rng.uniform(0,8),
    rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType);

    では、cv::putText 関数は何をするのか?この例では:

    • テキスト "Testing text rendering"image に描画する。
    • テキストの左下隅は点 org に配置される。
    • フォントの種類は範囲 \([0, 8>\) のランダムな整数値である。
    • フォントのスケールは式 rng.uniform(0, 100)x0.05 + 0.1 で表される(つまりその範囲は \([0.1, 5.1>\) である)。
    • テキストの色はランダムである(randomColor(rng) で表される)。
    • テキストの太さは、rng.uniform(1,10) で指定されるとおり、1から10の範囲である。

    結果として、(他の描画関数と同様に)画像上のランダムな位置に NUMBER 個のテキストが得られる。

  8. Displaying_Big_End

    int Displaying_Big_End( Mat image, char* window_name, RNG rng )
    {
    Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
    Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2);
    int lineType = 8;
    Mat image2;
    for( int i = 0; i < 255; i += 2 )
    {
    image2 = image - Scalar::all(i);
    putText( image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
    Scalar(i, i, 255), 5, lineType );
    imshow( window_name, image2 );
    if( waitKey(DELAY) >= 0 )
    { return -1; }
    }
    return 0;
    }

    getTextSize 関数(引数のテキストのサイズを取得する)のほかに、観察できる新しい操作は foor ループの内側にある:

    image2 = image - Scalar::all(i)

    つまり、image2imageScalar::all(i) の差である。実際にここで起きているのは、image2 の各ピクセルが image の各ピクセルから値 i を引いた結果になるということだ(各ピクセルについてR、G、Bのような3つの値を考慮していることを思い出してほしい。したがってそれぞれが影響を受ける)。

    また、減算操作は 常に 内部で saturate(飽和)操作を実行することも思い出してほしい。これは、得られる結果が常に許容範囲内に収まることを意味する(この例では負にならず、0から255の間)。

結果

コードセクションで見たとおり、プログラムはさまざまな描画関数を順に実行し、次のものを生成する:

  1. まず、このスクリーンショットに見られるように、ランダムな NUMBER 本の線のセットが画面に現れる:
  1. 次に、今度は 矩形 という新しい図形のセットが続く。
  2. 次にいくつかの楕円が現れる。それぞれランダムな位置、サイズ、太さ、円弧の長さを持つ:
  1. 次に、03本のセグメントを持つ 折れ線 が、再びランダムな構成で画面に現れる。
  1. 塗りつぶされた多角形(この例では三角形)が続く。
  2. 最後に現れる幾何学的図形: 円!
  1. 終わり近くで、テキスト "Testing Text Rendering" がさまざまなフォント、サイズ、色、位置で現れる。
  2. そして大団円(ちなみにこれは大きな真実も表現している):