OpenCVを使ったPythonでの画像処理について、これまで物体の検出や追跡について触れてきました。
OpenCVの中には追跡アルゴリズムがTracking APIとして色々と用意されています。
ここでは、これらのAPIを使って、webカメラに映された物体の追跡を行ってみようと思います。
Tracking API
PythonでのOpenCVを使った物体のトラッキングには、Boosting、MIL(Multiple Instance Learning)、KCF(Kernelized Correlation Filters)、TLD(Tracking, learning and detection)、MedianFlowといったAPIがあります。
それぞれ、分類器ベースで実行されているものであったり、カーネルを加味したり、学習と検証や時間的な軌跡の差異を測定したりと特徴がありますが、物体の遠近やカメラの前を遮ることがある場合、動きの速さなどで追跡の精度にも一長一短があります。
この中ではおそらくMedianFlowが一番トラッキングとしては使いやすいものだと思いますので、ここではこのMedianFlowを使ってwebカメラでの物体の追跡をやってみたいと思います。
次のようなコードになります。
import cv2
tracker = cv2.TrackerMedianFlow_create()
tracker_name = str(tracker).split()[0][1:]
cap = cv2.VideoCapture(0)
#webカメラの軌道に時間がかかる場合
import time
time.sleep(1)
ret, frame = cap.read()
roi = cv2.selectROI(frame, False)
ret = tracker.init(frame, roi)
while True:
ret, frame = cap.read()
success, roi = tracker.update(frame)
(x,y,w,h) = tuple(map(int,roi))
if success:
p1 = (x, y)
p2 = (x+w, y+h)
cv2.rectangle(frame, p1, p2, (0,255,0), 3)
else :
cv2.putText(frame, "Tracking failed!!", (500,400), cv2.FONT_HERSHEY_SIMPLEX, 1,(0,0,255),3)
cv2.imshow(tracker_name, frame)
k = cv2.waitKey(1) & 0xff
if k == 27 :
break
cap.release()
cv2.destroyAllWindows()
OpenCVのインポートをして、MedeanFlowのAPIを選択しています。ここではcv2.TrackerMedianFlow_create()を使うことになります。tracker_nameの部分は、表示用にAPI名を取り出しているだけです。
cv2.VideoCapture(0)で内臓webカメラに接続して、cv2.capread()で映像の最初のフレームを読み込んでいきます。カメラの起動が遅くて読み込み時にエラーが出る場合は、time.sleep(1)などを入れてみてください。
cv2.selectROI(frame, False)で関心領域を指定します。これをtrackerで初期化しておきます。
while文を使って、キャプチャーを実行して行きます。
新しく画像を読み込み、trackerを更新します。roiの変数は4つのfloat型のタプルなので、それぞれの値を整数に変換しておきます。
if-else文を使って、トラッキングが成功している時に、p1とp2の座標を取得して、ROI部分に緑色の矩形を表示させます。トラッキングが失敗した場合には赤字で「Tracking failed!!」と表示するようにしています。
これをimshow()で表示しています。
[esc]キーが押された時に処理を終了して、ウインドウを閉じる処理はこれまでやってきたことと同じです。
以上のPythonスクリプトをターミナルから実行してみましょう。
最初にカメラで捉えられた静止画が表示されます。
ターミナルには、「Select a ROI and then press SPACE or ENTER button!」と表示されているはずです。
そこで、マウスを使って静止画に映ったもの(例えば自分の顔)を四角で囲みましょう。青の線で囲まれるはずです。これが追跡対象となります。そしたスペースキーやreturnキーを押してみましょう。
すると、カメラで撮影された映像の中に、先ほど指定した部分が緑色の四角で囲まれて追跡できているのがわかります。追跡が失敗すると赤字で「Tracking failed!!」と表示されるはずです。
以上、OpenCVに組み込まれているTracking APIの追跡アルゴリズムを使ってみるコードでした。
ここではMedianFlowを使いましたが、Boosting、MIL、KCF、TLDを使うには、最初のtracker = cv2.TrackerMedianFlow_create()のところを、それぞれcv2.TrackerBoosting_create()、cv2.TrackerMIL_create()、cv2.TrackerKCF_create()、cv2.TrackerTLD_create()に変更して実行してみてください。それぞれのトラッキングの違いを確認してみてください。
Tracking APIを選択して利用するコードに変更
上ではMedianFlowを使ったトラッキングを行いましたが、Boosting、MIL、KCF、TLDを使う為に上のコードをいちいち書き換えるのも手間なので、その都度APIを選択して利用できるように、上のコードを変更してみます。
import cv2
# トラッカーを選択する
def select_tracker():
print("Which Tracker API do you use?")
print("0: Boosting")
print("1: MIL")
print("2: KCF")
print("3: TLD")
print("4: MedianFlow")
choice = input("Please select your tracker number: ")
if choice == '0':
tracker = cv2.TrackerBoosting_create()
if choice == '1':
tracker = cv2.TrackerMIL_create()
if choice == '2':
tracker = cv2.TrackerKCF_create()
if choice == '3':
tracker = cv2.TrackerTLD_create()
if choice == '4':
tracker = cv2.TrackerMedianFlow_create()
return tracker
tracker = select_tracker()
tracker_name = str(tracker).split()[0][1:]
cap = cv2.VideoCapture(0)
import time
time.sleep(1)
ret, frame = cap.read()
roi = cv2.selectROI(frame, False)
ret = tracker.init(frame, roi)
while True:
ret, frame = cap.read()
success, roi = tracker.update(frame)
(x,y,w,h) = tuple(map(int,roi))
if success:
p1 = (x, y)
p2 = (x+w, y+h)
cv2.rectangle(frame, p1, p2, (0,255,0), 3)
else :
cv2.putText(frame, "Tracking failed!!", (500,400), cv2.FONT_HERSHEY_SIMPLEX, 1,(0,0,255),3)
# 実行しているトラッカー名を画面に表示
cv2.putText(frame, tracker_name, (20,600), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0),3)
cv2.imshow(tracker_name, frame)
k = cv2.waitKey(1) & 0xff
if k == 27 :
break
cap.release()
cv2.destroyAllWindows()
先ほどのコードと違う部分だけ触れておきます。
最初にAPIを選択する関数、select_tracker()を定義しています。pirnt()とinput()を使って、APIの選択肢を示して、番号を入力させるようにしています。その選択した番号をif文を使ってAPIの選択をしてtrackerを設定しています。
あとは全て同じで、cv2.putText(frame, tracker_name, (20,600), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0),3)という一文をimshow()の前に追加しています。これで、実行した時に画面左下に実行しているトラッカー名が緑色で表示されるようにしています。
スクリプトを実行するとターミナルに次のように表示されます。
番号でトラッカーを入力してreturnキーを押すと、上と同じような操作でトラッキングをすることができます。トラッカーの違いを確認してみてください。
最後に
OpenCVを使ったPythonでの画像処理について、これまで物体の検出や追跡について触れてきましたが、OpenCVの中には追跡アルゴリズムがTracking APIとして色々と組み込まれています。
物体追跡のアルゴリズムは、Boosting、MIL(Multiple Instance Learning)、KCF(Kernelized Correlation Filters)、TLD(Tracking, learning and detection)、MedianFlowといったAPIがあり、ここではこれらを使ってwebカメラに映された物体の追跡を扱ってみました。