opencv双目相机标定-示例代码分析

  在这里我使用的是Learning OpenCV3的示例,本节使用的项目代码可以在这里下载到。

一、运行示例

  在下载完整个工程以后,按照工程使用说明,下载配置Opencv,运行VS2019项目即可。正常情况下,运行结果如下图所示:
opencv双目相机标定-示例代码分析_第1张图片
图1
opencv双目相机标定-示例代码分析_第2张图片
图2
opencv双目相机标定-示例代码分析_第3张图片
图3

  图1显示了dos框输出的信息:计算stereo calibration以及误差。图2和图3和双目标定其实没有关系,图2显示的是rectify以后双目图像对齐的结果,图3是stereo match的结果,也就是disparity map。有多组图像对的结果,这里只放出了第一组。

二、代码分析

Opencv函数还是好用啊,可惜没有内部算法的说明文档。本示例代码主要流程:

  • 图像对棋盘格角点提取
  • 双目标定
  • 误差统计
  • rectify
  • stereo match

1. 提取图像对棋盘格角点

CV_EXPORTS_W bool findChessboardCorners(InputArray image, 
										Size patternSize, 
										OutputArray corners,
                                        int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );

这个函数在opencv单目相机标定-示例代码分析说明过,这里就不再详细分析了。

2. 双目标定

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) );
  • objectPoints:棋盘格3D角点坐标
  • imagePoints1:左图棋盘格角点
  • imagePoints2:右图棋盘格角点
  • cameraMatrix1:左相机内参矩阵
  • distCoeffs1:左相机畸变系数
  • cameraMatrix2:右相机内参矩阵
  • distCoeffs2:右相机畸变系数
  • imageSize:图像大小
  • R:左右相机之间的旋转矩阵
  • T:左右相机之间的平移矩阵
  • E:本质矩阵
  • F:基础矩阵
  • flags:标定参数设置的标志位,CALIB_FIX_INTRINSIC表示固定输入的内参矩阵和畸变系数。
  • criteria:迭代优化参数的结束条件

  直接分析标定参数是否正确并不直观,一般在标定完成后,使用rectify算法将双目图像处理成光轴平行的图像,然后直接对比某个方向是否对齐。

3. 误差统计

(1) 棋盘格角点去畸变

CV_EXPORTS_W void undistortPoints(InputArray src, 
								  OutputArray dst,
                                  InputArray cameraMatrix, 
                                  InputArray distCoeffs,
                                  InputArray R = noArray(), 
                                  InputArray P = noArray() );
  • src:畸变图像上的棋盘格角点
  • dst:去畸变的棋盘格角点
  • cameraMatrix:相机内参矩阵
  • distCoeffs:相机畸变参数
  • R:旋转矩阵
  • P:新的相机内参

(2) 极线计算

CV_EXPORTS_W void computeCorrespondEpilines(InputArray points, 
											int whichImage,
                                            InputArray F, 
                                            OutputArray lines );
  • points:棋盘格角点
  • whichImage:图像编号,1或2
  • F:基础矩阵
  • lines:计算得到的极线方程[a,b,c],ax+by+c=0

(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=alxr+blyr+cl+arxl+bryl+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=linerxl+linelxr

(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 );
  • cameraMatrix1:左相机内参矩阵
  • distCoeffs1:左相机畸变系数
  • cameraMatrix2:右相机内参矩阵
  • distCoeffs2:右相机畸变系数
  • imageSize:图像大小
  • R:相机间的旋转矩阵,双目标定获得
  • T:相机间的平移矩阵,双目标定获得
  • R1:rectify后,左相机的旋转变换矩阵
  • R2:rectify后,右相机的旋转变换矩阵
  • P1:左相机进行rectify得到的投影矩阵
  • P2:右相机进行rectify得到的投影矩阵
  • Q:视差到深度的变换矩阵
  • flags:CALIB_ZERO_DISPARITY表示图像对内参的主点没有偏移
  • alpha:拉伸参数,调整输出图像的显示区域
  • newImageSize:输出图像的大小
  • validPixROI1:可选参数
  • validPixROI2:可选参数

然后利用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);
  • minDisparity:最小视差值
  • numDisparities:视差范围值
  • blockSize:匹配区域大小
  • P1:控制小视差变化的系数
  • P2:控制大视差变化的系数
  • disp12MaxDiff:左右视差图最大差异值
  • preFilterCap:视差图变化差异截断阈值
  • uniquenessRatio:最小代价值和次小代价值之间的比值阈值
  • speckleWindowSize:平滑视差区域的最大尺寸
  • speckleRange:每个连接组件内的最大视差变化
  • mode:将其设置为StereoSGBM :: MODE_HH以运行全尺寸双通道动态编程算法

三、总结

  • 双目标定算法的原理比单目更加复杂,同时对应的后处理算法也更加复杂,这些算法十分重要,这里我只浮于表面的介绍了Opencv标定等函数,内部算法原理只能通过阅读源码做进一步的分析。

你可能感兴趣的:(calibration)