LYCHEE OpenCV 顔追跡

この記事は過去に運用していたブログから移行したものです

はじめに
GR-LYCHEEは昨年末に発売された、RENESAS社のプロトタイピングボードです
MBED対応ボードで、カメラ付き、LCD用コネクタなどがついています
ピンマップはArduino互換で、Arduinoスケッチも書けます
OpenCVも動作させることができ、カスケードファイルを変えれば色々認識させられます
 
ものづくり学園つばめからお借りしてきたので、
顔認識ロボットを作るため、顔の場所を把握し、ロボットに対して
どの方向にいるのか、LCDにウインカーを出すプログラムを作成します
 
測定
まず、実際のロボットはとある場所での屋外自動走行に使う予定ですが
筐体作成前に問題点等を考えるため、ロボット掃除機を使い
一通りの機能を実装して実験することになりました
 
ロボット掃除機iLIFEはリモコン操作ができ、
赤外線リモコンの左右のボタンを押すと
特定の角度回転します。まずはその回転角を測定します
 
ロボット掃除機の上部にレーザーポインターを固定、
何度も繰り返し動作させて、回転先のズレの中心と
初期方向付近のズレの中心との角度を測定します
 
左右それぞれ測定したら、LYCHEEのカメラの視野角との差を求めます
 
 
置き換え
先述した方法で測定したLYCHEEのカメラの視野角と
ロボットの左右1コマンドの角度の差をLCDのピクセルに置き換えます
 
LYCHEEに接続されるLCDは480×272。
電子工作でよく使われる、PSPと同じものです
 
x=240をロボットの正面としたとき、
置き換えの結果は左x=34、右x=446
(OpenCVは左上原点)
 
左右の値と正面との中間はそれぞれ136,343となるので
これを基準にロボットにコマンドを送れば顔を追跡することができます
 
LCDに目安表示
 
GR-LYCHEEをArduinoライクに開発できるIDE4GRでは
C++版OpenCVの構文が使えます。
 
公式サンプルのFaceDetection_Display_LCDは
顔を認識し、位置・サイズに合うよう枠を表示
LCDに映してくれます
 
それに加えて描画関数を使い、LCD上にロボット操作の目安となる
 
1. 左に1コマンド送った時向く方向 (x=34)
2. 1と3の中間線           (x=136)
3. ロボット正面方向         (x=240)
4. 3と4の中間線 (x=343)
5. 右に1コマンド送った時向く方向 (x=446)
 
これらのラインをそれぞれ描画したいと思います。
分かりやすいように、1,3,5は白っぽいグレー、2,4は黒っぽいグレーで描画します
 
cv::line(src, cv::Point(34, 3), cv::Point(34, 269), cv::Scalar(200, 200, 200), 1, 8);
cv::line(src, cv::Point(136, 3), cv::Point(136, 269), cv::Scalar(100, 100, 100), 1, 8);
cv::line(src, cv::Point(240, 3), cv::Point(240, 269), cv::Scalar(200, 200, 200), 1, 8);
cv::line(src, cv::Point(343, 3), cv::Point(343, 269), cv::Scalar(100, 100, 100), 1, 8);
cv::line(src, cv::Point(446, 3), cv::Point(446, 269), cv::Scalar(200, 200, 200), 1, 8);
 
このように線1本に1行のプログラムの追加で簡単に描画ができます。
 
このような感じで書くと、コマンドを送るべき方向にウインカーを出せます。
 
switch(areax){
case 0:
cv::line(src, cv::Point(3, 5), cv::Point(129, 5), cv::Scalar(255, 255, 255), 5, 8);
cv::line(src, cv::Point(3, 267), cv::Point(129, 267), cv::Scalar(255, 255, 255), 5, 8);
break;
case 1:
cv::line(src, cv::Point(143, 5), cv::Point(336, 5), cv::Scalar(255, 255, 255), 5, 8);
cv::line(src, cv::Point(143, 267), cv::Point(336, 267), cv::Scalar(255, 255, 255), 5, 8);
break;
case 2:
cv::line(src, cv::Point(349, 5), cv::Point(477, 5), cv::Scalar(255, 255, 255), 5, 8);
cv::line(src, cv::Point(349, 267), cv::Point(477, 267), cv::Scalar(255, 255, 255), 5, 8);
break;
default:
break;
}
 
 
動作中の様子(外部リンク)

 
顔座標に注意
どうも目安を顔が超えているはずなのに
ウインカーが切り替わらないなーという時の失敗。
 
 
 
FaceDetection_Display_LCDの顔の座標
face_roi.x , face_roi.y は表示される枠左上になっているので
 
int fplus;
fplus = face_roi.width/2;
 
こんな感じで顔のセンターを出さないとでした。
 
 
まとめ
LYCHEEのOpenCVのとっかかりでした
これから複雑な処理、他のマイコンとの連携もさせていきます