Contents — find the section you need

视觉SLAM、视觉里程计、极线几何和PnP都假定像素坐标到三维空间的映射关系正确。然而,光线穿过镜头成像的方式与教科书上理想的针孔成像方式截然不同。焦距是多少像素?主点距离图像中心有多远?图像上的直线弯曲程度是多少?相机标定就是通过数值方法求解这些量的过程。如果标定工作不到位,无论其上叠加的SLAM或SfM算法多么复杂,系统误差都会从根本上向外传播。

0. 30 秒概要

  • 相机标定是指根据已知的三维点与图像点之间的对应关系,估计相机的内部参数(焦距、主点、倾斜)和畸变系数。同时,外部参数(每次拍摄时的相机位姿)也会被恢复。

  • 镜头存在径向和切向几何畸变。标准的表示方法是 Brown-Conrady 模型,其中径向畸变表示为 k_1,k_2,k_3,切向畸变表示为 p_1,p_2。广角镜头和鱼眼镜头需要使用不同的模型。

  • 张氏方法——从多个位姿拍摄平面图案(例如棋盘格),通过线性求解每个视图的单应性矩阵得到内部参数,然后通过非线性优化修正畸变——是实践中常用的标准标定方法。

  • 标定质量通过重投影误差来判断。仅仅关注平均值是不够的——你还需要检查图像内误差的空间分布以及不同姿态间的差异,否则你会错过那些未被完全捕捉到的局部畸变。

  • 校准并非一成不变,一旦找到便永久有效。缩放、对焦、温度、冲击以及分辨率或裁剪的变化都会改变其固有参数。一旦这一假设失效,下游的视觉SLAM、VO和PnP性能就会悄然下降。

1. 从坐标重新审视针孔模型

在针孔模型中,世界坐标系中的点 \mathbf{X}=(X,Y,Z,1)^\mathsf{T}(齐次坐标)按比例投影到图像上,如下所示:

\tilde{\mathbf{x}} \sim P\mathbf{X},\qquad P=K[R\mid\mathbf{t}]

R\in SO(3) 和 \mathbf{t} 分别是从世界坐标系到相机坐标系的旋转和平移(外参),K 是内参矩阵。

K=\begin{bmatrix}f_x&s&c_x\\0&f_y&c_y\\0&0&1\end{bmatrix}

其中,f_x,f_y 是以像素为单位的焦距,(c_x,c_y) 是主点(光轴与像平面的交点),s 是倾斜角(在大多数现代传感器上接近于零)。校准的逆问题在于,仅根据观测数据恢复K、畸变系数以及每次射击的R,\mathbf{t}。

Diagram 1 · Use the button to switch views
Recovering intrinsic parameters from a checkerboard seen in multiple poses A diagram showing a planar pattern photographed several times at different angles and distances by a fixed camera, and the intrinsic matrix K and distortion coefficients being jointly estimated from each view's homography. Camera (fixed) Pose 1 Pose 2 Pose 3 K, k1,k2,k3 p1,p2 R,t for each pose

如图所示,单次拍摄无法将内部参数与外部参数区分开来。只有通过在不同姿态(倾斜、距离)下采集多个观测值,才能几乎唯一地确定 K 的值——这正是接下来要介绍的张氏方法的核心思想。

2. 镜头并非理想针孔:畸变模型

实际镜头存在径向畸变和切向畸变。将归一化图像坐标写成(x,y)=(X_c/Z_c,\,Y_c/Z_c) 和半径 r^2=x^2+y^2,布朗-康拉迪畸变模型可以写成如下形式。

x_d = x\left(1+k_1r^2+k_2r^4+k_3r^6\right) + 2p_1xy+p_2\left(r^2+2x^2\right)

y_d = y\left(1+k_1r^2+k_2r^4+k_3r^6\right) + p_1\left(r^2+2y^2\right)+2p_2xy

k_1,k_2,k_3 是径向畸变系数,p_1,p_2 是切向畸变系数。径向畸变是指图像根据与镜头中心的距离而收缩或凸起的现象,表现为广角镜头中明显的“桶形”畸变,或长焦镜头中明显的“枕形”畸变。切向畸变是一个较小的非对称分量,由镜头组和图像传感器并非完全平行等实现缺陷引起。最终像素坐标由 \tilde{\mathbf{x}}_{px}=K(x_d,y_d,1)^\mathsf{T} 表示。

Diagram 2 · Use the button to switch views
Comparing an undistorted grid to barrel-type radial distortion The left side shows an ideal grid whose lines stay straight; the right side shows the same grid appearing as a barrel shape, curving inward more toward the outer edges, due to a lens's radial distortion. Ideal (no distortion) Barrel-type radial distortion

