3、坐标系与变换:世界坐标系、相机坐标系、图像坐标系、像素坐标系,以及刚体变换与投影变换

做三维重建这些年,我踩过最大的坑,就是坐标系搞混了。

你想想看,一个点在世界里好好的,经过相机一照,再落到图像上,最后变成像素坐标——这中间经历了四次变换。哪一步搞错了,重建出来的模型就是歪的。今天咱们就把这四层坐标系和它们之间的变换关系,彻底捋清楚。

核心一句话:三维重建的本质,就是找到从「像素坐标」反推回「世界坐标」的那条路。

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

我个人习惯把这四个坐标系想象成一条流水线:

  1. 世界坐标系 (World Coordinate System) —— 真实世界的绝对坐标。你放一个物体在房间里,它的位置就是世界坐标。单位一般是米或毫米。
  2. 相机坐标系 (Camera Coordinate System) —— 以相机光心为原点,Z轴指向相机前方。说白了,就是「相机眼里的世界」。
  3. 图像坐标系 (Image Coordinate System) —— 在成像平面上,以光轴与平面的交点为原点,单位是毫米。这是物理层面的图像。
  4. 像素坐标系 (Pixel Coordinate System) —— 就是我们最终看到的图像,原点在左上角,单位是像素。

嗯,这里要注意:从世界到像素,每一步都是「有损」的。尤其是从三维到二维,深度信息直接丢了。这就是为什么重建需要多张图或者深度传感器。

3.2 刚体变换:世界 → 相机

从世界坐标系到相机坐标系,用的是刚体变换。说白了就是旋转加平移,不改变物体的形状和大小。

公式长这样:

P_cam = R * P_world + T

其中 R 是 3x3 旋转矩阵,T 是 3x1 平移向量。

我在项目中遇到过一个问题:用 OpenCV 的 Rodrigues 函数把旋转向量转成矩阵时,方向搞反了。结果重建出来的点云,整个场景像被拧麻花一样。后来我养成了一个习惯——每次做完变换,先拿一个已知点验证一下。

我的小技巧:刚体变换有6个自由度(3旋转+3平移)。调试时,先固定旋转只调平移,确认平移对了再调旋转。分步调试,问题定位快很多。

3.3 投影变换:相机 → 图像

这一步是三维到二维的关键。用的是针孔相机模型,说白了就是相似三角形。

公式:

x = f * X_cam / Z_cam
y = f * Y_cam / Z_cam

这里 f 是焦距,单位是毫米。X_cam、Y_cam、Z_cam 是相机坐标系下的坐标。

你可能会问:为什么是除以 Z?因为远处的物体看起来小,近处的看起来大。这个除法就是透视效果的数学本质。

曾经踩过的坑:我刚开始做时,忘了考虑镜头畸变。结果重建出来的物体边缘都是弯的。后来才意识到,真实相机不是完美的针孔模型,必须先做畸变校正。建议你在标定时,一定把畸变系数算出来并应用。

3.4 离散化:图像 → 像素

图像坐标系是连续的(毫米),像素坐标系是离散的(像素)。转换很简单:

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

其中 dx、dy 是每个像素的物理尺寸,u0、v0 是图像中心点的像素坐标。

这里有个细节:像素坐标系的原点在左上角,u 轴向右,v 轴向下。而图像坐标系的原点在中心。这个偏移很多人会忘。

坐标系 原点 单位 维度
世界坐标系 自定义 米/毫米 3D
相机坐标系 光心 米/毫米 3D
图像坐标系 光轴与像平面交点 毫米 2D
像素坐标系 图像左上角 像素 2D

3.5 合在一起:相机内参和外参

把上面三步串起来,就得到了完整的投影方程:

s * [u, v, 1]^T = K * [R | T] * [X_w, Y_w, Z_w, 1]^T

这里:

  • K 是内参矩阵(包含 fx, fy, u0, v0)
  • [R | T] 是外参矩阵(刚体变换)
  • s 是尺度因子(就是 Z_cam)

内参是相机的固有属性,标定一次就能用很久。外参每次换位置都得重新算。

记住:内参把相机坐标系下的点映射到像素,外参把世界坐标系下的点映射到相机坐标系。两者缺一不可。

3.6 知识体系总览

下面这张图,是我自己整理的四坐标系变换流程。每次做项目前,我都会看一眼,防止自己走偏。

世界坐标系 3D (X_w, Y_w, Z_w) 相机坐标系 3D (X_c, Y_c, Z_c) 图像坐标系 2D (x, y) 毫米 像素坐标系 2D (u, v) 像素 刚体变换 R, T (外参) 投影变换 针孔模型 离散化 dx, dy, u0, v0 完整投影方程 s · [u, v, 1]^T = K · [R | T] · [X_w, Y_w, Z_w, 1]^T 内参K:fx, fy, u0, v0 | 外参[R|T]:旋转+平移 | s:尺度因子

3.7 实战中的几点提醒

  • 坐标系方向:不同软件对坐标轴的定义不一样。OpenCV 的相机坐标系是 Z 轴向前,而某些引擎是 Z 轴向上。导入导出时一定要确认。
  • 单位统一:世界坐标用毫米,内参的焦距也是毫米,像素尺寸也是毫米。单位不一致,结果全乱套。
  • 齐次坐标:用齐次坐标可以把旋转和平移统一成一个矩阵,计算起来方便很多。建议你代码里全程用齐次坐标。

调试小技巧:写一个函数,输入一个世界坐标点,输出对应的像素坐标。然后用这个函数验证你标定的内参和外参对不对。如果投影回去的点跟实际图像上的点偏差超过几个像素,说明标定有问题。

好了,坐标系和变换这部分,说白了就是「从三维世界到二维照片」的数学映射。搞懂了它,三维重建的骨架你就搭起来了。


公众号:蓝海资料掘金营,微信deep3321