読者です 読者をやめる 読者になる 読者になる

cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

Depth From Sequenceのc++コア部分をMSVCで動かしてお勉強

(編集中)

twitterで@ginrou799さんの開発されたiPhoneで奥行き推定するプログラム[1][2]、という、とても興味深い記事が紹介されていました。今日の現実逃避活動は、これのお勉強にしてみます。

iPhoneで、とありますが、コア部分はc++で開発されているそうなので、MSVCでも動かせるはずです。とりあえず、サンプル画像を入力としてデプス出力をとることを目標にしてみます。

ソースコードのダウンロード

[1]からDepthFromSequenceのソースコードをzipでダウンロードしてきて解凍します。c++コア部分だけが必要なので、libフォルダとsampleフォルダを自分のプロジェクトにコピーしてきます。普通にプロジェクトを作って、ビルドして、すんなり動いてくれればいいのですが、何か所かエラーが出ます。これを動くように改造していきます。

環境は、

  • MSVC2012
  • opencv300alpha

です。

修正箇所の羅列(後で整理)

main.cpp

#include <opencv2/opencv.hpp>
using namespace cv;

#include "depth_from_sequence.hpp"
#include "refocus.hpp"

#if _DEBUG
#pragma comment(lib, "E:\\opencv300\\build\\x86\\vc11\\lib\\opencv_world300d.lib")
#else
#pragma comment(lib, "E:\\opencv300\\build\\x86\\vc11\\lib\\opencv_world300.lib")
#endif

main.cpp

CV_LOAD_IMAGE_COLOR->IMREAD_COLOR

main.cpp

// setup ROI
cv::Rect roi;
cv::Size img_size = input_images.front().size();
if ( img_size.width > img_size.height ) {
roi = cv::Rect( (img_size.width-img_size.height)/2, 0, img_size.height, img_size.height);
} else {
roi = cv::Rect( 0, (img_size.height-img_size.width)/2, img_size.width, img_size.width);
}

depth_from_sequence.cpp

CV_RGB2GRAY->cv::COLOR_RGB2GRAY

depth_from_sequence.cpp

if ( track_points.front().size() < 70 ) return FeatureTrackingFailed;

70を変数に置き換えた方がいい

    if ( solver.reprojection_error() >= 1.0 ) return BundleAdjustmentFailed;

1.0を変数に置き換えた方がいい

bundle_adjustment.cpp

double BundleAdjustment::Solver::reprojection_error() {
double error = 0.0;

int n = 0;
for( int i = 0; i < (int)Nc; ++i ) {
for( int j = 0; j < (int)Np; ++j ) {
Point2d reproj = ba_reproject(points[j], camera_params[i] );
double ex = captured[i][j].x - reproj.x, ey = captured[i][j].y - reproj.y;
error += ex*ex + ey*ey;
n++;
}
}

return sqrt(error) / n; //error;
}

 エラーの評価値が発散してしまうので、画像サイズに応じて正規化するように変更。正しいかどうかちょっと不安。

bundle_adjustment.cppのvoid BundleAdjustment::Solver::run_one_step()内

// update valiables
for ( int k = 0, l = 0; k < (int)this->K; ++k ) {
if ( k == 0 ) continue;
if ( k == 1 ) continue;
if ( k == Nc ) continue;
if ( k == 2*Nc ) continue;
if ( k == 3*Nc ) continue;
if ( k == 4*Nc ) continue;
if ( k == 5*Nc ) continue;

if(update.size().area() <= k || solved.size().area() <= l){ /*l++;*/ continue; }
update.at<double>(k) = solved.at<double>(l);
l++;
}

 なぜか、メモリの範囲外を参照することがあるので強制的に排除。後で、慎重に要確認。

for ( int j = 0; j < (int)Np; ++j ) {
if(update.size().area() <= (int)(j + 0*Np + 6*Nc)) continue;
if(update.size().area() <= (int)(j + 1*Np + 6*Nc)) continue;
if(update.size().area() <= (int)(j + 2*Np + 6*Nc)) continue;
points[j].x += update.at<double>( j + 0*Np + 6*Nc );
points[j].y += update.at<double>( j + 1*Np + 6*Nc );
points[j].z += update.at<double>( j + 2*Np + 6*Nc );
}

同じく、参照外のエラーを弾く。

plane_sweep.cpp

Point2d ps_homogenious_point( Matx33d homo_mat, Point2d ref_point) {
Matx31d dst = homo_mat * Matx31d(ref_point.x, ref_point.y, 1.0);
return Point2d( dst(0,0)/dst(2,0), dst(1,0)/dst(2,0) );
//cout << dst(2, 0) << " " << dst(1, 0) << " " << dst(0, 0) << endl;
//return Point2d( dst(0,0)/dst(0,2), dst(0,1)/dst(0,2) );
}

行列の指定が逆で0割が発生するのを直す。

depth_from_sequence.hpp

DepthFromSequence(std::vector<cv::Mat3b> images, cv::Rect roi)
:_images(images),
_roi(roi)
{
// Default value
_min_depth = 500.0;
_fov = 50.0;
_depth_resolution = 127; //20
}

のdepth解像度を大きくしておく。普通のPCならCPUスペックやメモリに余裕があります。

main.cpp

imwrite("depth_smooth.png", (int)(256/_depth_resolution) * dfs._depth_smooth);
imwrite("depth_raw.png", (int)(256/_depth_resolution) * dfs._depth_raw);
imwrite("depth_color.png", dfs._depth_color);
imshow("depth_smooth", (int)(256/_depth_resolution) * dfs._depth_smooth);
imshow("depth_raw", (int)(256/_depth_resolution) * dfs._depth_raw);
imshow("depth_color", dfs._depth_color);

実行結果

サンプルとちょっと違うので、何か間違いがあるかも。。。

f:id:cvl-robot:20141006190628p:plain

f:id:cvl-robot:20141006190610p:plain

f:id:cvl-robot:20141006190636p:plain

 

KLTトラッカーをAKAZEに変えても面白いかもしれませんね。

 

[1] ginrou/DepthFromSequence · GitHub

[2] Depth From Sequence

[3] Seene: Share life in 3D

[4] Research Blog: Lens Blur in the new Google Camera app