Intel Edisonでステレオカメラを作る


Pocket

以前EdisonでOV7670モジュールを動かしましたが、折角なのでステレオカメラを作ってみました。
『Intel® EdisonにOV7670カメラモジュールを繋げる』

そして、ステレオカメラから取得できる視差画像から、OpenCVを利用して奥行き情報を取得したいと思います。

 

回路作り

基本的には、OV7670モジュールをそれぞれEdisonに接続しただけですが、端子節約のため下記3端子は共有するようにしました。
・OE
・RRST
・RCLK

ピンアサインや回路の引き回しなどは、表計算ソフトを使って描いていきます。
(なんか便利な設計ツールないかな…)
回路設計

後はひたすら半田付けです。
ステレオカメラ

そして、ケースなんかを3Dプリンターで作ったりして完成したのがこちらです。
ステレオカメラ+ケース

カメラ間の距離は44mm(適当に決めた)で、取得できる画像は下記のようになります。
ステレオ写真
(後の処理がしやすいようにグレースケールに変換しています。)

 

奥行き情報の取得

2枚の画像からの奥行き情報取得は、OpenCVのStereoSGBMを使用しました。

/**
 * 奥行き情報を取得する
 * @param dist 奥行きマップの出力先
 * @param left 左画像
 * @param right 右画像
 */
void createDepthMap(Mat dist, Mat left, Mat right) {
  Mat result = Mat(info.rows, info.cols, CV_16S);
  StereoSGBM sgbm = StereoSGBM(0, 16*3, 21);
  sgbm.speckleWindowSize = 200;
  sgbm.speckleRange = 32;

  sgbm.operator()(left, right, result);

  double minVal; double maxVal;
  minMaxLoc(result, &minVal, &maxVal);
  result.convertTo(dist, CV_8UC1, 255/(maxVal-minVal));
  equalizeHist(dist, dist);
}

9行目:

StereoSGBMのパラメータは、
minDisparity : 最小視差値。特別理由がなければ0。
numDisparities : 最大視差値と最小視差値の差。16の倍数でないといけない。
blockSize : 比較するブロックサイズ。一般的には3〜11が推奨。
 

10行目:

speckleWindowSize : ノイズを除去して視差値をスムーズにするフィルタ。0にすると適用しない。50〜500の範囲で使用する。
 

11行目:

speckleRange : フィルタをかける際の隣同士の最大視差値?通常は1か2がいい。
 

 

結果

奥行き画像
カメラから取得でいる画像の解像度は320*240です。

まぁ…なんとなくは取れているかなといった具合です。
やはりキネクトみたいには行きませんね。(あっちは赤外線プロジェクション方式ですが)

普通はキャリブレーションを行うみたいで、今回それを端折ったのが精度がでない原因の1つかもしれません。
(キャリブレーションはチェス盤用意したり若干めんどくさいようなので…)

 

パターンマッチングでもやってみる

StereoSGBMを使用せずにパターンマッチングでも試してみました。
24*24サイズでパターンマッチした座標のズレを検出しています。

結果

パターンマッチ
パターンマッチ2

こちらもサイズやしきい値などを変えて何パターンか試してみましたが…いまいちかな。

今回試したのはここまで。
 

あとがき

カメラモジュールを2つ使ってとりあえず試してみた程度の内容ですが、一応成功かなと思ってます。
精度が出ないのは残念でしたが、まったくステレオカメラの知識がなくても試せてしまうのはOpenCVのおかげですね。
今度はもっと精度がだせるよう、ちゃんと勉強してからリベンジしたいと思います。

ではでは〜。
 
 

Leave a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です