相机内参标定类
该代码是一个关于摄像头内参处理类的实现。它主要做了以下几件事情:
1. 提供读取和保存相机内参的功能。
2. 允许用户设置一系列参数(如图像尺寸、棋盘格尺寸等)。
3. 支持从图像中检测棋盘格角点,并根据检测到的角点及其他参数计算相机位姿。
4. 提供误差计算和图像去畸变功能。
主要功能包括:
读取和写入相机内参文件(.yml格式),包括相机矩阵、畸变系数等。
设置参数,包含文件名、图像大小、标定图案信息、是否为圆形图案、是否使用鱼眼模型、是否使用复
杂的相机模型等,以预备进行校准作业。
提供参数的打印功能,便于调试。
从输入图像中检测棋盘格角点,支持圆形和非圆形棋盘格的检测,并根据检测结果对角点进行处理。
根据检测到的角点进行相机位姿估计(PNP问题)。
根据校准得到的参数进行图像的去畸变处理。
计算位姿估计后的重投影误差,以评估校准质量。
支持在符合条件的情况下对高重投影误差的数据进行剔除,从而改善校准结果。
总之,这段代码实现了相机内参的读取、保存、设置、位姿估计、去畸变和误差计算等功能,是进行相机校准和图像预处理的重要工具。
公有变量:图像尺寸、棋盘格物理坐标、棋盘格图像角点、内参矩阵、鱼眼相机畸变系数、普通相机畸变系数、棋盘格角点检测结果、是否使用鱼眼相机模型
私有变量:是否使用复杂相机模型、是否已加载标定文件、标定图像文件名列表、角点布局尺寸、角点ROI尺寸、角点之间物理距离、是否使用圆点标定板。标定过程中使用的最大重投影误差、计算得到的重投影误差。
成员函数:默认构造函数、使用内参文件名进行构造、析构函数、从文件中读取相机内参、将相机内参保存到文件、设置计算最大重投影误差、设置用于内参标定的参数、输出所有相机内参和标定结果、计算某张图像的棋盘格外参、执行内参计算对每张标定图像提取角点、判断相机是否已经标定、根据内参对输入的图像进行畸变矫正、根据内参对输入的像素点进行畸变矫正、获取角点布局尺寸、获取角点ROI尺寸、获取角点物理距离。获取图像中的棋盘格角点保存至成员变量。
----------------------------------
默认构造函数: 初始化复杂相机模型为假,初始化最大投影误差,初始化内参载入状态为假,初始化角点ROI大小为5x5
带参构造函数(参数为内参文件路径):初始化角点ROI大小为5X5,初始化复杂相机模型为假,初始化最大投影误差,根据提供的路径读取相机内参。
读取相机内参:获取文件名后缀,确保为.yml。打开.yml文件,如果没打开输出提示返回false。从文件中读取各种内参,如果是鱼眼相机读取鱼眼畸变系数,否则读取普通畸变系数。最后关闭文件。输出提示,设置内参载入状态为真。返回true。
保存相机内参:检查文件名后缀是否为.yml,若不是输出提示返回false。创建写入的.yml文件,将各种内参写入文件,如果是鱼眼相机,写入鱼眼畸变系数,否则写入普通畸变系数。全部写完最后关闭文件。返回true。
设置内参相关参数,注意,这里设置的参数由外部调用者给出:设置是否使用复杂相机模型,清空已有的文件名列表,清空检测结果,清空图像上的校准点,清空世界坐标系中的校准点,设置文件名列表,设置图像尺寸,设置棋盘格尺寸,设置棋盘格大小,设置是否为圆形标志,设置是否用鱼眼相机。
打印所有参数到控制台,用于调试:打印图像尺寸、打印相机矩阵、打印鱼眼相机畸变系数、打印普通相机畸变系数、打印是否使用复杂的相机模型、打印是否加载了相机内参、打印角点布局尺寸、打印两角点之间的物理距离、打印是否使用圆点标定板、打印是否使用鱼眼相机模型、打印最大允许的重投影误差、打印重投影误差。
检测棋盘格角点的方法实现:结果标志位置为false,定义存储找到的角点向量,如果使用的是圆点检测{ 如果没有找到圆点网格,结果置为false并加入角点检测是否成功向量,返回false; 如果找到了圆点网格,绘制找到的角点,标记结果为真并保存到角点检测是否成功向量,保存角点到棋盘格角点向量,返回成功}。如果使用的是棋盘格检测{ 如果没有找到棋盘格角点,标记结果为假并保存到检测结果向量,如果找到了棋盘格角点,转换为灰度图,精细化角点,保存角点到棋盘格角点向量,绘制找到的角点,输出矫正成功信息,返回成功} 。如果检测到了角点且需要可视化,反转灰度图的颜色,显示灰度图,等待100ms,以便视图更新。
获取棋盘格相对于相机的位姿: 存放灰度图,获取棋盘格角点,{如果没有成功获取角点,移除检测结果的最后一个元素,适配vector大小,返回失败}。删除掉刚刚添加的检测结果,适配vector大小,获取最后一组角点向量,定义存储校正后的角点向量,移除最后一组角点,适配vector大小,定义世界坐标系的点,生成棋盘格每个角点在世界坐标系中的坐标,定义旋转向量和平移向量,如果是鱼眼相机,对角点进行畸变校正,定义畸变系数全为0,求解外参,如果不是鱼眼相机,直接先求解外参R T的三维向量。定义重投影点向量,对于普通相机和鱼眼相机分别计算重投影点,计算重投影点与检测的角点之间误差,处于角点数得到角点平均误差,打印重投影误差。定义旋转矩阵,将外参r矢量转换为旋转矩阵(Rodrigues变换),输出4X4位姿矩阵。返回true。
进行相机内参和畸变系数的计算:清空之前的检测结果向量,清空图像点向量,清空世界点向量,根据图像宽度调整角点搜索区域ROI的大小{ 如果图像宽度大于等于1280,设置ROI为11x11, 如果图像宽度小于等于640,设置ROI为5X5,对于中间范围的宽度,设置ROI为7X7. } 。获取待处理的图片数量,遍历所有图片,获取图片文件名,读取图片,定义灰度图,调用之前的函数获取棋盘格角点。 根据检测到的角点数量,生成对应的世界坐标系中的点, 定义存储角度信息的向量,计算检测到的棋盘格角点的角度,标记矫正是否成功为false,while循环当有足够的图像点并且尚未成功矫正时{ 定义旋转向量、平移向量,矫正映射x,y . 如果是鱼眼相机,则使用相应的calibrate和initUndistortRectifyMap方法,设置矫正标志位,包括:重新计算外参、检查输出数据的合理性以及矫正鱼眼相机镜头原有的倾斜,生成矫正映射。如果不是鱼眼相机:定义迭代终止条件,标志位0,如果选择更复杂的相机模型,设置标志(理想模型-两种径向畸变和两种切向畸变 | 相机的图像平面不再和理想的图像平面重合 | 薄棱镜畸变模型 ) 通过cv::calibrateCamera()函数获取校准相机的结果返回后打印总的重投影误差。} 。初始化单个误差、初始化平均误差、初始化总误差,存储重投影的点、存储每张图片的重投影误差,遍历所有棋盘格图片,计算每张图片的重投影误差{ 获取当前图片的世界坐标系中的点,根据是否是鱼眼相机选择不同的投影方式,将重投影的点与实际检测到的图像点进行比较,计算重投影误差,保存当前图片的误差,计算平均误差,累加到总误差 }。计算所有图片的平均重投影误差,如果平均重投影误差小于等于允许的最大误差 标记校正成功。如果平均重投影误差超过允许的最大误差,标记是否基于重投影误差进行筛选,初始化最大误差的位置为-1,如果基于重投影误差进行筛选,找到最大误差的位置,计算最大误差的索引,移除最大误差。 根据误差筛选结果,删除相应的数据,并尝试重新进行校正:删除最大误差对应的世界坐标,删除最大误差对应的图像坐标,更新检测结果。将最大误差对应的检测结果置为失败。打印使用的棋盘格图片数量。返回成功。
对输入的图像进行畸变矫正: 判断是否为鱼眼相机,如果是,创建爱你单位矩阵用于初始化,获取图像大小,创建存储X坐标映射的矩阵,创建存储Y坐标映射的矩阵,初始化畸变校正映射,使用映射关系进行畸变校正:对输入图像进行畸变校正,结果输出到output。 如果不是鱼眼相机,直接使用直接使用OpenCV提供的undistort函数进行畸变校正。
对输入的像素点进行畸变校正: 鱼眼相机cv::fisheye::undistortPoints 普通相机undistortPoints。