5.2. 座標と領域

画像処理はピクセルに対して作用します。あるピクセルに作用するには、アルゴリズムがそれを座標で指定できなければなりません。それらの矩形に作用する場合も同じで、アルゴリズムとアプリケーションコードの双方が合意できる形で矩形を記述する必要があります。image モジュールが座標と矩形に用いる規約は分かりやすいものですが、コンピュータグラフィックスの慣習ではなく数学的な慣習に慣れた読者が引っかかりやすい一点があり、これは最初に明確にしておく価値があります。

5.2.1. ピクセルグリッド

ピクセル (0, 0) は画像の左上の隅です。x 軸は右方向に伸びるため、x が大きいほど右側になります。y 軸は下方向に伸びるため、y が大きいほど画像の側になります。幅×高さの画像は、(0, 0) から (width - 1, height - 1) までの整数座標にピクセルを保持します。(width, 0)(0, height) にはピクセルは存在しません。これらの位置は右端と下端であり、各方向で実際の最後のピクセルから一歩外側にあたります。

下向きの y 軸が、上で触れた一点です。方眼紙の幾何学に慣れた読者は、y が大きいほどにあると考えますが、ここではその直感がちょうど逆になります。この反転の理由は、デジタルセンサーもデジタルディスプレイも左上から始まり、各行を右へ進みながら上から下へとたどる仕組みになっているためです。ピクセルをメモリ上に同じ順序で並べることで、「バッファ内の位置 i」と「画像の行 r、列 c」の関係を、可能な限り単純な算術にできます。ピクセル (x, y) の位置 i は単に y * width + x です。あらゆる画像処理ライブラリは数十年前から同じ理由でこの配置で合意しており、その代償は画像を初めて扱うときのちょっとした頭の切り替えだけです。

画像を表す矩形。左上の隅にマーカーがあり (0, 0) と表示されています。上辺に沿った 矢印が右を指して x と表示され、左辺を下る 矢印が下を指して y と表示されています。 内側に描かれた小さめの矩形には ROI と 表示され、その左上の隅は (x, y) にあり、 各辺に沿って寸法 w と h が記されています。

画像座標系: 原点は左上、x は右方向に伸び、y は下方向に伸びます。画像内の矩形領域は、その左上の隅 (x, y) と寸法 (w, h) で名付けられます。

5.2.2. 矩形

画像に対するほとんどの操作は、単一のピクセルよりもピクセルの矩形に関心があります。探索する範囲、コピーして取り出す領域、統計を計算するフレーム内のフレームなどです。矩形を名付ける形式は、単一ピクセルの規約を可能な限り単純に拡張したものを採用しています。左上の隅の座標に続けて矩形の寸法を与え、四要素タプル (x, y, w, h) にまとめます。矩形内のピクセルは列 x から x + w - 1 まで、行 y から y + h - 1 までにあります。

ここで明確にしておく価値があるのは、whサイズであって右下の座標ではないという点です。矩形 (10, 20, 4, 3) は列 10、11、12、13 と行 20、21、22 を覆い、合計で 12 ピクセルになります。(10, 20) から (4, 3) まで伸びる領域ではありません。この規約はモジュール全体で統一されているため、いったん身につけてしまえば間違いはなくなりますが、最初のうちは確かに引っかかるものです。

(x, y, w, h) 形式は、一見異なるように見えて同じ規約を共有する三つの場面に現れます。一つ目は、画像が自身の占有範囲を記述するときです。画像全体を覆う矩形は (0, 0, width, height) です。二つ目は、検出メソッドがバウンディングボックスを伴う結果を返すときです。blobrectapriltag などで、ボックスは (x, y, w, h) として返されます。三つ目は、メソッドにフレーム全体ではなく画像の部分領域で動作するよう指示しなければならないときです。操作の範囲を限定する roi キーワード引数は、同じ四要素タプルを取ります。

あるメソッドからバウンディングボックスを受け取り、それを次のメソッドの roi に渡すことは、画像処理で最も一般的なパターンの一つです。粗い一次検出のバウンディングボックスが、より細かい二次検出の探索範囲を絞り込みます。検出結果とメソッド引数にまたがる統一された語彙こそが、このパターンをこれほど分かりやすくしているものです。一つのタプル形式が、受け渡しの両側で同じように使われます。

5.2.3. 整数のアドレス、小数の重心

ピクセルのアドレスそのものは整数です。あるピクセルは指定された整数の列と行に存在する存在しないかのいずれかであり、座標 (40.5, 30.7) に何があるかを尋ねるのは適切に定義された問いではありません。ちょうどその位置に座るピクセルは存在しないからです。とはいえ、image モジュールがピクセル位置から導出するいくつかの量は小数になります。後でアプリケーションが面食らわないよう、その理由を理解しておく価値があります。

