5.31. 変位マッチング

テンプレートマッチングは このパッチがフレーム内のどこにあるか に答えます。類似度スコアリングは これら2つの画像が全体としてどれだけ似ているか に答えます。それらの間にある別の問いがあります。2つのフレームは同じシーンを示しているが、それらの間でカメラ(またはシーン)が動いた。どれだけ動いたか? これが 変位 の問題であり、imageモジュールは単一の位相相関メソッドでこれを解決します。

5.31.1. 位相相関による変位

find_displacement() は、位相相関 を用いて同じサイズの2つの画像間の剛体アライメントを推定します。これは周波数領域の手法で、各画像に対して高速フーリエ変換(FFT)を実行し、それらの位相を相互相関させ、結果中のピークを特定します。ピーク位置が2つの画像を整列させる平行移動量です。

d = img.find_displacement(template)

print("shift:", d.x_translation, d.y_translation,
      " response:", d.response)

返される Displacementx_translationy_translation(各軸のピクセルシフト)を持ち、さらに response0.0 から 1.0 までの信頼度スコアで、1.0 が完全なピーク)を持ちます。response > 0.3 を下回る検出をフィルタリングして除外すると、位相相関がきれいなピークを見つけられなかった誤った結果が破棄されます。

rotationscale はデフォルトモードではそれぞれ0.0と1.0です。これらは logpolar=True(下記参照)のときにのみ実際の値を取ります。

このメソッドには2つの実用上の制約があります。1つ目は 2のべき乗の寸法 です。位相相関の核心であるFFTは、32×32、64×64、128×128といったサイズで最も高速であり、カメラ上では完全にサポートされるのもそれらのサイズだけです。最もすっきりした構成は、解像度をタプルとして framesize() に渡すことで、これらのサイズのいずれかで直接取り込むことです。

csi0.framesize((64, 64))

より大きなフレームから変位を求める必要があるアプリケーションは、代わりに対象とする領域から2のべき乗のパッチをクロップし、そのパッチに対してマッチャーを実行します。

2つ目は 同じサイズの入力 です。roitemplate_roi は同一の幅と高さを選択しなければならず、そうでない場合マッチャーは呼び出しを拒否します。同じカメラの同じ設定からの2回の取り込みは自動的にこれを満たします。取り込んだフレームを読み込んだ参照と比較する場合は、まず両方を一致する2のべき乗のパッチにクロップする必要があります。

5.31.2. 対数極座標による回転とスケール

デフォルトモードは 平行移動のみ を求めます。2つのフレームが選択した中心まわりの 回転 や同じ中心まわりの スケール でも異なる場合、各画像の 対数極座標 再投影に対して位相相関を実行すると、それらのパラメータが対数極座標系における平行移動に変換されます。これは同じ位相相関マッチャーで復元できます。

d = img.find_displacement(template, logpolar=True)

print("rotation rad:", d.rotation,
      " scale:", d.scale,
      " response:", d.response)

logpolar=True の場合、メソッドは元の画像の代わりに対数極座標投影された画像に対して同じマッチングパイプラインを実行します。結果の rotationscale フィールドが埋められて返されます。rotation は2つのフレーム間の角度(ラジアン単位)、scale はそれらの間のスケール係数です。x_translationy_translation はこのモードでは意味を持たなくなります(対数極座標軸に沿った平行移動はソース内の線形な平行移動に対応しません)。

fix_rotation_scale=True キーワードは中間的なケースに対応します。2つの画像が平行移動と回転/スケールの 両方 で異なり、アプリケーションが回転とスケールを補正した後の 平行移動のみ を必要とする場合です。マッチャーはまず対数極座標パスを実行して回転とスケールを復元し、画像の一方に逆変換を適用し、その後平行移動パスを実行して残りのシフトを復元します。このフラグは logpolar=False のときにのみ意味を持ちます。これは平行移動モードのマッチャーに対して、まず回転/スケールを取り除くよう要求するものです。

極座標変換のパターン、すなわち 直交座標 → 極座標 → マッチング は、logpolar=True を指定した find_displacement() が1回の呼び出しで行うことそのものです。アプリケーションは起動時に参照用の対数極座標パッチを保存し、各ライブフレームを取り込んで対数極座標変換し、メソッドがそれらの間の回転とスケールの差を復元します。回転およびスケールに不変なトラッカーを必要とするアプリケーション(ターゲットに接近する際にカメラが傾いたりズームしたりするドッキングロボット、参照に対して画像がどのように回転しているかを知る必要がある安定化ジンバルなど)にとって、これは標準的な構成です。

5.31.3. 古典的な用途

find_displacement() の最も一般的な用途は、動くカメラを処理するパイプラインにおける フレーム間の動き推定 です。カメラはフレームNで小さな2のべき乗のパッチを取り込み、フレームN+1で同じサイズのパッチを取り込み、その2つに対して find_displacement() を実行し、それらの間のピクセルシフトを読み取ります。このシフトは2回の取り込みの間のカメラ(またはどちらの基準フレームが重要かに応じてシーン)の推定された動きであり、以下の用途に有用です。

  • オプティカルフロー的なセンシング — 下向きカメラを備えたホバリングドローンは、フレームごとの変位を使って横方向の動きを推定し、それをフライトコントローラーにフィードバックします。

  • 画像安定化 — 連続するフレーム間の変位が、記録または伝送される前に取り込んだ画像から差し引かれ、より滑らかなビデオストリームを生成します。

  • 検査アライメント — コンベア沿いに移動する走査カメラは、フレームごとの変位を使って各フレームを次のフレームに対して位置合わせし、部品全体のつなぎ合わせたビューを構築します。

これらのアプリケーションはいずれも同じ形を取ります。取り込み、変位算出、累積して継続的な推定値に反映、そして再度取り込み、です。