我正在尝试使用以下 OpenCV 函数消除一对相机的输出失真:
cv::stereoCalibrate(object_points, image_points_left, image_points_right,cameraMatrixLeft, distCoeffsLeft, cameraMatrixRight, distCoeffsRight,cv::Size(sensor_width, sensor_height),R, T, E, F);
cv::stereoRectify(cameraMatrixLeft, distCoeffsLeft, cameraMatrixRight, distCoeffsRight, cv::Size(sensor_width, sensor_height), R, T, R1, R2, P1, P2, Q);
cv::undistortPoints(src_left, dst_left, cameraMatrixLeft, distCoeffsLeft, R1, P1);
cv::undistortPoints(src_right, dst_right, cameraMatrixRight, distCoeffsRight, R2, P2);
据我了解,函数 cv::undistortPoints
还应该根据我的立体相机设置使用矩阵 R1
、R2
、P1
和 P2
校正输出,即设置平行于图像 y 轴的对极线并裁剪图像。
这是正确的吗?
然而,在src_left
和src_right
中的点上执行的映射是“倾斜的”,即未失真的输出图像是倾斜的,在边界上留下空白(特别是在图像的一半角上)。我相信这种倾斜来自旋转矩阵 R1
和 R2
,并且对应于围绕 z 轴的旋转。
现在这是我的问题:
- 为什么(校正后的)输出图像没有填满整个图像空间?
最佳答案
在校正和去畸变过程中,图像可以根据立体相机的方向进行平移和/或旋转。
显然,如果您保留转换图像的原始分辨率 - 您将丢失边界周围的一些信息。例如。考虑到没有平移,但您必须将其中一张图像顺时针旋转 45 度并使用相同的分辨率 - 角将是“空白”。
常见的解决方案是找到一个最大的“内切”矩形并将其放大到原始分辨率。
您可以为此使用 initUndistortRectifyMap
而不是 undistortPoints
。
对于您的 stereoRectify
调用,对 initUndistortRectifyMap
的调用如下所示:
- 左:
initUndistortRectifyMap(cameraMatrixLeft, distCoeffsLeft, R1, P1, cv::Size(sensor_width, sensor_height), CV_32FC1, map_left_1, map_left_2);
- 右:
initUndistortRectifyMap(cameraMatrixRight, distCoeffsRight, R2, P2, cv::Size(sensor_width, sensor_height), CV_32FC1, map_right_1, map_right_2);
这将为您提供调用 remap
的 map :
remap(left, left_rectified, map_left_1, map_left_2, INTER_LINEAR, BORDER_CONSTANT);
remap(right, right_rectified, map_right_1, map_right_2, INTER_LINEAR, BORDER_CONSTANT);
关于c++ - OpenCV 立体校准旋转矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26860635/