Python
OpenCV
機械学習
MachineLearning
dlib

泳いでいる鯉を認識してみる

More than 1 year has passed since last update.

今回は、これまでと趣向を変えて物体認識について取り扱ってみます。

動画の中から任意の個体を認識させて、それを追跡する検証をPythonベースのプログラムで行ってみます。

泳いでいる鯉の認識

今回扱う映像は、泳いでいる鯉の映像です。
Goldfish.gif
(※GIF動画にしたので画像が少々荒いです。)

画面を横切っていく、少し体の大きな赤色の鯉を認識させてみます。
goldfish_tartget.jpg

機械学習ライブラリ「dlib」

これまでのブログでは、scikit-learnを使ってきましたが、今回はdlibという機械学習のライブラリを使ってみます。
オープンソースのC++ベースのライブラリで、Pythonからも使用することができます。

dlibをインストールする場合は、ライブラリのビルドをC++ライブラリのboostを用いて行うので、それも合わせてインストールする必要があります。

ちなみに、Macの場合のインストールコマンドは以下の通り。

brew install boost
brew install boost-python --with-python3
pip install dlib

サンプリング画像と矩形データの作成

動画から対象の鯉が写っているコマをいくつかキャプチャして、学習データを作成していきます。

今回は動画プレイヤーでコマを進めながら20ファイル分、サンプリングしてみます。
sampling.png

サンプリングした画像から、鯉が表示されている矩形をデータ化します。

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キーを押しながらドラッグすると、
赤い矩形範囲がマーキングできます。

imglab.png

全てのサンプリング画像に対して、鯉の部分を矩形でマーキングしたあとに
「File」メニューから「Save」コマンドで保存します。

サンプリング画像と同階層に生成された「training.xml」ファイルには
以下のように、画像ファイルと矩形のbox情報(top,left,width,height)が
記録されていることが確認できます。

xml_shot.png

学習データの作成

先ほどの矩形データの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()

実行すると以下のような映像が出力されます。

detect_frame.gif

サンプリング画像は、鯉が全体で写っている画像で学習させているので、
見切れているときは、青枠は表示されませんね。

ただ、20ファイル程度のサンプリングデータで、動画中の対象物体の認識も
そこそこ出来ているようです。

今回はここまで。


参照動画URL:
https://pixabay.com/videos/id-3613/