camera:单目相机标定
本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。
相机标定内容
相机标定的目标是估计相机的 内参矩阵、外参(位姿) 以及 畸变参数 等,使我们能够在「像素坐标 ↔ 相机坐标/世界坐标」之间可靠地转换。
内参
相机内参矩阵是相机自身的属性,一般写作:
[ K= \begin{bmatrix} f_x & \gamma & u_0 \ 0 & f_y & v_0 \ 0 & 0 & 1 \end{bmatrix} ]
其中各个量含义为:
f:物理焦距,单位毫米(更偏物理概念,在几何推导中常用);
fx:x 方向的「等效焦距」,以像素为单位;
fy:y 方向的「等效焦距」,以像素为单位;
u₀, v₀:主点坐标(成像平面上光轴与成像平面交点),单位为像素;
γ:像素坐标轴的倾斜因子,理想情况下为 0(像素为正交网格)。
在多数工程场景中,γ 通常直接固定为 0,不参与优化。
外参
外参描述「相机坐标系与世界坐标系之间的刚体变换」,通常记作旋转矩阵 R 和平移向量 t,或者其等价的旋转向量 rvec:
旋转矩阵/旋转向量:描述世界坐标系相对于相机坐标系的朝向变化;
平移向量:描述在相机坐标系下,世界坐标系原点的位置。
不同库(包括 OpenCV)在「相机看世界」还是「世界看相机」上的约定略有不同,但本质都是一组 [R | t] 刚体变换。
畸变参数
常见的针孔+畸变模型会包含:
- 径向畸变系数:k1, k2, k3(有的模型还会扩展到 k6),主要描述桶形/枕形畸变;
- 切向畸变系数:p1, p2,主要来自镜头装配时光轴与图像平面不完全平行;
- 在广角/鱼眼镜头、工业相机中,还可以启用更加复杂的棱镜畸变、倾斜传感器模型等(OpenCV 对应
CALIB_RATIONAL_MODEL、CALIB_THIN_PRISM_MODEL、CALIB_TILTED_MODEL等标志位)。
径向畸变主要发生在「相机坐标 → 图像物理坐标」的映射过程中;切向畸变则更多与成像几何误差有关。通常越靠近成像边缘,畸变越明显。
相机标定步骤
https://docs.opencv.org/3.4.0/d9/d0c/group__calib3d.html
提取角点
棋盘格角点检测
第一个参数是输入的棋盘格图像(可以是8位单通道或三通道图像); 第二个参数是棋盘格内部的角点的行列数(注意:不是棋盘格的行列数,如棋盘格的行列数分别为4、8,而内部角点的行列数分别是3、7,因此这里应该指定为cv::Size(3, 7)); 第三个参数是检测到的棋盘格角点,类型为std::vectorcv::Point2f。 第四个参数flag,用于指定在检测棋盘格角点的过程中所应用的一种或多种过滤方法,可以使用下面的一种或多种,如果都是用则使用OR: cv::CALIB_CB_ADAPTIVE_THRESH:使用自适应阈值将图像转化成二值图像 cv::CALIB_CB_NORMALIZE_IMAGE:归一化图像灰度系数(用直方图均衡化或者自适应阈值) cv::CALIB_CB_FILTER_QUADS:在轮廓提取阶段,使用附加条件排除错误的假设 cv::CALIB_CV_FAST_CHECK:快速检测
对粗提取的角点进行精确化
image源图像 corners,提供角点的初始坐标 region_size: 搜索窗口的一般尺寸\
亚像素检测
image源图像 corners,提供角点的初始坐标,返回更加精确的点 winSize,搜索窗口的一般尺寸,如果winSize=Size(5,5),则search windows为11*11 winSize,死区的一般尺寸,用来避免自相关矩阵的奇点,(-1,-1)表示没有死区 criteria,控制迭代次数和精度
棋盘格角点的绘制
image为8-bit,三通道图像 patternSize,每一行每一列的角 corners,已经检测到的角 patternWasFound,findChessboardCorners的返回值
相机标定
生成 objectPoints
|
|
求相机的内参外参
|
|
objectPoints:世界坐标(棋盘格平面上的 3D 点),类型为
vector<vector<Point3f>>,对于平面棋盘一般 z=0; imagePoints:对应的图像坐标,类型为vector<vector<Point2f>>; imageSize:图像的尺寸,用于初始化相机模型;cameraMatrix:输出的内参数矩阵(K);distCoeffs:输出的畸变系数向量(k1,k2,p1,p2,k3,…);rvecs:每一张标定图像对应的旋转向量(相机相对于棋盘平面的姿态);tvecs:每一张标定图像对应的平移向量; flags,可以组合: CALIB_USE_INTRINSIC_GUESS:使用该参数时,将包含有效 fx, fy, cx, cy 估计值的cameraMatrix作为初始值输入,然后对其做进一步优化;如果不使用,则以图像中心作为主点初值,通过最小二乘等方式估计初始焦距。CALIB_FIX_PRINCIPAL_POINT:在优化时固定主点坐标(cx, cy),不再更新;和
CALIB_USE_INTRINSIC_GUESS配合使用时,主点保持为输入值。CALIB_FIX_ASPECT_RATIO:固定 fx/fy 的比值,只将 fy 作为变量进行优化;在没有给定内参初值时,只会使用 fx/fy 的比值。
CALIB_ZERO_TANGENT_DIST:将切向畸变系数(p1, p2)固定为 0;
CALIB_FIX_K1,…,CALIB_FIX_K6:对应的径向畸变系数在优化中保持不变(常用于已有标定结果只做微调时)。
CALIB_RATIONAL_MODEL(有理模型):启用额外的径向畸变 k4, k5, k6,使标定函数使用更高阶的畸变模型(广角镜头时常用);
CALIB_THIN_PRISM_MODEL(薄棱镜畸变模型):启用棱镜畸变系数 S1–S4;
CALIB_FIX_S1_S2_S3_S4:固定薄棱镜畸变系数 S1–S4,不参与优化;
CALIB_TILTED_MODEL(倾斜传感器模型):启用倾斜畸变系数 tauX, tauY;
CALIB_FIX_TAUX_TAUY:在优化过程中固定倾斜传感器模型系数 tauX, tauY。
常用的工程实践是:从简单模型开始(只估计 k1, k2, p1, p2, k3),当发现边缘残差较大、镜头视角较广时,再逐步打开有理模型和其他复杂畸变项。
相机矫正
参考:
相机标定(4) 矫正畸变 undistort()和initUndistortRectifyMap()
计算无畸变和修正转换映射
|
|
1.
cameraMatrix:输入相机矩阵 2.distCoeffs:输入参数,相机的畸变系数: (k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τ**x,τ**y]]]]) ,有4,5,8,12或14个元素。如果这个向量是空的,就认为是零畸变系数。 3.R:可选的修正变换矩阵,是个3*3的矩阵。通过stereoRectify计算得来的R1或R2可以放在这里。如果这个矩阵是空的,就假设为单位矩阵。在cvInitUndistortMap中,R被认为是单位矩阵。 4.newCameraMatrix:新的相机矩阵 5.size:未畸变的图像尺寸。 6.m1type:第一个输出的映射的类型,可以为 CV_32FC1, CV_32FC2或CV_16SC2,参见cv::convertMaps。 7.map1:第一个输出映射。 8.map2:第二个输出映射。
这个函数用于计算无畸变和修正转换关系,为了重映射,将结果以映射的形式表达。无畸变的图像看起来就像原始的图像,就像这个图像是用内参为newCameraMatrix的且无畸变的相机采集得到的。 在单目相机例子中,newCameraMatrix一般和cameraMatrix相等,或者可以用cv::getOptimalNewCameraMatrix来计算,获得一个更好的有尺度的控制结果。 在双目相机例子中,newCameraMatrix一般是用cv::stereoRectify计算而来的,设置为P1或P2。 此外,根据R,新的相机在坐标空间中的取向是不同的。例如,它帮助配准双目相机的两个相机方向,从而使得两个图像的极线是水平的,且y坐标相同(在双目相机的两个相机谁水平放置的情况下)。 该函数实际上为反向映射算法构建映射,供反向映射使用。也就是,对于在已经修正畸变的图像中的每个像素(u,v),该函数计算原来图像(从相机中获得的原始图像)中对应的坐标系。
函数输出得到map1和map2,然后使用remap()函数
remap
第一个参数:输入图像,即原图像,需要单通道8位或者浮点类型的图像 第二个参数:输出图像,即目标图像,需和原图形一样的尺寸和类型 第三个参数:它有两种可能表示的对象:(1)表示点(x,y)的第一个映射;(2)表示CV_16SC2,CV_32FC1等 第四个参数:它有两种可能表示的对象:(1)若map1表示点(x,y)时,这个参数不代表任何值;(2)表示 CV_16UC1,CV_32FC1类型的Y值 第五个参数:插值方式,有四种插值方式: (1)INTER_NEAREST——最近邻插值
(2)INTER_LINEAR——双线性插值(默认)
(3)INTER_CUBIC——双三样条插值(默认)
(4)INTER_LANCZOS4——lanczos插值(默认)
第六个参数:边界模式,默认BORDER_CONSTANT
第七个参数:边界颜色,默认Scalar()黑色
实战中的标定注意事项与建议(2024 视角)
-
标定板与姿态多样性:
- 建议使用质量较好的棋盘格或圆点标定板(打印纸要平整、粘在硬质板上);
- 拍摄时要覆盖尽量多的姿态:左右、上下、大角度倾斜、远近距离都要有,避免所有图片都在视野中心/同一距离。
-
图像质量与曝光:
- 尽量避免过曝/欠曝和强反光;
- 对于运动模糊明显的图片,建议直接丢弃,不要参与标定。
-
分辨率与 ROI:
- 最终使用什么分辨率跑应用,就尽量用相同分辨率标定;
- 如果只使用图像中间区域,可以在采集时就裁掉黑边和无效区域,减少无用畸变影响。
-
标定结果评估:
- 重点看 reprojection error(重投影误差),一般来说 <0.5 像素效果较好,但也要结合分辨率和镜头质量;
- 随机丢弃/替换部分标定图像重新标定,对比参数变化,判断结果是否稳定。
-
广角/鱼眼镜头:
- 常规针孔模型在视角非常大(>150°)时往往不够用,可以考虑 OpenCV 中的
fisheye模块或启用CALIB_RATIONAL_MODEL、CALIB_THIN_PRISM_MODEL等更复杂模型; - 对于需要精确几何的任务(SLAM、多视图重建、AR 等),建议优先选用畸变更小、成像更均匀的镜头,再通过标定精修。
- 常规针孔模型在视角非常大(>150°)时往往不够用,可以考虑 OpenCV 中的
代码工程
完整代码工程(包含标定图片):