OpenCV-从视差图计算实际距离 [英] OpenCV - compute real distance from disparity map
问题描述
我已经在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倍,如报道的 .我不使用C ++,openCv3,也找不到在您的代码中指定的差异方法SGBM,但我认为可能是同一回事.尝试将每个视差值除以16(同样,对于OpenCV 2.4肯定是正确的,我不知道3.0版本)
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屋!