我已经在OpenCV 3.1中使用StereoSGBM算法计算了视差图。我已经校准了具有较小RMS误差的立体摄像机。现在,我想为视差图中的某些点计算以毫米为单位的实际距离。
这似乎是相对容易的问题。据我了解,我可以简单地使用公式
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 m。对于距离很近的物体(例如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;
我有做错什么吗?
提前致谢。
最佳答案
我知道OpenCV 2.4中用于视差的立体算法(stereoBM,stereoSGBM)将视差值提供为实际值的16倍,如in the documentation所报道。我不使用C++,openCv3,也找不到在您的代码中指定的差异方法SGBM,但我认为可能是同一回事。尝试将每个视差值除以16(同样,对于OpenCV 2.4肯定是正确的,我不知道3.0版本)
关于c++ - OpenCV-从视差图计算实际距离,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40905380/