Camera-to-World
在 3D 图形学中,我们不能仅仅依靠相机本身的视角来定位物体。因为相机会平移、会旋转,如果以相机中心为原点(相机坐标系),整个世界就都在跟着乱晃。我们需要一个固定不变的参考系——世界坐标系(World Coordinate System)。
变换矩阵
我们需要在“世界”和“相机”之间建立一座桥梁。这座桥梁就是变换矩阵(Transformation Matrix)。
相机到世界矩阵 (Camera-to-World Matrix)
这个矩阵描述了相机在世界中的位置和姿态。它是一个
- 左上角的
3 \times 3 区域 (R ):负责旋转(Rotation)。它决定了相机是朝前看、朝天上看,还是歪着头看。 - 最后一列的前3个元素 (
t ):负责平移(Translation)。它代表了相机在世界坐标系中的x, y, z 具体位置。 - 最后一行:永远是
[0, 0, 0, 1] ,为了数学运算上的补齐(构建齐次坐标)。
世界到相机矩阵 (World-to-Camera Matrix)
我们的点云原本是用世界坐标系的
将一个点从相机坐标系转换到世界坐标系,公式为:
R :相机到世界的旋转矩阵。t :相机到世界的平移向量。
现在,我们的目标是把上面的等式反过来,也就是已知
首先,把
接着,在等式两边同时左乘
把括号展开,我们得到:
代码实现
理论懂了,接下来进行代码编写。我们要用 PyTorch 进行矩阵乘法,完成坐标系的转换。
假设我们的点云数据 PC 形状是
第一步:构建世界到相机矩阵 (World-to-Camera Matrix)
要将物体投影到相机视野中,我们首先需要从输入的相机到世界矩阵 (camera2world) 中,推导出 世界到相机矩阵 (world2camera)。
- # 1. 从 camera2world 提取旋转 R 和平移 t
- R = camera2world[:3, :3]
- t = camera2world[:3, 3]
- # 2. 计算 R 的转置
- R_t = R.t()
- # 3. 计算世界到相机转换的平移向量:t_w2c = -R_t @ t
- t_w2c = -R_t @ t
- # 4. 构造世界到相机的变换矩阵 world2camera
- world2camera = torch.eye(4, dtype=camera2world.dtype, device=camera2world.device)
- world2camera[:3, :3] = R_t
- world2camera[:3, 3] = t_w2c
第二步:构建齐次坐标
我们构造出来的 world2camera 变换矩阵是
根据矩阵乘法“前列等于后行”的规则,我们无法直接用
- # 5. 点云拼上最后一列 1
- ones = torch.ones((PC.shape[0], 1), dtype=PC.dtype, device=PC.device)
- PC_homo = torch.cat([PC, ones], dim=1)
第三步:执行矩阵乘法与空间变换
现在我们有了
- 我们先将点云转置,使其形状变为
4 \times N 。 - 执行矩阵乘法:
(4 \times 4) \times (4 \times N) \rightarrow 结果形状为4 \times N 。 - 再次转置回来,恢复为
N \times 4 。 - 最后舍弃最后一列(即没用的尾巴),只保留全新的前三列
(x, y, z) ,恢复到N \times 3 的形状。
- # 6. 利用变换矩阵变换点云
- PC_cam = (world2camera @ PC_homo.t()).t()[:, :3]
同样我们改变相机位置,进行可视化验证。完整的可视化代码可以查看 Commit 89087d7:visualize_camera_transformation.py。