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 知识结构总览
下面这张图,把整个流程串起来了。我建议你把它存下来,每次做标定前看一眼。
2.7 几个容易踩的坑
做标定这么多年,我总结了几条血泪教训:
| 常见错误 | 后果 | 我的建议 |
|---|---|---|
| 搞混图像坐标系和像素坐标系 | 主点偏移,投影偏差几个像素 | 先画个坐标系草图,标清原点位置 |
| 忘记除以 Zc 归一化 | 投影点完全不对 | 检查齐次坐标最后一步是否归一化 |
| 把内参矩阵当成固定值 | 变焦或换镜头后标定失效 | 每次改变硬件配置都要重新标定 |
| 忽略畸变直接做拼接 | 拼接缝处出现弯曲变形 | 先做畸变校正,再做拼接 |
我曾经踩过的坑:有一次做多相机拼接,标定结果看起来很好,重投影误差只有0.3像素。但拼接出来的图像就是有错位。查了两天才发现,是其中一个相机的畸变参数没加载进去。从那以后,我每次标定完都会做一次「投影验证」——把棋盘格角点投影到图像上,肉眼确认一遍。
2.8 小结
相机成像模型,说白了就是四步走:
- 世界→相机:刚体变换,解外参
- 相机→图像:透视投影,除以 Zc
- 图像→像素:离散化,乘内参
- 合体:P = K [R | T]
这个模型是所有标定算法的基础。你把它吃透了,后面学张正友标定法、立体匹配、图像拼接,都会轻松很多。