对于像鱼眼镜头这样具有极广视场的镜头,布朗-康拉迪多项式模型在边缘附近容易发散,因此并不实用。通常的做法是使用基于角度的等距投影近似方法,例如 OpenCV 的鱼眼模型。重要的是,与其“死记硬背一个畸变模型”,不如根据镜头的视场和光学设计来选择合适的模型。

3. 张氏方法:平面图案标定

目前应用最广泛的方法是张正友于2000年发表的平面图案标定方法。该方法无需特殊的3D标定装置,只需从多个姿态拍摄平面图案(例如印刷的棋盘格图案),并移动相机或图案本身即可。

从某个姿态i下的图案平面(取Z=0)到图像的映射关系,可以用旋转矩阵的第一列和第二列\mathbf{r}_1,\mathbf{r}_2和平移\mathbf{t}表示为单应性矩阵。

H_i \sim K\begin{bmatrix}\mathbf{r}_1&\mathbf{r}_2&\mathbf{t}\end{bmatrix}

这里,每个姿态的 H_i 可以通过已知图案上的网格点及其图像对应关系进行线性估计,使用单应性入门中介绍的 DLT 方法。利用旋转矩阵列正交的约束条件——\mathbf{r}_1^\mathsf{T}\mathbf{r}_2=0,\ \|\mathbf{r}_1\|=\|\mathbf{r}_2\|——可以得到关于 B=K^{-\mathsf{T}}K^{-1} 的线性方程:

\mathbf{h}_1^\mathsf{T}B\mathbf{h}_2=0,\qquad \mathbf{h}_1^\mathsf{T}B\mathbf{h}_1=\mathbf{h}_2^\mathsf{T}B\mathbf{h}_2

每个姿态对应两个这样的方程(\mathbf{h}_1,\mathbf{h}_2 是 H_i 的第一列和第二列)。由于 B 是一个具有 6 个自由度的对称矩阵,给定 3 个或更多位姿,可以通过线性最小二乘法找到 B,然后通过等价于 Cholesky 分解的过程找到 K 的闭式解。这就是为什么 Zhang 的方法只需要“几张平面照片”。然而,如果所有位姿都几乎平行于图像平面(正面平行),则方程会退化,因此需要几个不同倾斜角度的位姿。

闭式解只是一个忽略畸变的初始值。在此基础上,实践中标准的两阶段方法会使用下一节中描述的重投影误差作为目标函数,通过非线性优化(通常是 Levenberg-Marquardt 算法)来优化所有参数,包括畸变系数。

4. 重投影误差和参数优化

标定的目标函数是最小化每个姿态和每个网格点上观测像素与使用估计参数计算的投影位置之间的差异。假设姿态为 i,点为 j,对应的已知三维平面点为 \mathbf{u}_{ij},

E(K,\boldsymbol{\kappa},\{R_i,\mathbf{t}_i\})= \sum_{i=1}^{n}\sum_{j=1}^{m} \left\|\mathbf{u}_{ij}-\pi_d\!\left(K,\boldsymbol{\kappa},R_i\mathbf{X}_j+\mathbf{t}_i\right)\right\|^2

是需要最小化的目标。\boldsymbol{\kappa}=(k_1,k_2,k_3,p_1,p_2) 是畸变系数向量,\pi_d 是包含畸变的投影函数。未知量很大——每个姿态下有K(4-5个自由度)、\boldsymbol{\kappa}(3-5个自由度)和R_i,\mathbf{t}_i(6个自由度×姿态数)——但只要观测点足够多,问题就能得到很好的约束。这种表述可以看作是光束法平差入门中介绍的“联合优化相机姿态和3D结构”框架的一个特例。由于3D点坐标在标定中已知且固定,因此它比普通的光束法平差问题更容易解决。

通常将重投影误差\left\|\mathbf{u}_{ij}-\hat{\mathbf{u}}_{ij}\right\|的均方根(RMS)作为“标定精度”来报告,但仅仅通过观察均值就断言标定完成是存在风险的。此外,还需检查以下内容:

  • 每个姿态的平均误差是否存在差异(特定角度下误差特别大的姿态可能提示图案扭曲、运动模糊或光照不均)

  • 图像内误差的空间分布(边缘处残留的系统误差可能提示畸变模型的阶数或类型不足)

  • 网格点检测的亚像素精度(如果角点检测本身不稳定,则任何优化都无法将其与模型误差区分开来)

5. OpenCV 中的实现框架

典型的单相机标定流程如下。固定拍摄条件(分辨率、变焦、对焦),并在图像的四个角点、中心以及多个倾斜角度拍摄图案,即可完成 90% 的良好标定。

import cv2 as cv
import numpy as np

