在这里我使用的是Learning OpenCV3的示例,本节使用的项目代码可以在这里下载到。
在下载完整个工程以后,按照工程使用说明,下载配置Opencv,运行VS2019项目即可。正常情况下,运行结果如下图所示:
图1
图2
图3
图1显示了dos框输出的信息:计算stereo calibration以及误差。图2和图3和双目标定其实没有关系,图2显示的是rectify以后双目图像对齐的结果,图3是stereo match的结果,也就是disparity map。有多组图像对的结果,这里只放出了第一组。
Opencv函数还是好用啊,可惜没有内部算法的说明文档。本示例代码主要流程:
CV_EXPORTS_W bool findChessboardCorners(InputArray image,
Size patternSize,
OutputArray corners,
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
这个函数在opencv单目相机标定-示例代码分析说明过,这里就不再详细分析了。
CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints1,
InputArrayOfArrays imagePoints2,
InputOutputArray cameraMatrix1,
InputOutputArray distCoeffs1,
InputOutputArray cameraMatrix2,
InputOutputArray distCoeffs2,
Size imageSize,
OutputArray R,
OutputArray T,
OutputArray E,
OutputArray F,
int flags = CALIB_FIX_INTRINSIC,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) );
直接分析标定参数是否正确并不直观,一般在标定完成后,使用rectify算法将双目图像处理成光轴平行的图像,然后直接对比某个方向是否对齐。
(1) 棋盘格角点去畸变
CV_EXPORTS_W void undistortPoints(InputArray src,
OutputArray dst,
InputArray cameraMatrix,
InputArray distCoeffs,
InputArray R = noArray(),
InputArray P = noArray() );
(2) 极线计算
CV_EXPORTS_W void computeCorrespondEpilines(InputArray points,
int whichImage,
InputArray F,
OutputArray lines );
(3) 对齐误差统计
这里写点自己的理解,也不确定是不是正确的,代码中计算误差的公式为: e r r = ∣ a l ∗ x r + b l ∗ y r + c l ∣ + ∣ a r ∗ x l + b r ∗ y l + c r ∣ err=|a_{l}*x_{r}+b_{l}*y_{r}+c_{l}|+|a_{r}*x_{l}+b_{r}*y_{l}+c_{r}| err=∣al∗xr+bl∗yr+cl∣+∣ar∗xl+br∗yl+cr∣
也就是: e r r = ∣ l i n e r ∗ x l ∣ + ∣ l i n e l ∗ x r ∣ err=|line_{r}*x_{l}|+|line_{l}*x_{r}| err=∣liner∗xl∣+∣linel∗xr∣
(4) rectify
CV_EXPORTS_W void stereoRectify(InputArray cameraMatrix1,
InputArray distCoeffs1,
InputArray cameraMatrix2,
InputArray distCoeffs2,
Size imageSize,
InputArray R,
InputArray T,
OutputArray R1,
OutputArray R2,
OutputArray P1,
OutputArray P2,
OutputArray Q,
int flags = CALIB_ZERO_DISPARITY,
double alpha = -1,
Size newImageSize = Size(),
CV_OUT Rect* validPixROI1 = 0,
CV_OUT Rect* validPixROI2 = 0 );
然后利用initUndistortRectifyMap和remap函数分别对左右图进行rectify处理。
(5) stereo match
CV_WRAP static Ptr<StereoSGBM> create(int minDisparity = 0,
int numDisparities = 16,
int blockSize = 3,
int P1 = 0,
int P2 = 0,
int disp12MaxDiff = 0,
int preFilterCap = 0,
int uniquenessRatio = 0,
int speckleWindowSize = 0,
int speckleRange = 0,
int mode = StereoSGBM::MODE_SGBM);