Optical Flow
オプティカルフローは、2つのビデオフレーム間で各ピクセルがどのように移動したかを、動きベクトルの場として推定します。従来手法とディープラーニング手法、用途、OpenCVのコードを紹介します。
オプティカルフローとは、通常は連続するビデオフレーム間で、輝度パターンが見かけ上どのように移動するかを表します。オプティカルフローアルゴリズムは、1枚目のフレーム内の各ピクセルについて、そのピクセルの内容が2枚目のフレームのどこに現れるかを示す2次元変位ベクトル(dx, dy)を推定します。フローフィールドと呼ばれるこの結果は、移動物体とカメラ自体の動きを捉えます。そのため、コンピュータビジョンシステムは、動画の手ぶれ補正、自己運動の推定、フレーム補間、行動認識を実行できます。フローが測定するのはカメラに映る動きであり、真の3D運動ではありません。完全に均一な球体がその場で回転してもフローは生じず、動く影は物理的に何も動いていない場所にフローを生み出します。
オプティカルフローの推定方法#
ほとんどの手法は、点が移動しても輝度は変わらないという輝度一定の仮定から始めます。これを線形化すると、ピクセルごとに1つの方程式が得られます。Ix·u + Iy·v + It = 0では、Ix、Iy、Itは画像のx、y、時間方向の微分で、(u, v)は未知のフローです。方程式が1つでは未知数2つを決定できません。これがアパーチャ問題です。小さな窓から直線のエッジを見る場合、測定できるのはエッジに垂直な動きだけです。古典的な手法では、これを解決するために2つ目の仮定を加えます。
- Lucas-Kanade法(1981年): 小さなウィンドウ内ではフローが一定であると仮定し、ウィンドウ内の全ピクセルの方程式を最小二乗法で解きます。コーナーのようにウィンドウ内に2方向の勾配がある場所で機能するため、通常は選択した特徴点に対するスパースフローとして実行します。
- Horn-Schunck法(1981年): フローフィールドが画像全体で滑らかであると仮定し、大域的な最適化を解いて、すべてのピクセルに対するデンスフローを生成します。
どちらの仮定も大きな動きには当てはまらないため、実用的な手法では画像ピラミッド上で粗密探索によりフローを推定します。たとえば、フル解像度で16ピクセルの動きは、3段下では2ピクセルの動きになります。
OpenCVは、スパース点向けのピラミッド型Lucas-Kanade法と、デンスフロー向けのGunnar Farnebäckによる2003年の多項式展開アルゴリズムを実装しています。次のコードはランダムなテクスチャを既知の量だけ移動し、デンスFarnebäckフローで動きを復元します。
import cv2
import numpy as np
# A smooth random texture, then the same texture moved 3 px right and 2 px down
rng = np.random.default_rng(0)
texture = cv2.GaussianBlur(rng.random((240, 320)), (0, 0), 3)
frame1 = cv2.normalize(texture, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
frame2 = np.roll(frame1, shift=(2, 3), axis=(0, 1))
# Dense Farneback optical flow: one (dx, dy) displacement vector for every pixel
flow = cv2.calcOpticalFlowFarneback(
frame1, frame2, None, pyr_scale=0.5, levels=3, winsize=15, iterations=3, poly_n=5, poly_sigma=1.2, flags=0
)
print(f"flow field shape: {flow.shape}")
print(f"median motion: dx={np.median(flow[..., 0]):.2f}, dy={np.median(flow[..., 1]):.2f} pixels")flow field shape: (240, 320, 2)とmedian motion: dx=3.00, dy=2.00 pixelsが出力されます。76,800ピクセルそれぞれについて2成分のベクトルが1つずつ得られ、水平3ピクセル、垂直2ピクセルのシフトが復元されます。
ディープラーニング手法#
FlowNetは2015年に、実動画にはグラウンドトゥルースのフローが付属することが少ないため、畳み込みニューラルネットワークが合成学習データからエンドツーエンドでフローを学習できることを示しました。PWC-Netは、古典的手法のピラミッド、ワーピング、コストボリュームの考え方をコンパクトなネットワークに取り入れました。ECCV 2020の最優秀論文賞を受賞したRAFTは、1枚目のフレームのすべてのピクセルと2枚目のフレームのすべてのピクセルを相関ボリュームで比較し、繰り返しの再帰的更新により単一の高解像度フローフィールドを改良します。学習ベースの手法は、古典的手法よりも大きな変位、モーションブラー、テクスチャのない領域に優れています。また、torchvisionには事前学習済みのRAFTモデルが含まれています。精度はMPI SintelやKITTI 2015などのベンチマークで、予測されたフローベクトルと真のフローベクトルのピクセル単位の平均距離である終点誤差(EPE)を使って報告されます。
オプティカルフローと関連用語の違い#
- 物体追跡: 多数のフレームを通じて一意のIDを維持しながら物体全体を追跡します。一方、オプティカルフローは2フレーム間のピクセル単位の動きを記述し、物体については何も認識しません。トラッカーはフローを手掛かりとして利用します。Ultralytics YOLOのtrackモードでは、デフォルトのTrackTrackトラッカーとBoT-SORTがスパースLucas-Kanadeフロー(
gmc_method: sparseOptFlow)でカメラの動きを推定します。半解像度フレームで最大400個のコーナーを追跡し、RANSACでコーナーに回転、スケール、平行移動を当てはめ、その動きに合わせて予測済みのすべてのトラックボックスをシフトしてから、新しい検出結果と照合します。 - ポイント追跡: 2フレーム間のすべてのピクセルの動きを推定するのではなく、オクルージョン中も含め、選択した点を長い動画を通じて追跡します。
- シーンフロー: ステレオデータまたは深度データから推定される、空間内の点の3D運動です。オプティカルフローは、その画像平面への投影です。
- 動画コーデックの動きベクトル: H.264、HEVC、AV1のエンコーダーは、フレームのエンコードに必要なビット数を最小化するよう選択した動きベクトルをブロックごとに保存するため、真の動きとは異なることがよくあります。










