/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

Raspberry Pi camera moduleを試食してみた

近況

実は数日前まで、大学の研究、仕事、趣味全てに対してやる気が起きず、ただぼーっとTwitterをみてるだけの生活をしていましたが、少し回復してきた現在は本を読んだり、だめげーをしたり、Eject工作をすることになったりと、趣味に対しての活力が復活してきました。

経験上、こういう時は趣味に対するやる気が復活すると、その他のことに対するやる気も復活するので、しばらくは趣味に全力投資します。

本日の内容

さて、しばらく前にRaspberry Piを使ってハードウェアエンコードを行い、その際に「gstreamer関係の技術は、Webカメラにも応用できるのでは」と考えていました。 なぜこんなことを考えたかというと、以前どこかで「Raspberry Piでカメラを扱うには、遅過ぎて実用的ではない」という内容の記事を読んだ事がありまして、そこで指摘されている「遅い」という問題は、ハードウェアアクセラレーションを使うことで改善できるのではないかと考えたからです。

しかし私はWebカメラを1台も持っていなかったため「amazonほしい物リストから送られてきたら検証します」みたいなことを言って、この件は放置していました。

……その数日後、自宅に見覚えの無い宅配物が届きました。最初は冗談で「もしや…組織から送られてきた爆発物か!!!」とかアホなことを考えていましたが、ガワはamazonなのでまあ多分大丈夫だろうと中を開けてみると、このようなものが入っていました。

f:id:tnishinaga:20140604034853j:plain

中身はふぁらお加藤(@PharaohKJ)さんと、達人出版会でお世話になっている高橋征義@takahashim)さんから、amazon贈り物リストから届いた贈り物でした。*1

ふぁらおさん、高橋さん、ありがとうございます!

さて、今回は目的を示した上でそれに必要なモノを頂いたので、本来すぐに目的達成のため動くべきだったのですが、前述のとおり暫くの間 廃人のようなことになっていたためそれができず、今になってやっと動き始めたという次第です。

試食してみる

病み上がりなので今回はとりあえず、Raspberry Pi camera moduleの方を試食して、画面に映像を写す方法を探る程度にします。

情報を探す

何をするにも情報が必要ということで、以下のページを見つけました。

前者はPythonでカメラを扱う方法、後者はvlcやgstreamerを使ってストリーミングサーバーを作る方法の解説です。

gstreamerを使ってカメラの映像を表示してみる

とりあえず後者のリンクを参考に、gstreamerを使って画面上にカメラの映像を表示してみました。

基本的には raspivid コマンドの出力(H.264)を受け取って、それをパース、デコード、videoconvertしてsinkに渡してやればいいみたいです。

xvideosinkを使う

まずは以下のようにxvideosinkを使って表示してみました。

raspivid -n -w 1280 -h 720 -b 4500000 -fps 30 -vf -hf -t 0 -o - | \
gst-launch-1.0 -v fdsrc ! h264parse ! omxh264dec ! videoconvert ! xvideosink

この方法のいいところはSSHのXフォワーディング機能を使って、簡易的なストリーミング再生のようなことができることです。

ただ、Xを通し、SSHとネットワークも経由するので、表示はだいぶのろいです。 10秒ほど遅れてます。とても実用的ではありません。

別の方法を探りましょう。

fdsinkを使う

X経由が遅いなら、フレームバッファに直書きすれば速いのではと考えて実行してみました。

raspivid -n -w 1280 -h 720 -b 4500000 -fps 30 -vf -hf -t 0 -o - | \
gst-launch-1.0 -v fdsrc ! h264parse ! omxh264dec ! videoconvert ! fbdevsink

結果は悪化しました。30秒ほど遅れてます。とても実用的ではありません。

フレームバッファに直書きのほうが遅くなったのは、先ほどの方式はSSHのXフォワーディングより、描画を別のPCで行っていたからだと思います。 たぶん、Raspberry Pi上でxvideosink使って表示したら、同様の結果になるはずです。

eglglessink(Open GL ES vout Sink)を使う

OpenGL ESはRaspberry PiのGPUにも対応していたはずなので、GPUの機能を使って高速に描画が可能なはず…! と考えて実行してみました。

raspivid -n -w 1280 -h 720 -b 4500000 -fps 30 -vf -hf -t 0 -o - | gst-launch-1.0 -v fdsrc ! h264parse ! omxh264dec ! videoconvert ! eglglessink

結果は今までの中で最速。たった4秒ほどの遅れになりました。

そしてこれ以上早くする方法が思いつかないので、手詰まりです。

rasividを使ってカメラの映像を表示してみる

時間を置いて考えなおしてみたところ、そもそもraspivid自体の機能について触れていなかったことに気が付きました。

というわけでhelpをとってみると、どうやらこのコマンド、プレビュー表示ができるみたいです。 *2

というわけで以下のコマンドを実行。

raspivid -f -w 1280 -h 720 -b 4500000 -fps 30 -vf -hf -t 0

タイムラグはなし。これ以上文句のつけようの無いスコアを出しました。

カメラ映像を表示したいだけなら、この方法が一番のようです。

おわりに

とりあえず今日はRaspberry Pi camera moduleを使って、カメラの映像を表示する方法を調べてみました。 今回最速のraspividコマンドは一般的なWebカメラにも使用できるかわからないので、次はその辺りを調べたいと思います。

ある程度調べ終わったら、PythonOpenCVに食わせて、カメラに映った人間の顔を二次元美少女の顔に置き換えるアホなプログラムでもつくろうと思います。

それでは、おやすみなさい。

*1:しかし贈り物は届くまで本人には何も通知されないというのは、ちょっと不便…

*2:gstreamerに食わせるときは-nオプションで抑制してた