2. 相机成像模型

做多视角标定,绕不开一个核心问题:三维世界里的一个点,是怎么跑到二维照片上的?

说白了,相机就是个「降维机器」。它把真实世界的坐标,经过一连串数学变换,最终映射到像素网格上。我刚开始接触这个的时候,也觉得公式又多又绕。但后来发现,只要理清四个坐标系的关系,整个模型就清晰了。

嗯,咱们今天就把这层窗户纸捅破。

2.1 四个坐标系,一个都不能少

先记住这四兄弟:

  • 世界坐标系(Xw, Yw, Zw)—— 真实世界的位置,单位是米/毫米。
  • 相机坐标系(Xc, Yc, Zc)—— 以相机光心为原点,Z轴指向镜头前方。
  • 图像坐标系(x, y)—— 物理成像平面上的位置,单位还是毫米。
  • 像素坐标系(u, v)—— 你最终看到的图像,单位是像素。

它们之间的转换,就是一条流水线:

世界 → 相机 → 图像 → 像素

每一步都有对应的数学操作:刚体变换 → 透视投影 → 离散化采样。

我在项目里见过不少新手,上来就对着像素坐标调参数,结果怎么调都不对。为什么?因为没搞清楚前面几步的物理意义。你想想看,像素坐标是最后的结果,前面的误差会层层放大。

2.2 世界坐标系 → 相机坐标系:刚体变换

这一步最简单,也最直观。把世界坐标系下的点,通过旋转和平移,挪到相机坐标系下。

数学表达式:

| Xc |   | R11 R12 R13 | | Xw |   | Tx |
| Yc | = | R21 R22 R23 | | Yw | + | Ty |
| Zc |   | R31 R32 R33 | | Zw |   | Tz |

写成齐次坐标更简洁:

| Xc |   | R   T | | Xw |
| Yc | = | 0   1 | | Yw |
| Zc |          | Zw |
| 1  |          | 1  |

这里的 R 是 3×3 旋转矩阵,T 是 3×1 平移向量。它们合起来就是相机外参。

我的经验:外参决定了相机在世界中的「姿势」。标定棋盘格时,我们其实就是在解这6个自由度(3个旋转角 + 3个平移量)。

2.3 相机坐标系 → 图像坐标系:透视投影

这一步是核心,也是很多人容易混淆的地方。

相机坐标系下的点 (Xc, Yc, Zc),通过小孔成像原理,投影到成像平面上。根据相似三角形:

x = f * Xc / Zc
y = f * Yc / Zc

其中 f 是焦距(单位:毫米)。

写成矩阵形式:

| x |   | f  0  0  0 | | Xc |
| y | = | 0  f  0  0 | | Yc |
| 1 |   | 0  0  1  0 | | Zc |
                     | 1  |

注意!这里有个「除以 Zc」的操作,是非线性的。它把三维信息压缩成了二维,深度信息就此丢失。这也是为什么单张照片无法直接恢复深度——你丢掉了那个维度。

我曾经犯过一个低级错误:直接用线性变换处理这一步,结果投影出来的点全偏了。后来才意识到,透视投影必须用齐次坐标处理,最后归一化。

2.4 图像坐标系 → 像素坐标系:离散化

成像平面上的物理坐标 (x, y) 是连续的,但像素是离散的。这一步就是把毫米转换成像素。

公式:

u = x / dx + u0
v = y / dy + v0

其中:

  • dx, dy —— 每个像素在 x、y 方向上的物理尺寸(毫米/像素)
  • u0, v0 —— 主点(光轴与成像平面的交点)的像素坐标

矩阵形式:

| u |   | 1/dx  0    u0 | | x |
| v | = | 0     1/dy v0 | | y |
| 1 |   | 0     0    1  | | 1 |

2.5 合体!完整的投影矩阵

把上面三步串起来,就得到了从世界坐标到像素坐标的完整变换:

| u |   | fx  0   u0  0 | | R   T | | Xw |
| v | = | 0   fy  v0  0 | | 0   1 | | Yw |
| 1 |   | 0   0   1   0 |         | Zw |
                                  | 1  |

简化一下:

s * [u; v; 1] = K * [R | T] * [Xw; Yw; Zw; 1]

这里:

  • K —— 相机内参矩阵(fx, fy, u0, v0)
  • [R | T] —— 相机外参矩阵
  • s —— 尺度因子(就是之前的 Zc)

一句话总结:相机标定,本质上就是求解内参 K 和外参 [R | T] 的过程。

2.6 知识结构总览

下面这张图,把整个流程串起来了。我建议你把它存下来,每次做标定前看一眼。

相机成像模型:四坐标系转换流程 世界坐标系 (Xw, Yw, Zw) 刚体变换 R, T 相机坐标系 (Xc, Yc, Zc) 透视投影 f 图像坐标系 (x, y) 离散化 dx, dy, u0, v0 像素坐标系 (u, v) 关键参数总结 • 外参:[R | T] —— 世界→相机,6自由度 • 内参:fx, fy, u0, v0 —— 相机→像素,4个参数 • 畸变参数:k1, k2, p1, p2, k3 —— 修正镜头畸变(下一章细讲)

2.7 几个容易踩的坑

做标定这么多年,我总结了几条血泪教训:

常见错误 后果 我的建议
搞混图像坐标系和像素坐标系 主点偏移,投影偏差几个像素 先画个坐标系草图,标清原点位置
忘记除以 Zc 归一化 投影点完全不对 检查齐次坐标最后一步是否归一化
把内参矩阵当成固定值 变焦或换镜头后标定失效 每次改变硬件配置都要重新标定
忽略畸变直接做拼接 拼接缝处出现弯曲变形 先做畸变校正,再做拼接

我曾经踩过的坑:有一次做多相机拼接,标定结果看起来很好,重投影误差只有0.3像素。但拼接出来的图像就是有错位。查了两天才发现,是其中一个相机的畸变参数没加载进去。从那以后,我每次标定完都会做一次「投影验证」——把棋盘格角点投影到图像上,肉眼确认一遍。

2.8 小结

相机成像模型,说白了就是四步走:

  1. 世界→相机:刚体变换,解外参
  2. 相机→图像:透视投影,除以 Zc
  3. 图像→像素:离散化,乘内参
  4. 合体:P = K [R | T]

这个模型是所有标定算法的基础。你把它吃透了,后面学张正友标定法、立体匹配、图像拼接,都会轻松很多。