電気のDIY - Raspberry Pi3でカメラモジュールをOpenCVで使う
新バージョンのRaspberry Pi 純正カメラモジュール V2.1が届いた。
カメラモジュールの画像や動画をOpenCVで処理してみたい!
Webで情報収集をはじめる。相当なページを徘徊した。

先にまとめると
ttp://www.ics.com/blog/raspberry-pi-camera-module などを見てみると、
新しいRASPBIANにはRPi用に開発した公式のV4L2ドライバが含まれているようだ。
このドライバを有効にすると、一般的なLinuxアプリからカメラモジュールを使えるらしい。

検索が下手なだけ!と言われそうだが、タイムリーな情報の選別に苦労した。
ことを始める環境準備に手間取ったので、この時の手順をメモしておく。
  1. カメラモジュールの動作確認。
  2. V4L2ドライバをロードしてmotionのLive Stream Serverの動作を確認。
  3. C++を使ってOpenCVでカメラモジュールの映像をキャプチャーする。

Raspberry Pi3+RASPBIAN JESSIE(2016-03-18リリース)のデスクトップ環境下で
ネットワークの設定、日本語フォントのインストールを済ませ、タイムゾーン・キーボードなど
ロケーションを変更。日本語入力のパッケージをインストール後に
~ $ sudo apt-get update && sudo apt-get upgrade を実行した状態でバックアップした
イメージを使うことにした。

新しいSDメモリにイメージファイルを展開して作業をはじめる。

カメラモジュールの箱を開けて動作確認

Raspberry Pi3 と Camera Module V2.1をフレキケーブルで接続して電源ON。
デスクトップのMenuからカメラを有効にする。
設定変更は再起動をうながされるので再起動。
お決まりのコマンドで確認
~ $ raspistill -o image.jpg
カレントディレクトリに image.jpg が保存される。
~ $ gpicview image.jpg
デストップに静止画を表示して確認。
~ $ raspivid -o video.h264
カレントディレクトリに video.h264 が保存される。
~ $ omxplayer video.h264
ターミナルにはvideo.h264のプロパティが表示されるが再生されない。
お察しの通り、リモートでRPi3を操作しているからだ。
HDMI端子にディスプレイ、USBマウスとキーボードを接続して直接ログインすれば
デスクトップに再生される動画を確認できる。

これでカメラモジュールの動作確認ができた。
主観的には静止画・動画ともクオリティ対コストを考えると、かなりGoodだと感じた。

motionのLive Stream Serverを試す


まず
motionのインストール
~ $ sudo apt-get install motion

続いて
/etc/motion/motion.conf の編集
WAL側には配信しないで、LAN内でストリーミングを確認するだけなので
認証などのセキュリティ関連は設定しなかった。
daemon on ⇨ off
width 320 ⇨ 640
height 240 ⇨ 480
framerate 2 ⇨ 30
output_picture on ⇨ off
ffmpeg_output_movie on ⇨ off
stream_maxrate 1 ⇨ 30
stream_localhost on ⇨ off

WAL側へルーターの壁を超える場合は、セキュリティの設定は必須。

ここでmotionを起動しても
vid_v4lx_start: Failed to open Video device /dev/video0
デバイスを開けないと言われ、ストリーミングは失敗する。

インターフェイスの設定でカメラを有効にするだけでは、V4L2ドライバはロードされないようだ。
lsmodで確認すると、V4L2関連のモジュールはロードされていないことがわかる。
/dev/video0 はマウントされていないので、motionからカメラモジュールを使えない。
V4L2ドライバのロード
~ $ sudo modprobe bcm2835-v4l2
再びlsmodで確認してみると、以下のモジュールがロードされた。
 bcm2835_v4l2
 videobuf2_vmalloc
 videobuf2_memops
 videobuf2_core
 v4l2_common
 videodev
 media

これで /dev/video0 が現れる。
motionの起動
~ $ sudo motion -n
メッセージがターミナル画面を流れ
・・・
vid_v4lx_start: Using V4L2
・・・
motion_init: Started motion-stream server in port 8081.....と表示される。
どうやらストリーミングが開始されたようだ。

Windows10でWebブラウザはChromeを使った。アドレスバーにRPi3のIPアドレスとポート番号を入力
xxx.xxx.xxx.xxx:8081

ブラウザに映像が再生されはじめた。
このネットワーク環境は、RPi3はWiFi(11n/g/b倍速モード)、Windowsは有線(1000Base)のLANで
640×480サイズの映像は、ほんの少しだけ(1秒未満のズレ)遅れているが、リアルタイムと言っても
良いと思う。RPi3の処理能力アップの恩恵も大きいのだろう。スムースな動きの映像が確認できた。
Ctrl+C でmotionを停止する。
USBで接続したWeb Cameraと違い、動きは滑らかな映像だ。
真夏の熱をクリアできれば、高画質なドライブレコーダーとしてすぐに使えると感じた。

modprobeコマンドにより手動でV4L2ドライバをロードしたが、RPi起動時にロードさせるには
/etc/modules に書いておく。たった12文字の1行追加するだけだ。
 bcm2835-v4l2

OpenCVでカメラモジュールの映像をキャプチャーする


いよいよ本題
OpenCVのインストール
apt-getを使うと最新バージョンは無理。取り敢えず当たりをつけたい。
コンパイルとか面倒だし簡単に済ませる。
~ $ sudo apt-get install libopencv-dev
V4L2 APIを使えるようにしておく
Lowレベルなところでカメラモジュールをコントロールするには必要。
自分に使いこなせるのか? 今後、OpenCVと併用することになりそうなのでインストールした。
下記のテストプログラムをコンパイルするだけなら必要ない。
~ $ sudo apt-get install libv4l-dev
OpenCVで映像をキャプチャー

手始めなので、OpenCVでいう"Hollo,World" 的なコードで試してみる。
適当な場所にファイル名を main.cpp として作成。
//テストプログラム
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main(int argc, char* argv[])
{
    Mat mat;
    VideoCapture vcap(0);

    if (!vcap.isOpened())
        return -1;

    while (1) {
        vcap >> mat;
        imshow("camera", mat);
        if (waitKey(10) >= 0) break;
    }
    return 0;
}
単純にカメラモジュールをキャプチャーして、映像を表示するだけのプログラム。

main.cpp 保存したら、コンパイル
~ $ g++ main.cpp -o test -lopencv_core -lopencv_highgui
これでtestという実行ファイルが出来上がる。

テストプログラムの実行
~ $ ./test
キャプチャーされた映像がデスクトップに表示された。
何かキーを押せばプログラムは終了する。

ここをスタート地点にして、OpenCVの検出と認識などの解析に駒を進める準備ができた。

IDEは何がいいのだろう?
Code::Blocksでもインストールしてみようかな。