双目相机标定在OpenCV中提供了示例程序,本来是非常简单的事情,但是当标定自己的双目相机的时候却发现同样的程序最后标出的结果却很差劲,直接表现就是最后进行行对齐的时候获得图像根本不能看,所以从新梳理了双目标定的过程,并给出了对双目标定结果的应用,比如在ORB-SLAM中,双目模式是需要进行双目图像矫正和对齐的,这时就可以使用OpenCV提供的函数接口完成这个过程,其过程如图所示:
1.标定过程:
由于我的双目图像分辨率只有320*240,在进行角点检测时,检测的一点都不准,因此借鉴示例对图像进行的放大(缩放同理)处理,得到640*480的图像,然后再进行角点检测,完成亚像素精确化之后再将特征点坐标反算回320*240,这个过程基本使得角点检测的结果用肉眼看不出有误差,主要程序过程:
//改变图像尺寸;
cv::resize(imageL, sFrame0, cv::Size(640, 480)); cv::resize(imageR, sFrame1, cv::Size(640, 480));
//改变角点坐标值; if (scale) { for (size_t j = 0; j < tmpPointsL.size(); j++) { tmpPointsL[j].x = tmpPointsL[j].x / 2.; tmpPointsL[j].y = tmpPointsL[j].y / 2.; tmpPointsR[j].x = tmpPointsR[j].x / 2.; tmpPointsR[j].y = tmpPointsR[j].y / 2.; } }
效果图:
第二个问题就是关于标定函数stereoCalibrate,在OpenCV2和OpenCV3中的参数定义的顺序是不同的,OpenCV2:
double rms = cv::stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1], cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], imageSize, R, T, E, F, TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 100, 1e-5), CV_CALIB_FIX_ASPECT_RATIO + CV_CALIB_ZERO_TANGENT_DIST + CV_CALIB_SAME_FOCAL_LENGTH + CV_CALIB_RATIONAL_MODEL + CV_CALIB_FIX_K3 + CV_CALIB_FIX_K4 + CV_CALIB_FIX_K5);
第三个问题就是标定结果,注意T矩阵中的第一个元素通常是两个相机的基线距离,其他标定结果包括两个相机的内参和畸变矩阵,以及相对的R,T和R1,P1等;另外就是极线的显示,如下图所示:
需要注意,两幅图像对应的点应该在同一条极线上,上图中每条绿线应近似表示两幅图像上对应的点。
2.标定结果的使用:主要就是使双目相机输出的图像获得矫正和对齐
cv::Mat R1, R2, P1, P2, Q; cv::stereoRectify(K1, D1, K2, D2, cv::Size(320, 240), R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 0, cv::Size(320, 240)); Mat rmap[2][2]; initUndistortRectifyMap(K1, D1, R1, P1, cv::Size(320, 240), CV_16SC2, rmap[0][0], rmap[0][1]); initUndistortRectifyMap(K2, D2, R2, P2, cv::Size(320, 240), CV_16SC2, rmap[1][0], rmap[1][1]); //图像显示循环过程; remap(frame0, remapFrame0, rmap[0][0], rmap[0][1], CV_INTER_LINEAR); remap(frame1, remapFrame1, rmap[1][0], rmap[1][1], CV_INTER_LINEAR);
其中最重要的就是stereoRectify函数的使用,倒数第二个参数alpha的取值使得输出的图像不同,当alpha=0时,输出经过剪裁之后的图:
当alpha=1时,表示图像不经任何剪裁,保持原始尺度:
当alpha=-1时,表示取默认值:
官方对于alpha参数的解释为:
因此,在使用过程中应设alpha=0作为输出,下面给出视频输出结果:
请注意,正确的双目矫正结果不仅需要将图像畸变进行矫正,还需要进行行对齐,如同上面的绿线所示,它们表示两个相机已经达到了正视平行状态,只有y上的差别。