Python版OpenCVでLucas-Kanade法を実装し、物体追跡(オプティカルフローを計算)する方法をソースコード付きで解説します。
オプティカルフローで物体追跡
オプティカルフローとは、デジタル画像中の物体の動きを「ベクトル」で表したものです。
主に移動物体の検出や、その動作の解析などによく用いられています。
実行例
しかしオプティカルフロー(=物体の移動ベクトル)を一意的に求めることは困難です。
一般的には推定によって動き(ベクトル)を求めます。
オプティカルフローを推定する手法は代表的なモノに「LucasKanade法」や「Horn-Schunk法」があります。
今回は、Shi-Tomasi法で求めた特徴点を「LucasKanade法」で追跡してみます。
【オプティカルフローとは】推定の原理・特徴・計算式
オプティカルフローとは?移動量の推定方法、原理、計算式についてまとめました。
サンプルコード
サンプルプログラムのソースコードです。
サンプルコードの詳細解説
サンプルコードの各部分を詳しく解説します。
1. ライブラリのインポート
import cv2
import numpy as np
- cv2: OpenCVライブラリをインポートします。OpenCVはコンピュータビジョンのための強力なツールセットを提供します。
- numpy: NumPyライブラリをインポートします。NumPyは数値計算を効率的に行うためのライブラリです。
2. ビデオキャプチャーの設定
cap = cv2.VideoCapture("/Users/github/sample/python/opencv/video/input2.mp4")
- cv2.VideoCapture: 指定されたビデオファイルを読み込みます。ここでは、
input2.mp4
というファイルを読み込んでいます。
3. Shi-Tomasi法のパラメータ設定
ft_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)
- maxCorners: 検出する最大の特徴点数を指定します。ここでは最大100個の特徴点を検出します。
- qualityLevel: 特徴点の品質を決めるしきい値です。値が高いほど、品質の高い特徴点のみが選ばれます。
- minDistance: 特徴点間の最小距離を指定します。これにより、近接する特徴点が除外されます。
- blockSize: 特徴点を計算するためのブロックサイズを指定します。
4. Lucas-Kanade法のパラメータ設定
lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
- winSize: オプティカルフローを計算するためのウィンドウサイズを指定します。ここでは15×15ピクセルのウィンドウを使用します。
- maxLevel: ピラミッドのレベル数を指定します。ここでは2レベルのピラミッドを使用します。
- criteria: 探索アルゴリズムの終了条件を指定します。ここでは、10回の反復または0.03の精度に達するまで計算を続けます。
5. 最初のフレームの取得とグレースケール変換
ret, frame = cap.read()
gray1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
- cap.read(): ビデオから最初のフレームを取得します。
- cv2.cvtColor: フレームをグレースケールに変換します。カラー画像をグレースケールにすることで、計算が高速化されます。
6. Shi-Tomasi法で特徴点の検出
ft1 = cv2.goodFeaturesToTrack(gray1, mask=None, **ft_params)
- cv2.goodFeaturesToTrack: Shi-Tomasi法を使用して、グレースケール画像から特徴点を検出します。
7. マスク用の配列を生成
mask = np.zeros_like(frame)
- np.zeros_like: フレームと同じサイズのゼロ配列(黒い画像)を生成します。これは特徴点の軌跡を描画するために使用されます。
8. フレームごとの処理
while(cap.isOpened()):
ret, frame = cap.read()
gray2 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ft2, status, err = cv2.calcOpticalFlowPyrLK(gray1, gray2, ft1, None, **lk_params)
good1 = ft1[status == 1]
good2 = ft2[status == 1]
for i, (pt2, pt1) in enumerate(zip(good2, good1)):
x1, y1 = pt1.ravel()
x2, y2 = pt2.ravel()
mask = cv2.line(mask, (x2, y2), (x1, y1), [0, 0, 200], 2)
frame = cv2.circle(frame, (x2, y2), 5, [0, 0, 200], -1)
img = cv2.add(frame, mask)
cv2.imshow('mask', img)
gray1 = gray2.copy()
ft1 = good2.reshape(-1, 1, 2)
if cv2.waitKey(30) & 0xFF == ord('q'):
break
- cap.isOpened(): ビデオキャプチャーが開いているかを確認します。
- cap.read(): 次のフレームを取得します。
- cv2.cvtColor: フレームをグレースケールに変換します。
- cv2.calcOpticalFlowPyrLK: Lucas-Kanade法を使用して、前のフレームと現在のフレーム間の特徴点のオプティカルフローを計算します。
- status: 特徴点が追跡されたかどうかを示すステータス配列です。
- good1とgood2: 追跡された特徴点の座標を取得します。
- cv2.line: 特徴点の軌跡をマスクに描画します。
- cv2.circle: 現在のフレームに特徴点を描画します。
- cv2.add: フレームとマスクを合成します。
- cv2.imshow: 合成画像をウィンドウに表示します。
- cv2.waitKey(30): 30ミリ秒待機し、’q’キーが押されたらループを終了します。
9. 終了処理
cv2.destroyAllWindows()
cap.release()
- cv2.destroyAllWindows: すべてのウィンドウを閉じます。
- cap.release: ビデオキャプチャーを解放します。
【Python版OpenCV超入門】使い方とサンプルコードを解説
Python版OpenCVで画像処理プログラミングを行う方法を入門者向けにソースコード付きで解説するページです。
コメント