左侧 3D 视角说明:
- 绿色网格:世界坐标系 ($Z=0$ 平面)
- 红色点:棋盘格上的角点 $P$
- 蓝色模型:相机坐标系
拖动鼠标可旋转视角
← 返回标定原理

硬核推导:内参 K 与单应性矩阵 H

第一部分:内参矩阵 K 是怎么来的?

我们经常看到内参矩阵 $K$ 长这样,但它到底是怎么一步步推导出来的?其实它只包含了两步简单的物理几何转换:

1. 小孔成像(3D 物理空间 $\rightarrow$ 2D 物理平面)

根据相似三角形原理,世界中的一个 3D 点 $(X_c, Y_c, Z_c)$(在相机坐标系下),投影到距离小孔为 $f$(物理焦距)的感光平面上,其物理坐标 $(x, y)$ 为:

$$ x = f \frac{X_c}{Z_c} \quad , \quad y = f \frac{Y_c}{Z_c} $$

2. 物理坐标转像素坐标(2D 物理平面 $\rightarrow$ 2D 像素图片)

相机的感光芯片是由一个个小像素格子组成的。假设每个像素的物理宽度是 $dx$,高度是 $dy$,并且照片的左上角才是原点(所以要加上中心点偏移量 $c_x, c_y$)。像素坐标 $(u, v)$ 就是:

$$ u = \frac{x}{dx} + c_x \quad , \quad v = \frac{y}{dy} + c_y $$

3. 组合成矩阵形式

把第一步的 $x, y$ 代入第二步,并且令 $f_x = f/dx$$f_y = f/dy$,我们得到:

$$ u = f_x \frac{X_c}{Z_c} + c_x \quad , \quad v = f_y \frac{Y_c}{Z_c} + c_y $$

为了让这个公式看起来更优雅,数学家引入了“齐次坐标”(也就是加个尾巴 1,方便做矩阵乘法),把它写成了矩阵相乘的样子。中间这个神秘的 $3 \times 3$ 矩阵,就是大名鼎鼎的内参矩阵 $K$

$$ Z_c \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_c \\ Y_c \\ Z_c \end{bmatrix} = K P_c $$

第二部分:单应性矩阵 H 是怎么来的?

在张正友标定法中,最绝妙的一步就是引入了单应性矩阵 $H$。它是怎么消掉复杂度的呢?

1. 完整的相机投影公式

把物体从世界坐标系,经过外参 $(R, T)$ 转到相机坐标系,再经过内参 $K$ 投影成像素,完整的公式是:

$$ s \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = K \begin{bmatrix} R & T \end{bmatrix} \begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix} $$
($s$ 是深度因子,其实就是前面的 $Z_c$)

2. 见证奇迹的时刻:令 $Z = 0$

张正友教授说:我们把打印好的棋盘格放在桌子上,把桌子所在的平面定义为世界坐标系的 $XY$ 平面。这意味着,棋盘格上所有角点的 $Z$ 坐标,统统等于 0! (参考左侧 3D 演示)

既然 $Z=0$,我们将旋转矩阵 $R$ 拆成三列向量 $[r_1, r_2, r_3]$,代入公式看看会发生什么:

$$ s \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} $$

矩阵相乘展开后,$r_3$ 这一列刚好和 $Z=0$ 乘在了一起,$r_3$ 直接被彻底消灭了!公式瞬间被降维打击,简化成了:

$$ s \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = K \begin{bmatrix} r_1 & r_2 & T \end{bmatrix} \begin{bmatrix} X \\ Y \\ 1 \end{bmatrix} $$

3. 定义 $H$ 矩阵

我们把中间这部分 $K \begin{bmatrix} r_1 & r_2 & T \end{bmatrix}$ 打包起来,它是一个 $3 \times 3$ 的矩阵,我们称之为单应性矩阵 $H$

