我目前正在尝试在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投影,但我期待的东西有点......更好。
有什么建议吗?
答案 0 :(得分:0)
在fronto-parrallel假设下,视差与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上的简单差异浏览器。