はじめに
OpenCV(Open Source Computer Vision Library)はBSDライセンスの映像/画像処理ライブラリ集です。画像のフィルタ処理、テンプレートマッチング、物体認識、映像解析、機械学習などのアルゴリズムが多数用意されています。
OpenCVを使った動体追跡の例 (OpenCV Google Summer of Code 2015)
https://www.youtube.com/watch?v=OUbUFn71S4s
インストールと簡単な使い方はこちら
OpenCV 3(core + contrib)をPython 3の環境にインストール&OpenCV 2とOpenCV 3の違い&簡単な動作チェック
静止画像のフィルター処理についてはこちら
OpenCVでエッジ検出してみる
OpenCVで各種フィルター処理をする(グラディエント、ハイパス、ラプラシアン、ガウシアン)
OpenCVで特徴点を抽出する(AgastFeature, FAST, GFTT, MSER, AKAZE, BRISK, KAZE, ORB, SimpleBlob)
動画ファイルの処理についてはこちら
OpenCVで動画をリアルタイムに変換してみる
OpenCVでWebカメラ/ビデオカメラの動画をリアルタイムに変換してみる
今回は、OpenCVを使ってオプティカルフローをリアルタイムに描画してみます。
オプティカルフロー
オプティカルフローとは、動画において、特徴点のフレームとフレームの差分(ベクトル)を表現する方法です。フレームレートは、通常一定なので、特徴点の速度を表現しているとも言えます。
計算方法は、テンプレートマッチングを用いる方法や特徴点/特徴量を用いる方法があります。
今回は、特徴点を用いてオプティカルフローを描画してみます。流れは以下のようになります。
- 前のフレームに対して特徴点を検出します。今回は、Shi-Tomashiの方法を用いて特徴点を検出します。
cv2.goodFeaturesToTrack() を利用します。 - 前フレーム内の特徴点のオプティカルフローを、前フレーム、次フレームの情報を用いて、画像ピラミッド型Lucas-Kanade法で計算します。
cv2.calcOpticalFlowPyrLK() を利用します。 - フレームにオプティカルフローを描画します。
- 2と3を繰り返します。
プログラム
-
動作環境
- python: 3.5.1
- OpenCV: 3.1.0
-
動画データ
OpenCVに付属しているサンプル動画を利用しました。
OpenCV\opencv\sources\samples\data\768x576.avi
import numpy as np
import cv2
cap = cv2.VideoCapture('768x576.avi')
# Shi-Tomasiのコーナー検出パラメータ
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
# Lucas-Kanade法のパラメータ
lk_params = dict( winSize = (15,15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# ランダムに色を100個生成(値0~255の範囲で100行3列のランダムなndarrayを生成)
color = np.random.randint(0, 255, (100, 3))
# 最初のフレームの処理
end_flag, frame = cap.read()
gray_prev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
feature_prev = cv2.goodFeaturesToTrack(gray_prev, mask = None, **feature_params)
mask = np.zeros_like(frame)
while(end_flag):
# グレースケールに変換
gray_next = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# オプティカルフロー検出
feature_next, status, err = cv2.calcOpticalFlowPyrLK(gray_prev, gray_next, feature_prev, None, **lk_params)
# オプティカルフローを検出した特徴点を選別(0:検出せず、1:検出した)
good_prev = feature_prev[status == 1]
good_next = feature_next[status == 1]
# オプティカルフローを描画
for i, (next_point, prev_point) in enumerate(zip(good_next, good_prev)):
prev_x, prev_y = prev_point.ravel()
next_x, next_y = next_point.ravel()
mask = cv2.line(mask, (next_x, next_y), (prev_x, prev_y), color[i].tolist(), 2)
frame = cv2.circle(frame, (next_x, next_y), 5, color[i].tolist(), -1)
img = cv2.add(frame, mask)
# ウィンドウに表示
cv2.imshow('window', img)
# ESCキー押下で終了
if cv2.waitKey(30) & 0xff == 27:
break
# 次のフレーム、ポイントの準備
gray_prev = gray_next.copy()
feature_prev = good_next.reshape(-1, 1, 2)
end_flag, frame = cap.read()
# 終了処理
cv2.destroyAllWindows()
cap.release()
OpenCVなら、特徴点の抽出、オプティカルフローの計算ともに、メソッドを1個呼ぶだけです。
なんて便利な世の中なんでしょう(^^;)
実行結果
実行すると、リアルタイムにオプティカルフローが描画されます。