Optical Flow
コンピュータービジョンにおけるオプティカルフローの基礎を確認します。モーションベクトルが動画理解を支え、Ultralytics YOLO26のトラッキングを強化する方法を学びます。
光学フローとは、観測者とシーンの相対的な動きによって生じる、視覚シーン内の物体、表面、エッジの見かけ上の動きのパターンです。コンピュータビジョンの分野では、この概念は動画シーケンス内の時間的ダイナミクスを理解するための基礎となります。連続する2フレーム間のピクセルの移動を分析することで、光学フローアルゴリズムはベクトル場を生成します。各ベクトルは、特定の点における動きの方向と大きさを表します。この低レベルの視覚的手掛かりにより、人工知能システムは画像内に何があるかだけでなく、それがどのように動いているかも認識でき、静止画像の分析と動的な動画理解の間のギャップを埋めます。
光学フローの主要な仕組み#
光学フローの計算は、一般に輝度恒常性の仮定に基づいています。これは、物体上のピクセルの強度が、移動している場合でも、あるフレームから次のフレームへ変わらないと仮定するものです。アルゴリズムはこの原理を利用し、主に次の2つのアプローチで動きベクトルを求めます。
- スパース光学フロー: この手法は、特徴抽出によって検出されたコーナーやエッジなど、特定の一部の特徴について動きベクトルを計算します。Lucas-Kanade法などのアルゴリズムは計算効率に優れており、特定の注目点を追跡できれば十分なリアルタイム推論タスクに適しています。
- 密な光学フロー: このアプローチでは、フレーム内のすべてのピクセルについて動きベクトルを計算します。計算負荷は大幅に高くなりますが、画像セグメンテーションや構造解析など、きめ細かなタスクに不可欠な包括的な動きのマップを提供します。最新のディープラーニングアーキテクチャは、大規模なデータセットから複雑な動きのパターンを学習することで、密なフロー推定において従来の数学的手法を上回ることがよくあります。
光学フローと物体追跡の違い#
光学フローと物体追跡は併用されることが多い一方で、両者を区別することが重要です。光学フローはピクセルの瞬間的な動きを記述する低レベルの処理であり、物体の同一性や継続性を本質的に理解するものではありません。
これに対して、物体追跡は特定の対象を検出し、時間の経過に伴って一貫したIDを割り当てる高レベルのタスクです。Ultralytics YOLO26に統合されているものなどの高度なトラッカーは、通常、物体検出を実行して物体を見つけ、その後、光学フローから導出されることもある動きの手掛かりを使用して、フレーム間の検出結果を関連付けます。光学フローが答えるのは「これらのピクセルは今どのくらい速く動いているか」であるのに対し、追跡が答えるのは「車両5号はどこへ行ったか」です。
実世界での利用例#
ピクセルレベルで動きを推定できることは、幅広い高度なテクノロジーを支えています。
- 自律走行車とロボティクス: 光学フローはビジュアルオドメトリに使用され、ロボットや車両が環境に対する自身の動きを推定できるようにします。また、視野内の物体がどの程度の速さで拡大または移動しているかを分析することで、深度推定や障害物回避にも役立ちます。
- 動画安定化: カメラや編集ソフトウェアは、意図しないカメラの揺れを検出するためにフローベクトルを使用します。この全体的な動きを補正することで、システムは映像をデジタル処理で安定化できます。これは、スマートフォンやアクションカメラなどの最新のコンシューマーエレクトロニクスに標準搭載されている機能です。
- 動作認識: スポーツ分析やセキュリティでは、ピクセルの時間的なフローを分析することで、システムが複雑な人間の動作を識別できるようになります。たとえば、姿勢推定モデルにフローデータを追加することで、手足の動く速度に基づいて、人が歩いているのか走っているのかを区別できます。
- 動画圧縮: MPEG動画符号化などの規格は、動きの推定に大きく依存しています。コーデックは、すべての完全なフレームを保存する代わりに、光学フロー(動きベクトル)とフレーム間の差分(残差)を保存することで、ストリーミングやストレージに必要なファイルサイズを大幅に削減します。
実装例#
次の例では、コンピュータビジョンのエコシステムで標準的に使用されるツールであるOpenCVライブラリを使用して、密な光学フローを計算する方法を示します。このコードスニペットでは、Farnebackアルゴリズムを使用して、連続する2フレーム間のフローマップを生成します。
import cv2
import numpy as np
# Simulate two consecutive frames (replace with actual image paths)
frame1 = np.zeros((100, 100, 3), dtype=np.uint8)
frame2 = np.zeros((100, 100, 3), dtype=np.uint8)
cv2.rectangle(frame1, (20, 20), (40, 40), (255, 255, 255), -1) # Object at pos 1
cv2.rectangle(frame2, (25, 25), (45, 45), (255, 255, 255), -1) # Object moved
# Convert to grayscale for flow calculation
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# Calculate dense optical flow
flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
# Compute magnitude and angle of 2D vectors
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
print(f"Max motion detected: {np.max(mag):.2f} pixels")生のピクセルの動きではなく、物体の継続的な追跡を必要とする高レベルのアプリケーションでは、Ultralytics YOLO11およびYOLO26で利用できる追跡モードを検討してください。これらのモデルは動きの分析の複雑さを抽象化し、交通監視から小売分析まで、さまざまなタスクですぐに利用できる堅牢な物体IDと軌跡を提供します。









