第二章 坐标系与空间变换:车辆坐标系、相机坐标系、图像坐标系、世界坐标系定义及相互转换,外参内参标定基础

各位同学,欢迎来到第二章。

做BEV感知,说白了就是在做一件事:把不同传感器看到的东西,统一到一个“上帝视角”下。你想想看,摄像头看到的是2D图像,激光雷达看到的是3D点云,它们各自为政,怎么融合?

答案就是坐标系变换。这一章,我们就把这几个坐标系的关系彻底捋清楚。我当年刚入行时,被这四个坐标系绕得晕头转向,后来踩了不少坑才真正搞明白。今天咱们一次搞定。

2.1 四大坐标系定义

先给个直观印象。我们做自动驾驶,天天打交道的就这四个坐标系:

  • 世界坐标系:真实世界的绝对位置。比如经纬度+海拔,或者某个固定原点的笛卡尔坐标。它是“万物之锚”。
  • 车辆坐标系:以车为中心。通常原点在后轴中心,x轴朝前,y轴朝左,z轴朝上。这是车辆的“身体坐标系”。
  • 相机坐标系:以相机光心为原点。z轴沿着光轴朝前,x轴朝右,y轴朝下(注意,这里y轴方向跟车辆坐标系不同)。
  • 图像坐标系:就是像素坐标。原点在图像左上角,u轴向右,v轴向下。单位是像素。

核心要点:所有变换的终极目标,就是把世界坐标系下的一个3D点,映射到图像坐标系下的一个2D像素点。反过来,从2D像素反推3D位置,则需要深度信息。

2.2 坐标系之间的变换关系

咱们一步步来。先从最简单的开始。

2.2.1 世界坐标系 → 车辆坐标系

这其实就是一个刚体变换:旋转 + 平移。车辆在世界中运动,它的位姿由外参决定。

公式很简单:

P_vehicle = R * P_world + T

其中R是3x3旋转矩阵,T是3x1平移向量。R和T合起来就是车辆的外参。我在项目中遇到过,很多人把旋转矩阵和平移向量的顺序搞反,结果点云全飞了。记住:先旋转,再平移

2.2.2 车辆坐标系 → 相机坐标系

这也是刚体变换。相机安装在车上,它相对于车辆的位置是固定的。这个变换矩阵,就是相机的外参(相对于车辆)。

P_camera = R_cam_vehicle * P_vehicle + T_cam_vehicle

嗯,这里要注意:不同车型的相机安装位置差异很大。我见过一些方案,直接把相机外参写死,结果换了一辆车就全废了。所以,外参一定要做在线标定,或者至少要有离线标定流程。

2.2.3 相机坐标系 → 图像坐标系

这一步是透视投影,用到了相机内参

相机内参通常是一个3x3矩阵K:

K = [[fx,  0, cx],
     [ 0, fy, cy],
     [ 0,  0,  1]]

其中fx, fy是焦距(像素单位),cx, cy是光心偏移。

投影公式:

u = fx * (X_c / Z_c) + cx
v = fy * (Y_c / Z_c) + cy

说白了,就是把3D点除以深度Z,再乘以焦距,加上光心偏移。这就是针孔相机模型

个人经验:我建议你在做投影时,一定要检查Z_c是否为正。如果Z_c为负,说明点在相机后面,投影出来是错的。我曾经因为这个bug,调试了整整两天。

2.3 外参标定基础

外参标定,就是求R和T。常用的方法有:

  • 手眼标定:利用棋盘格,求解相机与机械臂(或车辆)之间的变换。
  • PnP方法:已知3D-2D对应点,求解相机位姿。OpenCV的solvePnP就是干这个的。
  • 在线标定:利用车道线、地面特征等,实时优化外参。这是量产方案的主流。

我简单说一下PnP的思路。假设你有一组3D点(世界坐标系下)和对应的2D像素点,那么:

// 伪代码
cv::Mat rvec, tvec;
cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
// rvec是旋转向量,tvec是平移向量

输出就是相机的外参。但要注意,solvePnP对噪声敏感,点越多越准。我一般至少用20个点。

2.4 内参标定基础

内参标定,就是求K和畸变系数。最经典的方法是张正友标定法

步骤很简单:

  1. 打印一张棋盘格,贴在平面上。
  2. 用相机从不同角度拍20-30张照片。
  3. 用OpenCV的calibrateCamera函数计算。
// 伪代码
cv::Mat cameraMatrix, distCoeffs;
std::vector<cv::Mat> rvecs, tvecs;
cv::calibrateCamera(objectPoints, imagePoints, imageSize, 
                    cameraMatrix, distCoeffs, rvecs, tvecs);

避坑指南:我曾经用一张不平整的棋盘格做标定,结果内参误差很大,导致后续所有投影都偏移了。所以,棋盘格一定要贴平,最好用玻璃板压着。另外,照片要覆盖整个视野,尤其是边缘区域。

2.5 从像素反推3D:BEV视角的关键

做BEV感知,我们经常需要把图像像素映射到地平面(z=0)上。这其实是逆透视变换(IPM)。

公式推导如下:

  1. 已知像素(u, v),内参K,外参[R|T]。
  2. 假设地面z=0,那么世界坐标系下的点P_w = [X, Y, 0, 1]^T。
  3. 投影方程:s * [u, v, 1]^T = K * [R|T] * [X, Y, 0, 1]^T。
  4. 解这个方程,就能求出X, Y。

说白了,就是利用地面约束,把2D像素提升到3D。这也是BEV视角能成立的前提——我们假设所有目标都在地面上。

核心公式

X = (u - cx) * Z / fx
Y = (v - cy) * Z / fy
// 其中Z是深度,由地面假设或雷达提供

2.6 本章小结

这一章内容不少,但都是基本功。我帮你总结一下:

  • 四个坐标系:世界、车辆、相机、图像。记住它们的定义和方向。
  • 变换流程:世界→车辆→相机→图像。每一步都是刚体变换或投影。
  • 内参外参:内参是相机本身的属性,外参是相机在空间中的位姿。
  • 标定方法:张正友法标内参,PnP或手眼标定标外参。
  • BEV关键:利用地面假设,从像素反推3D位置。

下一章,我们会把这些变换写成代码,实现一个完整的BEV投影管线。到时候你会看到,这些公式到底是怎么跑起来的。

好了,今天就到这里。有问题随时在群里问我。