相机内参估计:从针孔模型到 Zhang 标定法

1. 标定目标

相机内参矩阵为

\[ 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\) 是坐标轴倾斜量(通常取 0)。真实镜头还需要畸变参数

\[ D=(k_1,k_2,p_1,p_2,k_3,\ldots). \]

\(K\) 不包含畸变:它描述理想针孔投影;\(D\) 描述镜头对理想模型的偏离。

2. 针孔投影与齐次尺度

世界点变换到相机坐标系:

\[ P_c=RP_w+t=(X_c,Y_c,Z_c)^T. \]

忽略畸变时,

\[ \lambda\begin{bmatrix}u\\v\\1\end{bmatrix} =K\begin{bmatrix}X_c\\Y_c\\Z_c\end{bmatrix} =K[R\mid t]\begin{bmatrix}X\\Y\\Z\\1\end{bmatrix}. \]

展开可得

\[ u=f_x\frac{X_c}{Z_c}+s\frac{Y_c}{Z_c}+c_x, \qquad v=f_y\frac{Y_c}{Z_c}+c_y. \]

在标准针孔模型中 \(lambda=Z_c\)。写成 \(lambda\) 是为了强调齐次坐标只确定到非零比例。投影会丢失深度:同一条经过光心的射线上的三维点投影到同一像素;像素加深度才能唯一恢复空间点。

当 \(s=0\) 且像素已去畸变时,反投影为

\[ X_c=\frac{u-c_x}{f_x}Z_c, \qquad Y_c=\frac{v-c_y}{f_y}Z_c. \]

3. 平面标定板与单应矩阵

把棋盘格坐标系定义在标定板平面上,则所有角点满足 \(Z=0\)。代入投影模型:

\[ \lambda\begin{bmatrix}u\\v\\1\end{bmatrix} =K\begin{bmatrix}r_1&r_2&r_3&t\end{bmatrix} \begin{bmatrix}X\\Y\\0\\1\end{bmatrix} =K\begin{bmatrix}r_1&r_2&t\end{bmatrix} \begin{bmatrix}X\\Y\\1\end{bmatrix}. \]

定义

\[ \boxed{H=K[r_1\ r_2\ t]}, \]

便得到平面单应关系

\[ \boxed{\lambda\begin{bmatrix}u\\v\\1\end{bmatrix} =H\begin{bmatrix}X\\Y\\1\end{bmatrix}}. \]

标定板角点 \((X_i,Y_i)\) 已知,图像角点 \((u_i,v_i)\) 可检测,因此每张图都能估计一个 \(H\)。理论上至少需要四个不共线点,实际使用大量角点做最小二乘估计。

4. 从 \(H\) 约束内参

将 \(H\) 按列写成 \(H=[h_1\ h_2\ h_3]\)。由 \(H=K[r_1\ r_2\ t]\) 可得:

\[ h_1=Kr_1,\qquad h_2=Kr_2,\qquad h_3=Kt. \]

所以

\[ r_1=K^{-1}h_1, \qquad r_2=K^{-1}h_2. \]

严格来说,单应矩阵只确定到一个整体比例;但这个比例会同时出现在 \(h_1,h_2,h_3\) 中,并在下面的正交、等长约束里消去,因此推导时可以省略,不必再引入新的符号。

旋转矩阵的列正交且等长:

\[ r_1^Tr_2=0, \qquad r_1^Tr_1=r_2^Tr_2=1. \]

代入上式并消去尺度:

\[ \boxed{h_1^TK^{-T}K^{-1}h_2=0}, \]

\[ \boxed{h_1^TK^{-T}K^{-1}h_1 =h_2^TK^{-T}K^{-1}h_2}. \]

定义对称矩阵

\[ B=K^{-T}K^{-1} =\begin{bmatrix} B_{11}&B_{12}&B_{13}\\ B_{12}&B_{22}&B_{23}\\ B_{13}&B_{23}&B_{33} \end{bmatrix}. \]

于是每张图提供两条约束:

\[ h_1^TBh_2=0, \qquad h_1^TBh_1-h_2^TBh_2=0. \]

5. 展开为 \(Vb=0\)

令 \(h_i=(h_{1i},h_{2i},h_{3i})^T\),定义

\[ v_{ij}=\begin{bmatrix} h_{1i}h_{1j}\\ h_{1i}h_{2j}+h_{2i}h_{1j}\\ h_{2i}h_{2j}\\ h_{3i}h_{1j}+h_{1i}h_{3j}\\ h_{3i}h_{2j}+h_{2i}h_{3j}\\ h_{3i}h_{3j} \end{bmatrix}, \quad b=\begin{bmatrix}B_{11}&B_{12}&B_{22}&B_{13}&B_{23}&B_{33}\end{bmatrix}^T. \]

