2、标定概念与坐标系:世界坐标系、相机坐标系、图像坐标系、像素坐标系的关系与转换

做标定这么多年,我见过太多人一上来就调参、跑算法,结果标出来误差大得离谱。为什么?说白了,就是没搞懂坐标系是怎么转的。你连像素点在世界里对应哪个位置都说不清,标定怎么可能准?

这一章,咱们就把四个坐标系的关系彻底捋清楚。我保证,看完你就能自己手推转换公式。

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

先问个问题:一张图像上的像素点,怎么对应到现实世界中的某个位置?

答案是——经过四次坐标变换。每次变换都对应一个坐标系。我习惯把它们分成两组:

  • 物理世界组:世界坐标系、相机坐标系
  • 成像平面组:图像坐标系、像素坐标系

下面这张图,是我自己画的结构关系,你看一眼就能明白整体脉络:

四坐标系转换关系总览 世界坐标系 (Xw, Yw, Zw) 相机坐标系 (Xc, Yc, Zc) 图像坐标系 (x, y) 像素坐标系 (u, v) 刚体变换 R, t 透视投影 内参矩阵 离散化 dx, dy, u0, v0 💡 核心思路:从世界坐标到像素坐标,本质是“物理位置 → 相机光心 → 成像平面 → 像素阵列”的逐级映射。 标定要解的,就是每一级映射的参数(外参、内参、畸变系数)。

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

世界坐标系是你自己定的。你可以把原点放在标定板的角点上,也可以放在机器人基座上。相机坐标系的原点在相机光心,Z轴沿着光轴方向。

从世界坐标到相机坐标,说白了就是一次旋转加一次平移。数学上叫刚体变换:

|Xc|   | r11 r12 r13 | |Xw|   |tx|
|Yc| = | r21 r22 r23 | |Yw| + |ty|
|Zc|   | r31 r32 r33 | |Zw|   |tz|

写成齐次形式更简洁:

[Xc]   [R   t] [Xw]
[Yc] = [     ] [Yw]
[Zc]   [     ] [Zw]
[1 ]   [0 0 1] [1 ]

这里的 R 和 t 就是外参。标定要解的第一个东西。

我的经验:外参的旋转矩阵 R 有 9 个元素,但自由度只有 3(绕 X、Y、Z 轴的旋转角)。实际标定时,我习惯用罗德里格斯公式把旋转向量转成矩阵,数值稳定性更好。

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

这一步是核心中的核心。相机坐标系下的点 (Xc, Yc, Zc),通过小孔成像模型投影到成像平面上。

公式很简单:

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

其中 f 是焦距(单位:毫米)。注意,这里 Zc 不能为 0,否则投影无意义。

写成矩阵形式:

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

⚠️ 容易踩的坑:我曾经遇到过一台线扫相机,投影出来的图像总是有拉伸。查了半天,发现是镜头焦距标称值和实际值差了 0.3mm。别迷信镜头上的刻字,标定出来的才是真的。

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

图像坐标系 (x, y) 的单位是毫米,是连续的。但传感器是离散的像素阵列,所以需要转成像素坐标 (u, v)。

转换关系:

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| |     | |Yw|
|1|   | 0   0   1   0| |0 0 1| |Zw|
                              |1 |

其中 fx = f/dx,fy = f/dy,单位是像素。

这个 3×4 的矩阵,就是投影矩阵 P。标定的本质,就是解出 P 矩阵中的参数。

一句话总结:世界坐标到像素坐标,就是“外参(R,t)把点转到相机系,内参(fx,fy,u0,v0)把点投到像素面”。标定就是反着来——从已知的像素点和世界点,反推这些参数。

2.6 四个坐标系的参数对比

坐标系 符号 单位 维度 关键参数
世界坐标系 (Xw, Yw, Zw) 毫米 3D 自定义原点
相机坐标系 (Xc, Yc, Zc) 毫米 3D R, t(外参)
图像坐标系 (x, y) 毫米 2D f(焦距)
像素坐标系 (u, v) 像素 2D fx, fy, u0, v0(内参)

2.7 线扫相机的特殊之处

四线扫相机和普通面阵相机最大的区别在哪?

普通相机一次拍一张二维图像。线扫相机一次只拍一行像素,靠物体运动或相机运动来拼出整张图。

这意味着什么?

  • 图像坐标系只有一行:y 方向的信息来自运动,不是来自传感器本身
  • 需要额外的运动轴标定:编码器脉冲当量、运动方向与相机坐标系的夹角,都得标
  • 外参中的 t 不再是固定值:每行图像的 t 都在变,因为相机和物体在相对运动

我的做法:标定四线扫相机时,我会把运动轴当成一个额外的“时间维度”加入坐标系转换链。这样,世界坐标到像素坐标的映射就变成了 4D→2D 的映射。听起来复杂,但原理和单相机标定一模一样。

2.8 避坑指南:坐标系转换中的常见错误

  1. 主点不在图像中心:别想当然认为 u0, v0 就是图像宽高的一半。实际镜头装配有偏差,主点可能偏好几个像素。
  2. dx 和 dy 不相等:像素不一定是正方形。我遇到过传感器像素是 5.5μm × 5.5μm 的,但标出来 dx 和 dy 差了 0.02μm——这就是制造公差。
  3. Zc 的符号:相机坐标系下,物体在相机前方,Zc 应该是正值。如果标出来 Zc 是负的,检查一下你的坐标轴方向定义。
  4. 旋转矩阵的正交性:解出来的 R 矩阵可能不满足 R^T R = I。需要做正交化处理,否则后续计算会出问题。

⚠️ 我曾经踩过的坑:有一次标定结果反复验证都不对,误差一直在 5 个像素以上。折腾了两天,最后发现是标定板上的角点序号和世界坐标对应错了。低级错误,但最容易忽略。标定前,一定先确认对应关系。