おはよう君需要なし

求不得苦な日々

OpenCV 3.1がリリースされたらしいのでC++でSGBMを試してみる

OpenCVChangeLogによれば、OpenCV3.1において

“Recent advances in edge-aware filtering, improved SGBM stereo algorithm”
 – opencv/calib3d and opencv_contrib/ximgproc (Alexander Bokov, Maksim Shabunin)

らしいので、SGBMを試してみようと思う。

というか、バージョンアップによりstereoSGBMの実行の仕方が変わっているので、各種ハウツーを紹介しているサイトの 情報が今回のバージョンでは使えないので、メモ的な側面が強い。

なお、今回のプログラムはかなり手探りで書いたので、書き方が間違っている・こう書いたほうがスマートだとかいうのは超コメントが欲しい。

ソース

まずはクラスを用意する。StereoSGBM::create関数ってのに変わっていて戸惑った。パラメータは適当である。

int window_size = 3;

int minDisparity = 0;
int numDisparities = 32;
int blockSize = 3;
int P1 = 8 * 3 * window_size * window_size;
int P2 =  32 * 3 * window_size * window_size;
int disp12MaxDiff = 1;
int preFilterCap = 0;
int uniquenessRatio = 10;
int speckleWindowSize = 100;
int speckleRange = 32;

cv::Ptr<cv::StereoSGBM> ssgbm = cv::StereoSGBM::create(
    minDisparity,
    numDisparities,
    blockSize,
    P1,
    P2, disp12MaxDiff,
    preFilterCap,
    uniquenessRatio,
    speckleWindowSize , speckleRange, cv::StereoSGBM::MODE_SGBM);

画像をロードする。あんまり画素数が多いとうまく結果が出ないので適宜cv::pyrDown関数などでダウンサンプリングしてあげたほうが良い。

cv::Mat imgLeft = cv::imread(strImageNameLeft,1);
cv::Mat imgRight = cv::imread(strImageNameRight,1);

結果を格納するためのMatを用意する。stereoSGBMの計算結果はCV_16Sで格納される。

cv::Mat disparity;   //((cv::MatSize)leftImg.size, CV_16S);
ssgbm->compute(imgLeft,imgRight, disparity);

結果を表示する。0~255の値にしてやってグレースケールで表示する。

cv::Mat disparity_map;
double min, max;
cv::minMaxLoc(disparity, &min, &max);
disparity.convertTo(disparity_map, CV_8UC1, 255.0 / (max - min), -255.0 * min / (max - min));
cv::imshow("result", disparity_map);

大体こんな感じだろうか。過去のバージョンと結果を比較できるとよいなぁ。