hogehoge, world.

米国カリフォルニアのソフトウェアエンジニアがIT・自転車・音楽・天体写真・語学などについて書く予定。

Neural Compute Stick 2でリアルタイムオブジェクト検出 (3) ~ ドローンのFPVカメラ接続

前回MobileNet SSDという高速オブジェクト検出モデルの使い方がわかったので、これにドローンのFPVカメラ画像を食わせてみよう。結論を先に言うと、こんな↓感じでリアルタイムオブジェクト検出が実現できた。

youtu.be

この動画は機材の関係でNCS2を使わずCPUで計算したもので、またプログラム的な手抜きにより本来出せるフレームレートよりも落ちているので、ちゃんとやればもっと速くなるはずである。

ドローンへの接続

使っているドローンはParrotのMamboである。約一年前に自動着陸制御をやってみたくて買ったのだが、対地カメラの映像がリアルタイムで取れなくてお蔵入りになっていた。FPVカメラはオプションで、こちらはリアルタイムで行けるので、自分で追試したい人はFPVカメラ付きを買うべし。 

Parrot MinidoroneMAMBO FPV PACK(ミニドローンマンボFPV) PF727046

Parrot MinidoroneMAMBO FPV PACK(ミニドローンマンボFPV) PF727046

 

Parrotのドローンはメーカー公式のSDKオープンソースPythonライブラリでPCから制御することができる。そういえば自分でこんなこと↓やってたっけ。忘れてた。

今回はドローンを操作したいわけではなくカメラ映像へのアクセスが必要なのだが、以前使っていたPythonライブラリの後継が出ていたのでこれを調べてみる。

GitHub - amymcgovern/pyparrot: Python interface for Parrot Drones

このコードを読んでみると…あれれ?MamboのFPVカメラがWiFiアクセスポイントになるところまでは知ってたが、そこにつなぐと rtsp://192.168.99.1/media/stream2 で直接映像ストリームが見えるらしい?まじかよ、とPCに追加のWiFiドングルを挿してMamboに接続し、

ffplay rtsp://192.168.99.1/media/stream2

と打ち込んでみたら、おおすげえ。本当にカメラ映像が出た。道理で飛ばしてもいないのにドローンが爆熱になるわけだ(笑)。パケット落ちで映像がよく乱れるのもそれっぽい。

じゃあオブジェクト検出器にこのURLを渡せば楽勝じゃね?と前回のコマンドを使って

mobilenet-ssd-myriad.sh -i rtsp://192.168.99.1/media/stream2

とやってみたところ、一応ストリームは読み込もうとするのだが数フレームで止まってしまった。ストリームのパケット落ちをOpenCVのVideoCaptureが無視しきれずこけているように見える。

ともあれこれで取っ掛かりは掴めたと言える。

FFmpegによる映像ストリームのクリーンアップ

ドローンからの映像ストリームをFFmpegのメディアサーバに食わせて再配信し、それをオブジェクト検出器から食ってみたらどうだろう?とやってみた。かなり適当だが設定ファイルをここに公開してみる。後述の理由によりフレームレートを10FPSまで落とそうとしたのだが、どうも意図通り動いていないように見えるので、これが正しいと思わないように。

  • ffserver.confにFeedとStream を定義する。Feedの方でバッファサイズを、Streamの方でURL・エンコード方式・画像サイズ・フレームレート等を適当に指定する。
  • 上記設定を食わせてメディアサーバを起動する。(ffserver.sh)
  • ffmpegコマンドでドローンの映像ストリームをフィードする。(feeder.sh)

こうするとhttp://localhost:8090/test.flvに再エンコードされたストリームが見えるようになるので、

mobilenet-ssd-myriad.sh -i http://localhost:8090/test.flv

と叩くと、ようやくドローンの画像をオブジェクト検出器に通せるようになった。

フレームレート調製

ただしこのままだとひとつ難がある。このサンプルのオブジェクト検出器はストリームからフレームを一枚一枚順番に取って処理するよう作られていて、検出処理速度がストリームのフレームレートより遅いと、検出結果の方がどんどん遅れていってリアルタイムにならないのだ。ドローンを飛ばしながらオブジェクト検出というユースケースには使えない。

最新フレーム以外は読み飛ばすようにサンプルコードを修正すればよいのだが、ちょっとめんどくさいので、フレームレートを検出処理速度以下まで落とすアプローチを取ることにした。FFmpegの側で10FPSくらいに落とせばよいはずだが、どうもうまく行かなかったので、サンプルコードの方に常に一定数のフレーム数を読み飛ばす(数フレームに一回だけ検出処理を実行する)手抜きコードを追加してみた。

これで一応リアルタイムっぽい(遅延が一定で増大しない)動きになってくれた。ただ最悪ケースに合わせて読み飛ばし数を設定するので、全体としては本来可能なフレームレートより絞ることになる。ちゃんと最新フレーム以外読み飛ばす処理を実装すればもう少し滑らかに動くはずである。

実際にドローンを飛ばしてみる

これをドローンを実際に飛ばしながらやってみたのが冒頭の動画である。ドローンを飛ばせる部屋の都合で別のラップトップPCを使ったのだが、こいつにNCS2をうまく認識させることができず、やむなくCPUでの処理になっている。NCS2を使えば同等の結果がもう少し高速・滑らかに得られると考えられる。

検出結果はなかなかで、chair, diningtable, tvmonitorなどしっかり認識されている。暖炉がtvmonitorだったりくまのぬいぐるみがpersonだったりするのはご愛敬。

これなら人に向かって自動的に飛んでいく人なつっこいが危険なドローンくらい簡単に作れそうだ。今度やってみよう。

次回に続く。