今回は、これまでと趣向を変えて物体認識について取り扱ってみます。
動画の中から任意の個体を認識させて、それを追跡する検証をPythonベースのプログラムで行ってみます。
泳いでいる鯉の認識
今回扱う映像は、泳いでいる鯉の映像です。
(※GIF動画にしたので画像が少々荒いです。)
画面を横切っていく、少し体の大きな赤色の鯉を認識させてみます。
機械学習ライブラリ「dlib」
これまでのブログでは、scikit-learnを使ってきましたが、今回はdlibという機械学習のライブラリを使ってみます。
オープンソースのC++ベースのライブラリで、Pythonからも使用することができます。
dlibをインストールする場合は、ライブラリのビルドをC++ライブラリのboostを用いて行うので、それも合わせてインストールする必要があります。
ちなみに、Macの場合のインストールコマンドは以下の通り。
brew install boost
brew install boost-python --with-python3
pip install dlib
サンプリング画像と矩形データの作成
動画から対象の鯉が写っているコマをいくつかキャプチャして、学習データを作成していきます。
今回は動画プレイヤーでコマを進めながら20ファイル分、サンプリングしてみます。
サンプリングした画像から、鯉が表示されている矩形をデータ化します。
dlibに矩形データを作成する、imglabというGUIツールが用意されていますので、それを使います。
矩形データはxml形式のファイルで生成されます。
今回は、training.xmlというファイルにしましょう。
サンプリング画像を内包するディレクトリで、以下のコマンドを
実行します。
サンプル画像はPNGファイルで、「IMG_01.png」のような連番で
用意しておきます。
~/dlib/tools/imglab/build/imglab training.xml
~/dlib/tools/imglab/build/imglab -c training.xml IMG_*.png
以下のような、GUIのウィンドウが表示されます。
各画像ファイルに対して、Shiftキーを押しながらドラッグすると、
赤い矩形範囲がマーキングできます。
全てのサンプリング画像に対して、鯉の部分を矩形でマーキングしたあとに
「File」メニューから「Save」コマンドで保存します。
サンプリング画像と同階層に生成された「training.xml」ファイルには
以下のように、画像ファイルと矩形のbox情報(top,left,width,height)が
記録されていることが確認できます。
学習データの作成
先ほどの矩形データのxmlファイルで、学習データを作成していきます。
dlibのsimple_object_detectorを用いて認識を行うため、
それ用の学習データを用意します。
pythonで以下のコードで「detector.svm」という学習データを
作成しています。
import dlib
# 学習用のオプション変数の生成.
options = dlib.simple_object_detector_training_options()
# 認識はSVMアルゴリズムを使っている。それのコストパラメータを設定.
options.C = 3
# 学習処理を行うときの実行スレッドの数.
options.num_threads = 8
# 左右反転のイメージは生成しない(鯉が一方向に進むだけなので)
options.add_left_right_image_flips = False
# 学習処理の経過を出力する(ターミナルで確認可能)
options.be_verbose = True
# 矩形のXMLデータから学習データを作成.
dlib.train_simple_object_detector("training.xml", "detector.svm", options)
# 学習データから認識オブジェクトの作成.
detector = dlib.simple_object_detector("detector.svm")
認識アルゴリズムはサポートベクターマシン(SVM)を用いています。
options.CはSVMのコストパラメータと呼ばれるもので、値が大きいほど誤認識に対して厳しく判定するようになります。
動画の鯉を認識させてみる
上記で生成した鯉の認識オブジェクトを用いて、実際に動画中の鯉を認識させてみます。
動画の読み込みはOpenCVを用いて行います。
動画はmp4形式のファイルで扱っています。
OpenCVのVideoCaptureに動画ファイルを指定してやれば、簡単に動画のフレームを読み込み、解析処理を行うことができます。
以下のプログラムでは、VideoCaptureで読み込んだフレーム画像に対して、dlibの認識オブジェクト(detector)を通して、鯉の判定矩形を取得しています。
それをフレームに青枠で書き込んで、再生ウィンドウに出力しています。
import cv2
# 鯉の動画(input.mp4)をキャプチャーする.
cap = cv2.VideoCapture("input.mp4")
while(cap.isOpened()):
#キャプチャーで動画のフレームを読み込む.
ret, frame = cap.read()
#フレームが出来なかった場合(動画が終了した場合など)はループを抜ける.
if ret == False:
break
# 読み込んだフレームを鯉の矩形認識処理に通す.
dets = detector(frame)
# 返された矩形の数分、フレームに青色で矩形を書き込む.
for det in dets:
cv2.rectangle(frame, (det.left(), det.top()), (det.right(), det.bottom()), (255, 0, 0), 3)
# 出力ウィンドウにフレームを表示する.
cv2.imshow("frame", frame)
if cv2.waitKey(1) == 27: # ESCキーで終了
break
# キャプチャーの解放.
cap.release()
# 出力ウィンドウの破棄.
cv2.destroyAllWindows()
実行すると以下のような映像が出力されます。
サンプリング画像は、鯉が全体で写っている画像で学習させているので、
見切れているときは、青枠は表示されませんね。
ただ、20ファイル程度のサンプリングデータで、動画中の対象物体の認識も
そこそこ出来ているようです。
今回はここまで。
参照動画URL:
https://pixabay.com/videos/id-3613/