最も一般的なケースは重心、すなわち領域の質量中心です。連結したピクセル領域について、浮動小数点形式の重心は、構成ピクセルの位置を密度で重み付けした平均です。ピクセルが二つの列にまたがる領域では、重心の x が例えば 41.6 になります。これは実際のピクセルがちょうどその x に座っていなくても、目で見れば「その領域の真ん中」と表現するような実在の位置です。検出結果オブジェクトは、両方の形式を読み取り専用プロパティとして保持します。整数のペア(cx / cy、位置を整数のピクセル座標を要求するものに戻すときに便利)と、浮動小数点のペア(cxf / cyf、位置がサブピクセル解像度の恩恵を受ける制御ループに渡されるときに便利)です。

もう一つのケースは、周波数領域で測定される二つのフレーム間の変位です。画像のピクセルを直接ではなくスペクトル成分を解析する手法は、1 ピクセルより細かいシフトを分解でき、それらのシフトを浮動小数点の (dx, dy) 値として報告します。

経験則: ピクセルのアドレスは整数であり、アルゴリズムから出てくる位置やシフトは浮動小数点になり得ます。描画メソッドはどちらの形式も受け付け、結果をグリッド上に落とす必要がある場合は浮動小数点を最も近い整数ピクセルへ切り捨てます。

5.2.4. 直交座標と極座標

ここまで説明してきた系は直交座標系です。すべてのピクセルは原点からの水平方向と垂直方向のオフセットで名付けられます。これはバイトが格納される系であり、バッファ内のピクセル i は列 i % width、行 i // width のピクセルに対応し、上から各行をたどります。そしてこれは、すべてのメソッドがデフォルトで動作する系でもあります。

もう一つの表現は、一部のアルゴリズムがそこではるかにうまく機能するため、知っておく価値があります。座標は、各ピクセルを選んだ中心点からの距離と、基準方向との角度で名付けます。画像のピクセルは動いていません。バイトは依然として同じ行優先のバッファ内にあります。しかしアドレス指定の方式が「どれだけ右で、どれだけ下か」から「中心からどれだけ離れ、その周りのどの角度か」へと切り替わったのです。

二つの矩形が並んでおり、それぞれ同じ画像を 表しています。左側は直交座標を示します。 左上が原点で、x 軸と y 軸があり、座標 (x, y) にサンプル点 P があります。右側は 極座標を示します。矩形の内側に中心マーカー C があり、C から同じ点 P へ引かれた線に r(距離)と表示され、円弧に theta(角度) と表示されています。

同じ点 P を二通りに名付けたもの: 左上の原点からの直交座標 (x, y) と、選んだ中心からの極座標 (r, theta) です。

なぜわざわざ切り替えるのでしょうか。困難な探索を容易なものに変える二つの恒等性があるからです。

座標では、選んだ中心の周りで画像を回転させることは、再投影された画像における角度軸 ―― x 方向 ―― に沿ってピクセルを平行移動させるのと同じ操作になります。回転したコピーは、座標形式で元の画像を左右にずらしたものです。

対数極座標の変種 ―― 距離軸が対数スケールを用い、角度軸は線形のまま ―― では、選んだ中心の周りで画像を拡大縮小することは、距離軸 ―― y 方向 ―― に沿ってピクセルを平行移動させるのと同じ操作になります。拡大縮小したコピーは、対数極座標形式で元の画像を上下にずらしたものです。

そのため、回転や拡大縮小を受けた既知のパターンを認識しなければならないアルゴリズムは、空間で探索を行うことができ、そこでは両方の変換が通常の平行移動に変わります。平行移動は回転や拡大縮小よりもはるかに安価に探索でき、座標への再投影こそがこの置き換えを可能にするものです。

座標がピクセルの格納において直交座標を置き換えることはありません。バイトは常に直交グリッド上に存在します。モジュールは、必要に応じて画像を直交座標から座標形式へ再投影する一対のメソッドを提供し、座標を必要とするアルゴリズムがその作業を行い、結果を投影し戻すか、空間での測定値を直接利用します。この仕組みこそが、座標がモジュールの表に現れる唯一の理由です。

個々のピクセルを名付ける直交座標、それらの矩形を名付ける (x, y, w, h) の四要素タプル、そしてアルゴリズムが恩恵を受けるときに利用できる座標があれば、アプリケーションは画像内のどこに何があるかを名付けるための完全な語彙を手にすることになります。それらの位置のいずれかに実際に格納されているものが、この基礎の次の層です。