交互式相机标定应用
按照经典的标定技术,用户必须先收集所有数据,然后运行 cv::calibrateCamera 函数以获取相机参数。如果平均重投影误差很大,或者估计的参数看起来不对,那么选择/收集数据并重新运行 cv::calibrateCamera 的过程就要重复一遍。
交互式标定过程假定:在每加入一份新数据后,用户都能看到结果和误差估计,也可以删除最后一份数据;最终,当用于标定的数据集足够大时,会启动自动数据选择过程。
主要应用特性
Section titled “主要应用特性”示例应用程序将:
- 确定畸变矩阵及其每个元素的置信区间
- 确定相机矩阵及其每个元素的置信区间
- 从相机或视频文件获取输入
- 从 XML 文件读取配置
- 将结果保存到 XML 文件
- 计算重投影误差
- 拒绝处于锐角视角的图案视图,以防止出现病态的雅可比块
- 自动切换标定标志(如有需要,固定纵横比以及畸变矩阵的元素)
- 利用若干准则自动检测标定是否完成
- 自动捕获静止图案(用户无需按任何键来捕获帧,只需让图案静止一秒即可)
支持的图案:
- 黑白棋盘
- 非对称圆点图案
- 双重非对称圆点图案
- chAruco(带 ArUco 标记的棋盘)
- 对称圆点图案
应用程序有两组参数:主参数(通过命令行传递)和高级参数(通过 XML 文件传递)。
所有这些参数都通过命令行传递给应用程序。
-[参数]=[默认值]:说明
- -v=[filename]:从文件名获取视频,默认输入——id 为 0 的相机
- -ci=[0]:从指定 id 的相机获取视频
- -flip=[false]:对输入帧进行垂直翻转
- -t=[circles]:用于标定的图案(circles、chessboard、dualCircles、chAruco、symcircles)
- -sz=[16.3]:标定板上两个最近的圆心或方格中心之间的距离
- -dst=[295]:dualCircles 图案的白色与黑色部分之间的距离
- -w=[width]:图案的宽度(以角点数或圆点数计)
- -h=[height]:图案的高度(以角点数或圆点数计)
- -of=[camParams.xml]:输出文件名
- -ft=[true]:自动调节标定标志
- -vis=[grid]:捕获棋盘的可视化方式(grid、window)
- -d=[0.8]:两次捕获之间的延迟(以秒为单位)
- -pf=[defaultConfig.xml]:高级应用程序参数文件
- -force_reopen=[false]:在出错时强制重新打开相机。对于连接不稳定的 IP 相机可能会有帮助。
- -save_frames=[false]:保存对最终标定有贡献的帧
- -zoom=[1]:应用于预览图像的缩放因子
默认情况下,高级参数的值存储在 defaultConfig.xml 中
<?xml version="1.0"?><opencv_storage><charuco_dict>0</charuco_dict><charuco_square_length>200</charuco_square_length><charuco_marker_size>100</charuco_marker_size><calibration_step>1</calibration_step><max_frames_num>30</max_frames_num><min_frames_num>10</min_frames_num><solver_eps>1e-7</solver_eps><solver_max_iters>30</solver_max_iters><fast_solver>0</fast_solver><frame_filter_conv_param>0.1</frame_filter_conv_param><camera_resolution>1280 720</camera_resolution></opencv_storage>

- charuco_dict:用于生成 chAruco 图案的专用字典的名称
- charuco_square_length:chAruco 棋盘上方格的尺寸(以像素为单位)
- charuco_marker_size:chAruco 棋盘上 ArUco 标记的尺寸(以像素为单位)
- calibration_step:两次 cv::calibrateCamera 调用之间的帧间隔
- max_frames_num:如果用于标定的帧数大于此值,帧过滤器就会开始工作。过滤后,标定数据集的大小等于 max_frames_num
- min_frames_num:如果帧数大于此值,就会开启自动标志调节、去畸变视图和质量评估
- solver_eps:cv::calibrateCamera 中 Levenberg-Marquardt 求解器的精度
- solver_max_iters:求解器的迭代次数上限
- fast_solver:如果此值非零且找到了 Lapack,则求解器中使用 QR 分解代替 SVD。QR 比 SVD 更快,但可能精度较低
- frame_filter_conv_param:用于双准则帧过滤器线性卷积的参数
- camera_resolution:用于标定的相机的分辨率
注意: charuco_dict、charuco_square_length 和 charuco_marker_size 用于 chAruco 图案的生成(详见 Aruco 模块说明:Aruco 教程)
默认 chAruco 图案:
要制作这种图案,你需要标准的 OpenCV 圆点图案以及它的二值反转版本。将两个图案放在同一平面上,使得一个图案中圆点的所有水平线是另一个图案中相似水平线的延续。如下图所示测量两个图案之间的距离,并将其作为 dst 命令行参数传入。同时测量最近的圆心之间的距离,并将该值作为 sz 命令行参数传入。
这种图案对制作质量和测量非常敏感。
当标定数据集的大小大于 max_frames_num 时,数据过滤器就会开始工作。它会尝试从数据集中移除”坏”帧。过滤器会移除使 取得最大值的帧。
RMS 是为第 i 帧计算的平均重投影误差,reducedGridQuality 是在不包含第 i 帧时对场景覆盖质量的评估。 等于 frame_filter_conv_param。
要开始标定,只需运行应用程序。将图案置于相机前方,并在某个位姿下固定住图案。然后等待捕获(会显示诸如 “Frame #i captured” 的消息)。主屏幕上会显示当前的焦距和重投影误差。将图案移动到下一个位置并重复该过程。尽量均匀地覆盖整个图像平面,并且不要以与图像平面呈锐角的方式展示图案。
如果标定看起来成功了(置信区间和平均重投影误差都很小,帧覆盖质量和图案视图数量都足够大),应用程序会显示如下图所示的消息。
快捷键:
- Esc——退出应用程序
- s——将当前数据保存到 XML 文件
- r——删除最后一帧
- d——删除所有帧
- u——启用/禁用去畸变
- v——切换可视化模式
结果你将获得相机参数及其置信区间。
输出 XML 文件的示例:
<?xml version="1.0"?><opencv_storage><calibrationDate>"Thu 07 Apr 2016 04:23:03 PM MSK"</calibrationDate><framesCount>21</framesCount><cameraResolution> 1280 720</cameraResolution><camera_matrix type_id="opencv-matrix"> <rows>3</rows> <cols>3</cols> <dt>d</dt> <data> 1.2519588293098975e+03 0. 6.6684948780852471e+02 0. 1.2519588293098975e+03 3.6298123112613683e+02 0. 0. 1.</data></camera_matrix><camera_matrix_std_dev type_id="opencv-matrix"> <rows>4</rows> <cols>1</cols> <dt>d</dt> <data> 0. 1.2887048808572649e+01 2.8536856683866230e+00 2.8341737483430314e+00</data></camera_matrix_std_dev><distortion_coefficients type_id="opencv-matrix"> <rows>1</rows> <cols>5</cols> <dt>d</dt> <data> 1.3569117181595716e-01 -8.2513063822554633e-01 0. 0. 1.6412101575010554e+00</data></distortion_coefficients><distortion_coefficients_std_dev type_id="opencv-matrix"> <rows>5</rows> <cols>1</cols> <dt>d</dt> <data> 1.5570675523402111e-02 8.7229075437543435e-02 0. 0. 1.8382427901856876e-01</data></distortion_coefficients_std_dev><avg_reprojection_error>4.2691743074130178e-01</avg_reprojection_error></opencv_storage>