5.6. 図形とテキストの描画

画像について何かを判断するアルゴリズムは、しばしばその判断を可視化する必要があります。ブロブ検出器はアプリケーションが関心を持つ領域を見つけます。アプリケーションは、何が見つかったかをオペレーター、あるいはスクリプトを実行している開発者が確認できるように、その領域をフレームに描画したいと考えます。座標変換は入力位置を出力位置にマッピングします。そのデバッグでは通常、同じ画像上に2つの位置をマークします。IDEのプレビューはポーリングした時点でフレームバッファにあるものをそのまま読み取るので、アルゴリズムの出力を可視化する最も簡単な方法は、アノテーションをフレームバッファ自体に書き込むことです。Image クラスの 描画 ファミリーは、まさにその作業のためのツールキットです。

5.6.1. プリミティブ

各描画メソッドは、画像上に特定の1種類のマークを配置します。そのカタログは小さく、アノテーションが実際に必要とする幾何学的プリミティブに近いものに留まっています。

  • draw_line() -- 2つの端点間の直線セグメント。

  • draw_rectangle() -- 軸に揃えた矩形(中空または塗りつぶし)。

  • draw_circle() -- 中心の周りの円(中空または塗りつぶし)。

  • draw_ellipse() -- 任意の回転を持つ楕円。

  • draw_cross() -- 点上のプラス記号。重心やクリックターゲットを示す通常のマーク。

  • draw_arrow() -- 始点から終点への矢印。

  • draw_edges() -- 4つの角点を与えた、任意の四角形の4辺。検出したタグや透視変換された領域を縁取る自然な方法。

  • draw_string() -- 組み込みのビットマップフォントによるテキスト。

これらのいずれもソース画像をその場で変更し、チェーン可能なように同じ画像を返します。これは以前に確立された操作メソッドの慣例に従っています。

8つの描画プリミティブをそれぞれ1回ずつ 適用して示す小さなパネルのグリッド。 各パネルには、線、矩形、円、楕円、 クロス、矢印、四角形、または短い テキスト文字列のいずれかが含まれ、 それを生成したメソッドの名前が 下にラベル付けされている。

8つの描画プリミティブ、1パネルにつき1つ。各メソッドは1種類のマークを作成します。

5.6.2. カラー

すべての描画メソッドは color 引数を取り、これが各描画ピクセルに書き込む値を決定します。その引数が取る形式は画像のフォーマットに依存します。RGB565画像の場合、自然な形式は各チャンネルが 0 から 255 の範囲を持つ (r, g, b) タプルであり、モジュールは書き込む前にそれを16ビットのRGB565ワードにパックします。グレースケール画像の場合、自然な形式は 0(黒)から 255(白)までの単一の整数の明るさです。これらのメソッドは、フォーマットの生の格納値、すなわちRGB565の場合は16ビットのパックされたワード、グレースケールの場合は8ビットの整数も受け付けます。これはカラーが別の場所で計算され、すでに格納形式になっている場合に効率的な形式です。

color 引数を省略すると白が描画されます。このデフォルトはグレースケール作業に便利で、白は最大値であり、ほとんどの背景に対してはっきりと読み取れます。RGB565のデバッグオーバーレイではほとんど常に誤りです。カメラが実際に見るような種類のシーンに対しては、通常は緑や赤の方がよく読み取れますし、明示的なカラーは意図を伝えます。

5.6.3. 太さと塗りつぶし

幾何学的メソッドのほとんどは、マークの描画方法を決定する2つのフラグを取ります。

  • thickness=N は線の幅をピクセル単位で設定します。デフォルトは 1 で、ほとんどのオーバーレイにはこれで十分です。より大きな値は、アノテーションが煩雑なシーンに対して、あるいはパイプラインの後続段階が画像をさらに変更した後でも、見えたままでなければならない場合に役立ちます。

  • fill=True はマークをアウトラインから塗りつぶしに切り替え、内部のすべてのピクセルを選択したカラーで描画します。デフォルトは False です。

これらのフラグは、塗りつぶすべき内部を持たないプリミティブ、すなわち線、クロス、矢印、四角形には適用されません。これらでは thickness のみが意味を持ちます。

5.6.4. テキストの描画

draw_string() は、組み込みの8×10ピクセルのビットマップフォントから文字を書き込みます。xy は最初の文字のセルの左上隅、text は描画する文字列で、color は幾何学的メソッドと同じ慣例に従います。このフォントは印字可能なASCII範囲のすべてを備えており、カーニングがありません。各文字は同じ8ピクセル幅のセルを占めるので、出力の位置決めが容易です。

img.draw_string(10, 10, "blobs: 3", color=(0, 255, 0))

文字列には改行(\n)を含めることができます。各改行は次の文字を、前の行の10ピクセル下にある新しい行の先頭に移動させます。scale 引数は浮動小数点の係数によってすべての文字をより大きなサイズで描画し、x_spacingy_spacing は各文字の周りにパディングを追加します。回転/ミラー/反転フラグの小さなセットは、文字列全体または各文字個別のいずれかに適用されます。レイアウトが求める場合に、角度に沿ってテキストを配置したり、非水平のエッジに対して配置したりするのに十分な制御です。

5.6.5. キャンバスのクリア

このファミリーの1つのメソッドは、特定のマークを描画しません。画像のすべてのピクセルを単にゼロにリセットします。

  • clear() -- すべてのピクセルをゼロにする。オプションでROIに制限したり、マスクを通してスコープを限定したりできる。

clear() は、アプリケーションがキャプチャしたフレームの上に重ねるのではなく、各フレームでアノテーションをゼロから合成している場合に適切な答えです。黒いキャンバスから始め、新しいアノテーションを描画し、その結果をディスプレイに渡します。また、マスクバッファとして使用するためのスクラッチ画像を準備する最も安価な方法でもあります。

新しく割り当てられた画像はコンストラクタによってすでにゼロになっているため、clear() は特にフレーム間で再利用されるバッファに対して意味を持ちます。