リアルタイムに物体認識できるYOLOですが、最近YOLOv3が登場しました。
これを使って、試しに簡単な動画解析プログラムを組んでみます。
さて、私は、趣味でバイクに乗っていて、ドライブレコーダー代わりに、安価なアクションカメラを付けて、動画を撮影することがあります。
ただ、車載動画は撮影しても、長すぎて全部見返すことはほとんどありません。いいシーンだけ抜き出してくれればなぁと常々思っています。
ところで、バイク同士がすれ違うときに、軽く手を降るなど挨拶する文化があり、YAEH(ヤエー)と呼ばれています。
市街地ではほとんどないですが、ツーリングスポットでお互い集団だと時々ヤエーされたりします。
youtubeには多くのヤエー動画がアップロードされてます。
YOLOを使って、バイクとのすれ違いシーンをうまく切り出すことができれば、「YAEH(っぽいところ)動画」を自動的に作ることができそうです。見返すのも楽しくなりそうですね。
というわけでやっていき。
結局どういうのができるの
すれ違ってない部分も多いですが、バイクとのすれ違いシーンはおおかた抜き出せてるのでは、と思います。
ただ、(私が)全くヤエーしてなくて、もうちょっといいサンプルが必要ですね…
環境
動画から物体認識するので、高性能のGPUは必須です。
それ以外は、特に制約はありませんが参考まで。
OS:Ubuntu 16.04
GPU:GTX1080 (cuda9.1)
メモリ:16GB
動画フォーマット:MOV, 1280*720 60FPS
python3(anaconda3-5.1.0)を使いました。
また、OpenCV, CUDA, cudnnは予めインストールしています。
ちなみにOpenCV3.4.1だとdarknetのmakeできないIssueがあるようで、ハマりました。
OpenCVは3.4.1ではなく、3.4.0を使いましょう。
YOLOのインストール
YOLOは公式のdarknetでの実装を利用します。公式通りなので簡単に。
公式サイトの手順通り、darknetをcloneし、YOLOv3のconfig fileをダウンロードします。
ただし、CPUだと1画像(1フレーム)十数秒~かかるので、動画の場合はCompiling With CUDAを参考に、CUDAとOpenCVを有効にして、makeします。
makeが通り、detectが利用できれば問題ないと思います。
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
pythonからdarknetを利用する
darknetにはpython用のAPIとサンプルコードが用意されています。
- python/darknet.py
- examples/detector-scipy-opencv.py
今回、python3を利用するので、2to3を使い、darknet.pyをpython3で動くようにしておきます。
2to3 python/darknet.py -w
また、python/darknet.py で libdarknet.so をフルパスで指定しておかないとうまく動かないことがあります。darknet.pyの L47-48あたりを修正しておきましょう。
#lib = CDLL("/home/pjreddie/documents/darknet/libdarknet.so", RTLD_GLOBAL)
lib = CDLL("libdarknet.so", RTLD_GLOBAL)
動画解析のコードを書く
サンプルコードを参考に実装していきます。
実装コードはここのgistにあげました。
動画の読み込み/書き込みにはscikit-videoを使っています。
認識は0.18秒/1frame 程度で終わるので、デバッグ用のファイル出力をしなければ、1秒あたり2フレームを処理すると、10分の動画で、大体5分程度で終わります。全フレーム処理すると時間がかかるので間引いて処理しています。
実装では、YOLOで認識したバイク(motorbike)の認識結果をplotlyで可視化しています。
以下は、ある動画を解析した結果で、横軸がフレーム、縦軸がそれぞれのバイクの確率を表しています。
頻繁に1フレームだけバイクが検出されていて、ちょっとノイズが多いですね。より作りこむ場合には、この対策が必要です。
今回は、フレームごとに確率の総和を取り、適当なしきい値(1.8など)より大きい場合に、そのフレームを抜き出して、編集してみます。
すなわち1フレーム上に、複数台のバイクが存在していると、「バイクとすれ違った」と見なしています。
総和をとった結果はこちら。
ちょこちょこ、バイクを2台〜3台程度認識していることがわかります。
作成した結果は、上に上げたとおりです。
うまくいったり、いかなかったりした認識結果のフレームをいくつか参考に載せます。
バイクの認識結果だけを囲って表示しています。
32940フレーム目。遠くの自動車をバイクとして認識してしまっています。
28320フレーム目。自動車をバイクとしている以外は、いい感じ!
29160フレーム目。手前のバイクを認識してないですね… 奥の自動車をバイクとしています。
ざっと結果を見てみたところ、以下のような問題がありました。
- 真後ろ・真正面のバイクを認識できない(見逃す)
- 自動車をバイクと誤認識する(逆も多い)
しきい値を変えたりすることで緩和可能かと思います。
よりよい動画作成には、
- 誤認識(ノイズ)の扱い
- 自動車と認識した場合の対応、
- 認識したフレームの前後のフレームの利用
などが必要です。
もうちょっと作りこむ必要がありますね。
まとめとfeature work
YOLO使って、お手軽に動画解析し、動画を編集・作成するシステムを作りました。
しっかり取れることもありますが、1フレームのみでは、誤認識も多いのでうまく扱う必要がありそうです。
今回は、画像中のバイクの台数を利用して動画を作成しましたが、マスツーリングの場合には前に走っているバイクも含めてしまうので、対象物が迫ってきているのか(相対速度)を判別して「すれ違ったバイク」のみを認識する必要があるでしょう。
また、「ヤエー」そのものも認識したいです。が、体がバイクに隠れるので難易度高そうです。ポーズ推定(GoogleのPoseNetなど)を使ってみるのもありかもしれません。
動画解析サービス、例えば、Google Cloud Video Intelligenceとか、Azure Video Indexerとか、Amazon Rekognition Videoとかバシバシ登場してきてます。これらを用いればもっと簡単に・スケールするものが作れそうです。YOLOv3やTiny-YOLOv3との精度比較もしてみる価値はあると思います。