pattern_size = (9, 6)  # number of internal corners
objp = np.zeros((pattern_size[0]*pattern_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)
objp *= square_size_m  # measured side length of one square [m]

obj_points, img_points = [], []
for gray in calibration_images:  # multiple frames shot at different poses
    found, corners = cv.findChessboardCorners(gray, pattern_size)
    if found:
        corners = cv.cornerSubPix(gray, corners, (11, 11), (-1, -1),
                                   (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001))
        obj_points.append(objp)
        img_points.append(corners)

ret, K, dist, rvecs, tvecs = cv.calibrateCamera(
    obj_points, img_points, gray.shape[::-1], None, None)
# ret is the RMS reprojection error [px]. Also compute per-pose error separately to check.

对于广角或鱼眼镜头,请使用 cv.fisheye.calibrate 系列 API,而不是普通的 calibrateCamera。对于立体相机系统,除了两个相机的内部参数外,还需使用 cv.stereoCalibrate 来确定相对位姿,并使用 cv.stereoRectify 将左右图像对齐到水平极线。此过程直接与立体相机的工作原理和深度相机的工作原理中介绍的基线设计相关。

6. 为什么标定漂移会导致下游系统崩溃

视觉 SLAM、VO 和 PnP 中的许多数学公式都是基于这样的假设:只要拍摄条件不变,标定值就保持不变。极线几何入门中的基本矩阵估计假设坐标已归一化 K^{-1}\tilde{\mathbf{x}}; PnP Primer中的重投影误差最小化方法也将K视为已知值。如果K或畸变系数不再与实际光学系统匹配,则所有这些计算实际上都是“用错误的标尺”进行的。

具体来说,校准值会因以下原因悄然下降:

  • 变焦/对焦变化:对于焦距会变化的镜头,f_x,f_y会随拍摄而变化。启用自动对焦意味着校准时和运行时的内部参数将不匹配。

  • 温度和机械冲击:镜头筒或传感器安装位置的轻微偏移会导致主点和畸变系数发生变化。这对于户外、汽车和无人机应用尤其不可忽略。

  • 分辨率、裁剪或数码变焦的变化:由于 K 是一个像素单位的参数,如果图像被调整大小或裁剪,则 f_x,f_y,c_x,c_y 也必须根据缩放比例进行更新。忘记更新 f_x,f_y,c_x,c_y 是一个极其常见的错误。

  • 左右相机装置的变形:在立体视觉设置中,如果相对位姿(外参标定)——而不仅仅是内参——随时间发生轻微偏移,则由视差计算出的深度值会产生系统误差。

这些误差在单个孤立的位姿估计中很难察觉。但在像 VO 或 SLAM 这样按时间顺序积分位姿的系统中,系统性的重投影误差会随着漂移而累积,从而产生一个扭曲的地图,而回环检测无法完全纠正这种扭曲。在生产系统中,建议使用固定的、已知的 3D 特征(例如建筑物上的直线、已知尺寸的标志)在线监测校准漂移,或者建立定期重新校准的例行程序。

7. 常见故障及应对措施

故障模式 故障现象 应对措施
姿态多样性不足(仅拍摄正面照片) K 和畸变难以准确确定,尤其是 k_3 和主点 拍摄图像的四个角、中心以及几个不同的倾斜角度
图案偏离平面 校准的前提失效,导致系统误差扩散 将其安装在刚性平板上;通过物理测量校正打印比例误差
角点检测精度低 无论模型表现力如何,都会提高重投影误差的阈值 亚像素校正、足够分辨率、控制对焦和曝光
将普通针孔畸变模型应用于广角镜头 图像边缘发散误差,优化不稳定 选择与视场匹配的模型,例如鱼眼模型
调整大小/裁剪后未更新 K 主点和焦距与比例尺不同步,导致姿态估计出现系统误差 每次图像变换时,将 K 转换为相应的比例尺
忽略滚动快门 实际投影中心逐行不同,即使在单帧内也是如此 采用全局快门,或使用行定时模型进行校正

8. 总结

相机标定是将图像从“二维数组”转换为“几何可解释的观测结果”的第一步。针孔模型的内参和外参,以及径向和切向畸变系数,均可从多个姿态的观测数据中恢复——如同张氏平面模式法——最后通过非线性优化重投影误差得到最终结果。这种标定的质量并不会体现在任何单一算法自身的精度指标中,但它却是所有下游阶段(极线几何、PnP、视觉SLAM、SfM、光束法平差)中每个方程的基础。标定并非一次性操作,而是整个流程的一部分,需要随着拍摄条件的变化持续监控。

检查你的理解
一张标定图像上的小误差就足够了吗?

拟合结果可能支持这种观点。

检查不同倾斜角度、图像边缘以及单独的验证图像。

参考文献

What to read next

Continue the series特征检测入门Explore another aspect of this field图像亮度 Lab — 曝光、伽马与裁剪Explore another aspect of this field特征点提取实验 — 对比 Harris 与 Shi–Tomasi