OpenCV - 从视差图计算真实距离

5

我使用OpenCV 3.1中的StereoSGBM算法计算了视差图。我已经使用小均方根误差校准了立体相机。现在,我想计算视差图中某些点的实际距离(单位:毫米)。

这似乎是一个相对简单的问题。据我所知,我可以简单地使用以下公式:

distance = (baseline * focal length) / disparity

请问我可以在哪里使用矩阵Q(从stereoRectify输出)?Q[2][3] = 焦距,1 / Q [3][2] = 基线。

计算得到的Q矩阵如下:

Q: !!opencv-matrix
   rows: 4
   cols: 4
   dt: d
   data: [ 
    1., 0., 0., -1.5668458938598633e+02, 
    0., 1., 0., -1.1948609733581543e+02, 
    0., 0., 0., 2.3598119491957863e+02, 
    0., 0., 1.6254073321947445e-02, 0. ]

问题在于结果与实际情况不符。例如,对于距离约为2.5米的房间天花板瞄准的相机(其中视差计算正确为12),实际距离被计算为1.3米。对于非常近的物体(例如30厘米),似乎是正确的,但远处的物体非常不准确。在校准过程中,我指定了棋盘方格的确切尺寸(以毫米为单位)。
我按照以下步骤进行:
// compute rectification transforms from calibration data
stereoRectify(M1, D1, M2, D2, Size(FRAME_WIDTH, FRAME_HEIGHT), R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 0.0, Size(FRAME_WIDTH, FRAME_HEIGHT), &roi1, &roi2);

// compute the undistortion and rectification transformation maps for each camera
initUndistortRectifyMap(M1, D1, R1, P1, Size(FRAME_WIDTH, FRAME_HEIGHT), CV_16SC2, map11, map12);
initUndistortRectifyMap(M2, D2, R2, P2, Size(FRAME_WIDTH, FRAME_HEIGHT), CV_16SC2, map21, map22);

...

// get images from camera (VideoCapture)
camLeft.read(_frameLeft);
camRight.read(_frameRight);

// remap images using the calibration data
remap(_frameLeft, frameLeft, map11, map12, INTER_LINEAR);
remap(_frameRight, frameRight, map21, map22, INTER_LINEAR);

// compute disparity from undistorted images
stereo->compute(frameLeft, frameRight, disparityMap);

...

// compute the real-world distance [mm]
float fMaxDistance = static_cast<float>((1. / Q.at<double>(3, 2)) * Q.at<double>(2, 3));

// outputDisparityValue is single 16-bit value from disparityMap
// DISP_SCALE = 16
float fDisparity = outputDisparityValue / (float)StereoMatcher::DISP_SCALE;
float fDistance = fMaxDistance / fDisparity;

我有哪里做错了吗? 提前感谢。

1个回答

1

我知道OpenCV 2.4中用于视差的立体算法(stereoBM,stereoSGBM)将视差作为实际值的16倍给出,正如文档中所述。我不习惯使用C ++,openCV3,也找不到您代码中指定的视差方法SGBM,但我认为它可能是同样的东西。尝试将每个视差值除以16(同样适用于OpenCV 2.4,我不知道3.0版本)


这个已经完成了。我只是在我的帖子中忘记指定float fDisparity = (outputDisparityValue) / (float)StereoMatcher::DISP_SCALE; (DISP_SCALE = 16)。我会添加它的。 - bigmuscle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接