OpenCV-从视差图计算实际距离 [英] OpenCV - compute real distance from disparity map

查看:1063
本文介绍了OpenCV-从视差图计算实际距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在OpenCV 3.1中使用StereoSGBM算法计算了视差图.我已经校准了具有较小RMS误差的立体摄像机.现在,我想为视差图中的某些点计算以毫米为单位的实际距离.

I have computed disparity map using StereoSGBM algorithm in OpenCV 3.1. I have calibrated stereo camera with small RMS error. And now I want to compute real distance in mm for some points in disparity map.

这似乎是相对容易的问题.据我了解,我可以简单地使用公式

This seems to be relatively easy problem. From what I understand I can simply use formula

distance = (baseline * focal length) / disparity

在这里我可以使用矩阵Q(stereoRectify的输出). Q [2] [3] =焦距,1/Q [3] [2] =基线.

where I can use matrix Q (output from stereoRectify). Q[2][3] = focal length, 1/Q[3][2] = baseline.

计算出的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 m.对于距离很近的物体(例如30厘米),这似乎是正确的,但距离远的物体却是非常不正确的.在校准过程中,我指定了棋盘格的确切大小(以毫米为单位).

The problem is that the result does not correspond with the reality. For example, for the camera aiming to the room ceiling in distance approx. 2,5 metres (where the disparity is correctly computed as 12), the real distance is computed as 1,3 m. For very close objects (e.g. 30 cm), it seems to be correct, but far objects are very incorrect. During the calibration, I specified the exact size of chessboard square in millimetres.

我完全执行以下操作:

// 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;

我做错了什么吗? 预先感谢.

Is there something I do incorrectly? Thanks in advance.

推荐答案

我知道OpenCV 2.4中用于视差的立体声算法(stereoBM,stereoSGBM)将视差提供为实际值的16倍,如报道的

I know that the stereo algorithms for disparity in OpenCV 2.4 (stereoBM, stereoSGBM) give the disparity as values 16 times greater the real values, as reported in the documentation. I am not used with C++, openCv3 and I don't find the disparity method SGBM specified in your code, but I think it could be the same thing. Try to divide every disparity value by 16 (again, this is surely true for OpenCV 2.4, I don't know 3.0 version)

这篇关于OpenCV-从视差图计算实际距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