【问题标题】:Using OpenCV to generate 3d points (assuming frontal parallel configuration)使用 OpenCV 生成 3d 点(假设正面平行配置)
【发布时间】:2012-07-09 13:08:58
【问题描述】:

我目前正在尝试在 OpenCV 中生成给定立体图像对的 3D 点。据我所知,这已经做了很多。

我知道立体声设置的外在参数,我将假设它是正面平行配置(真的,还不错!)。我知道焦距、基线,并且我将假设主点为图像的中心(我知道,我知道...)。

我使用 StereoSGBM 计算了一个伪像样的视差图,并按照 O'Reilly 的 Learning OpenCV 书对 Q 矩阵进行了手动编码,其中指定:

Q = [ 1 0 0      -c_x
      0 1 0      -c_y
      0 0 0      f
      0 0 -1/T_x (c_x - c_x')/T_x ]

我认为 (c_x, c_y) 是主点(我在图像坐标中指定),f 是焦距(我用 mm 描述),T_x 是两个相机或基线之间的平移(我也在 mm 中描述过)。

int type = CV_STEREO_BM_BASIC;
double rescx = 0.25, rescy = 0.25;
Mat disparity, vdisparity, depthMap;

Mat frame1 = imread( "C:\\Users\\Administrator\\Desktop\\Flow\\IMG137.jpg", CV_LOAD_IMAGE_GRAYSCALE );
Mat frame1L = frame1( Range( 0, frame1.rows ), Range( 0, frame1.cols/2 ));
Mat frame1R = frame1( Range( 0, frame1.rows ), Range( frame1.cols/2, frame1.cols ));

resize( frame1L, frame1L, Size(), rescx, rescy );
resize( frame1R, frame1R, Size(), rescx, rescy );

int preFilterSize = 9, preFilterCap = 32, disparityRange = 4;
int minDisparity = 2, textureThreshold = 12, uniquenessRatio = 3;
int windowSize = 21, smoothP1 = 0, smoothP2 = 0, dispMaxDiff = 32;
int speckleRange = 0, speckleWindowSize = 0;

bool dynamicP = false;

StereoSGBM stereo( minDisparity*-16, disparityRange*16, windowSize,
    smoothP1, smoothP2, dispMaxDiff,
    preFilterCap, uniquenessRatio,
    speckleRange*16, speckleWindowSize, dynamicP );

stereo( frame1L, frame1R, disparity );

double m1[3][3] = { { 46, 0, frame1L.cols/2 }, { 0, 46, frame1L.rows/2 }, { 0, 0, 1 } };
double t1[3] = { 65, 0, 0 };
double q[4][4] = {{ 1, 0, 0, -frame1L.cols/2.0 }, { 0, 1, 0, -frame1L.rows/2.0 }, { 0, 0, 0, 46 }, { 0, 0, -1.0/65, 0 }};
Mat cm1( 3, 3, CV_64F, m1), cm2( 3, 3, CV_64F, m1), T( 3, 1, CV_64F, t1 );
Mat R1, R2, P1, P2;
Mat Q( 4, 4, CV_64F, q );

//stereoRectify( cm1, Mat::zeros( 5, 1, CV_64F ), cm2, Mat::zeros( 5, 1, CV_64F ),  frame1L.size(), Mat::eye( 3, 3, CV_64F ), T, R1, R2, P1, P2, Q ); 

normalize( disparity, vdisparity, 0, 256, NORM_MINMAX );
//convertScaleAbs( disparity, disparity, 1/16.0 );
reprojectImageTo3D( disparity, depthMap, Q, true );
imshow( "Disparity", vdisparity );
imshow( "3D", depthMap );

因此,我将来自 StereoSGBM 的结果视差图和 Q 矩阵提供给 3D 点,然后将其写入 ply 文件。

但结果是这样的:http://i.stack.imgur.com/7eH9V.png

看起来很有趣,但不是我需要的:(。我在网上看到,将视差图除以 16 后得到了更好的结果,而且确实看起来稍微好一些(实际上看起来像是有一台相机拍摄的!)。

如果你有兴趣,这是我的视差图:http://i.stack.imgur.com/lNPkO.png

我知道如果没有校准,它看起来几乎不会像最好的 3D 投影,但我期待一些……更好的东西。

有什么建议吗?

【问题讨论】:

    标签: opencv 3d depth


    【解决方案1】:

    在fronto-parallel假设下,视差与3D深度的关系为:d = f*T/Z,其中d是视差,f是焦距,T是基线,Z是3D 深度。如果将图像中心作为主点,则确定 3D 坐标系。那么对于一个像素(px,py),它的3D坐标(X, Y, Z)是:

    X = (px-cx)*Z/f, Y = (py- cy)*Z/f, Z = f*T/d,

    其中cx, cy是图像中心的像素坐标。

    您的视差图看起来不错,可以生成合理的 3D 点云。

    github 上的简单视差浏览器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 2012-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 2013-12-22
      • 1970-01-01
      相关资源
      最近更新 更多