銀の弾丸

プログラミングに関して、いろいろ書き残していければと思っております。

WEBカメラ2台のステレオマッチング結果をリアルタイムに表示する

リアルタイムにステレオマッチングの結果を表示してみました。相変わらず百均カメラ2台で頑張って(謎)います。

最初は前回(100均Webカメラ2台でステレオマッチングやってみた - 銀の弾丸)と同じく、Pythonで書いてみたのですが、出力の可視化処理が遅過ぎまして、C++で書き直し。numpyの使い方次第で速く処理できるのかもしれませんが、まだ自由にやれていないです。

てなことで、貧弱なPCでも秒間30フレームくらいで処理できています。「ナニゴト?」と家族が駆けつけるくらい、ファンがうなりますけど。

実行中画面

f:id:takamints:20141116104503p:plain

上段は、グレースケールに変換したカメラの生画像。左上が右目に相当するカメラの画像で、右上が左目に相当。 カメラの位置関係は、前回の 100均Webカメラ2台でステレオマッチングやってみた - 銀の弾丸の最初の写真と同じです。

左下は、ステレオマッチングの結果行列を可視化したもの。出力行列の仕様をキチンと理解していなかったのですが、中身をざっと覗いて適当に。サイズは入力画像と同じ2次元の行列で、要素は符号ありの16ビットのようでしたので、最大値と最小値を得てから各画素を一次変換して8ビットイメージを作ってみました。今回はStereoSGBMを使用してみましたけど、何が違うのかはわかっていません(適当w)

右下は、左の可視化イメージの過去15枚分の平均画像です。壁の部分の結果が安定しなかったので平均してみました。

ソースコードGitHub

ソースは全部GitHubに置いてます(↓)ので、どうぞご自由に。

github.com

ビルド方法などについてはREADMEを参照してください。

READMEでも書いていますが、上に示した画像のように、縦横に分割された画面や、以降で説明する個々の画像処理は cvImagePipeline(GitHub)というOpenCVを利用した自作ライブラリで行っています。単純な画像処理ルーチンの入力と出力行列をつなぎ、より一連の画像処理を構成できるようにしたものです。以降で説明する処理のほとんどのコードが、このライブラリに依存したものとなっています。

takamints.hatenablog.jp

class StereoBlockMatcher - ステレオマッチングを行うクラス

StereoSGBMでステレオマッチングを行うクラス。左右の入力画像のブロックマッチングを行い、結果を出力します。 マッチングのパラメータはコンストラクタのイニシャライザーでハードコーディングしています。

※ 基本クラスの ImageProcessor は、cvImagePipeline の抽象クラスです。単一、または、複数の入力行列に対して演算を行い、ひとつの行列を出力するように設計されているものです。

※ StereoBlockMatcher は、2つのカメラからの入力画像で、ブロックマッチングを行い、その結果の行列を出力するように実装しています。後段のプロセッサ群で可視化し、画面表示まで行います。

class DisparityVisualizer - ステレオマッチング結果の可視化

ステレオマッチングの出力行列を可視化するクラス。要素の最小値最大値を得てから、8ビットに一次変換しています。 べたっとループを書いちゃってますが、おそらくOpenCVの関数でスマートに書き直せるんじゃないかな。

※ DisparityVisualizer も ImageProcessor からの派生クラスです。StereoBlockMatcherの出力行列を画像に変換しています。

main

cvImagePipelineが提供しているフィルター(ImageProcessor実装クラス)や、上記2つのクラスのインスタンスを生成し、つなぎ合わせて実行しています。

左右のカメラのデバイスインデックスは、ハードコーディングしています。property("deviceIndex", n)というところです。環境に合わせて書き換えてください。