$$ H = \begin{bmatrix} h_1 & h_2 & h_3 \end{bmatrix} = \lambda K \begin{bmatrix} r_1 & r_2 & T \end{bmatrix} $$

有了 $H$,我们就可以直接跳过 3D 空间的复杂计算,把棋盘格平面上的点 $(X,Y)$ 直接映射到照片像素点 $(u,v)$ 上。

第三部分:如何代入数据解方程?(从 H 到 K)

我们在主页面提到,利用旋转矩阵列向量互相垂直和长度相等的性质,可以得到关于内参 $K$ 的两个方程:

$$ h_1^T (K^{-T} K^{-1}) h_2 = 0 $$ $$ h_1^T (K^{-T} K^{-1}) h_1 - h_2^T (K^{-T} K^{-1}) h_2 = 0 $$

这里的 $h_1, h_2$ 是我们通过照片算出来的单应性矩阵 $H$ 的第一、第二列(已知数字)。未知数全在 $K$ 里。怎么解这个看起来极其复杂的矩阵方程呢?

1. 引入中间变量矩阵 $B$

数学家们非常聪明,他们发现中间这一坨 $K^{-T} K^{-1}$ 可以看作一个整体,我们令它为 $B$。因为 $K$ 的特殊形式,$B$ 必定是一个对称矩阵

$$ 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} $$

这个 $3 \times 3$ 的对称矩阵其实只有 6 个独立的未知数。我们把这 6 个未知数拍扁,排成一个列向量 $b = [B_{11}, B_{12}, B_{22}, B_{13}, B_{23}, B_{33}]^T$。

2. 转化为线性方程组 $Vb = 0$

经过代数展开(将 $h_i^T B h_j$ 展开合并同类项),原来的那两个复杂的矩阵方程,就可以变成非常清爽的线性方程:

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

这里的 $v_{ij}$ 完全是由 $H$ 矩阵里的已知数字组合算出来的常数向量。这意味着,每拍一张照片,我们就能得到 2 个关于未知向量 $b$ 的纯线性方程!

3. 构造大矩阵并用 SVD 求解

如果我们拍了 $n$ 张照片,把它们提供的方程全叠在一起,就会得到一个大矩阵方程:

$$ V b = 0 $$
(其中 $V$ 是一个 $2n \times 6$ 的已知数字矩阵)

因为 $b$ 有 6 个元素(但齐次坐标下缩放比例不影响,实际是 5 个自由度),我们至少需要 $2n \ge 5$,也就是至少 3 张照片(提供 6 个方程)。

在代码中,计算机会使用SVD(奇异值分解)算法,瞬间找出矩阵 $V$ 的最小奇异值对应的特征向量,这就是这个方程组的最优解 $b$。现在,矩阵 $B$ 被我们解出来了!

4. 从 $B$ 还原内参 $K$ 和外参

得到矩阵 $B$ 后,计算机通过一种叫做 Cholesky 分解 的标准数学算法,可以直接把对称矩阵 $B$ 重新拆解成 $K^{-T} K^{-1}$,从而完美得到相机的内参矩阵 $K$

有了 $K$,把前面公式里的未知数替换掉,外参 $(R, T)$ 也迎刃而解:

$$ r_1 = \lambda K^{-1} h_1 \quad , \quad r_2 = \lambda K^{-1} h_2 \quad , \quad r_3 = r_1 \times r_2 \quad , \quad T = \lambda K^{-1} h_3 $$
标定全流程终极总结:
  1. 提取照片角点,算出每张图的单应性矩阵 $H$。
  2. 利用 $H$ 构造出线性方程组的大矩阵 $V$。
  3. 通过 SVD 奇异值分解,解出中间对称矩阵 $B$。
  4. 对 $B$ 进行 Cholesky 分解,得到相机内参 $K$。
  5. 将 $K$ 和 $H$ 代入公式,反推求出每一张照片的外参 $R, T$。
  6. 最后加上畸变系数,放入 LM 非线性优化算法中微调,得到最终结果!