则

\[ h_i^TBh_j=v_{ij}^Tb. \]

一张图的两行线性约束为

\[ \begin{bmatrix}v_{12}^T\\(v_{11}-v_{22})^T\end{bmatrix}b=0. \]

把所有图像的约束堆叠起来:

\[ \boxed{Vb=0}. \]

用 SVD 取 \(V\) 最小奇异值对应的右奇异向量,即得到只差整体尺度的 \(b\)。

\(B\) 有 6 个独立元素,但整体尺度不确定,本质上只有 5 个自由度。每张图给两条约束,因此理论上至少需要 3 张姿态不同且不退化的标定图;实践中需要更多图片抵抗检测误差与噪声。

6. 从 \(B\) 恢复 \(K\) 和外参

由

\[ B=K^{-T}K^{-1} \]

可得

\[ B^{-1}=KK^T. \]

对 \(B^{-1}\) 做 Cholesky 分解并按 \(K_{33}=1\) 归一化,即可恢复上三角矩阵 \(K\);也可使用 Zhang 论文中的显式公式。

得到 \(K\) 后,每张图的外参初值为

\[ \text{scale}=\frac1{\lVert K^{-1}h_1\rVert}, \]

\[ r_1=\text{scale}\,K^{-1}h_1, \quad r_2=\text{scale}\,K^{-1}h_2, \quad r_3=r_1\times r_2, \quad t=\text{scale}\,K^{-1}h_3. \]

噪声会使 \(R=[r_1\ r_2\ r_3]\) 不严格正交,通常再通过 SVD 将它投影到最近的旋转矩阵。

7. 加入镜头畸变

Zhang 法的线性初始化近似使用无畸变针孔模型,完整标定随后加入畸变。先计算归一化坐标:

\[ x=\frac{X_c}{Z_c},\qquad y=\frac{Y_c}{Z_c},\qquad r^2=x^2+y^2. \]

常见径向加切向畸变模型为

\[ x_d=x(1+k_1r^2+k_2r^4+k_3r^6) +2p_1xy+p_2(r^2+2x^2), \]

\[ y_d=y(1+k_1r^2+k_2r^4+k_3r^6) +p_1(r^2+2y^2)+2p_2xy. \]

最后映射到像素:

\[ u=f_xx_d+sy_d+c_x, \qquad v=f_yy_d+c_y. \]

完整成像链路是

\[ \boxed{P_w\rightarrow(R_i,t_i)\rightarrow(x,y) \rightarrow D\rightarrow K\rightarrow(u,v)}. \]

8. 联合非线性优化

线性推导给出 \(K\) 和各图外参的初值。随后把内参、畸变和每张图的外参一起优化,最小化所有角点的重投影误差:

\[ \boxed{ \min_{K,D,R_i,t_i}\sum_{i,j} \left\lVert p_{ij}^{\mathrm{obs}} -p_{ij}^{\mathrm{pred}}(K,D,R_i,t_i)\right\rVert^2}. \]

因此,\(K\) 本身不包含畸变,但最终的 \(K\) 是在考虑畸变后联合优化得到的。完整 Zhang 标定并非假设真实相机完全无畸变,而是“用理想模型求初值,再加入畸变并精化”。

9. 为什么需要多姿态图像

不同倾角产生不同的 \(H_i\),为 \(K\) 提供相互独立的约束。若所有图片都近似正视标定板,只做前后平移,约束容易退化,焦距、主点和外参难以稳定区分。

畸变在图像边缘通常更明显,因此标定板还应覆盖中心、四角和边缘。可靠的数据集应做到:

  • 左右、上下倾斜,角度丰富;
  • 覆盖中心、四角与边缘;
  • 距离有变化,同时保证角点清晰;
  • 避免大量几乎重复的姿态。

重点不是图片越多越好,而是约束是否丰富。

10. OpenCV 中的实现

ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(
    object_points,
    image_points,
    image_size,
    None,
    None,
)
  • K:最终内参矩阵;
  • dist:畸变参数;
  • rvecs, tvecs:每张图的外参;
  • ret:总体重投影误差指标。

整个流程可概括为

\[ \boxed{ \text{角点对应} \rightarrow H_i \rightarrow Vb=0 \rightarrow K_{\mathrm{init}} \rightarrow(R_i,t_i)_{\mathrm{init}} \rightarrow\text{加入畸变} \rightarrow\text{联合非线性优化}} \]

对于已完成出厂标定的 RGB-D 相机,通常优先通过厂商 SDK 读取 RGB、Depth 的 \(K,D\) 以及二者间外参;只有在精度验证、镜头改装或标定数据失效时才需要重新标定。