前视相机里,一个行人的脚落在像素 (860, 690)。他离车多远?只看这一个像素答不出来:投影把深度丢了,一个像素只对应一条射线。要把深度找回来,必须再加一个约束:已知这个点在某个平面上、有第二个视角,或者有学到的深度先验。 这篇用同一个点走完正向投影、反投影、畸变、两视图(view)和三角化,只需要线性代数。
待审核草稿。 这一篇还没有经过站主审阅,事实、取舍和措辞都可能修改;引用前请回到文中链接的一手资料核对。
一个点要经过哪几个坐标系
一个点要经过三个坐标系:
- 世界坐标(这里用车体坐标):x 向前、y 向左、z 向上,单位米。
- 相机坐标:原点在光心,x 向右、y 向下、z 沿光轴向前。这是视觉里常用的约定;换一套约定,下面的符号就要跟着换。
- 像素坐标:u 向右、v 向下,原点在图像左上角。
外参 $[R\mid t]$ 把世界坐标变到相机坐标,内参 $K$ 再把相机坐标投到像素:
$$ \lambda\begin{bmatrix}u\\v\\1\end{bmatrix}=K\,[R\mid t]\begin{bmatrix}X\\Y\\Z\\1\end{bmatrix},\qquad K=\begin{bmatrix}f_x&s&c_x\\0&f_y&c_y\\0&0&1\end{bmatrix}. $$
$f_x,f_y$ 是以像素为单位的焦距,$(c_x,c_y)$ 是主点,$s$ 是两条像素轴不垂直时的偏斜项,常取 0。$\lambda$ 就是这个点在相机坐标里的深度 $Z_c$:等式两边只差一个尺度,深度正是在这里丢掉的。Zhang 2000 第 2 节用的就是这个针孔模型(他把 $K$ 记作 $A$,技术报告版可免费读);Hartley & Zisserman 的第 9 章样章把相机矩阵写成 $P=K[R\mid t]$。
$R$ 把世界坐标轴转到相机坐标轴;$t=-RC$,其中 $C$ 是光心在世界坐标里的位置。把 $t$ 直接当成“相机装在哪”,是一个容易犯的错。
手算一次:从车体坐标到像素
设相机装在车体坐标 $C=(2,0,1.5)$:后轴前方 2 m、离地 1.5 m,光轴朝正前方。图像 1920×1080,$f_x=f_y=1000$,$(c_x,c_y)=(960,540)$,$s=0$。这些都是教学设定,不对应任何真车。
车体的“前、左、上”要变成相机的“右、下、前”:相机 x = −车体 y,相机 y = −车体 z,相机 z = 车体 x。于是
$$ R=\begin{bmatrix}0&-1&0\\0&0&-1\\1&0&0\end{bmatrix},\qquad t=-RC=\begin{bmatrix}0\\1.5\\-2\end{bmatrix}. $$
行人的脚在车体坐标 $X_w=(12,1,0)$:前方 12 m、偏左 1 m、在地面上。
- 外参:$X_c=RX_w+t=(-1,0,12)+(0,1.5,-2)=(-1,\,1.5,\,10)$,即相机左边 1 m、下方 1.5 m、前方 10 m,和直觉对得上。
- 除以深度:$(X_c/Z_c,\;Y_c/Z_c)=(-0.1,\;0.15)$,这叫归一化坐标。
- 内参:$u=1000\times(-0.1)+960=860$,$v=1000\times0.15+540=690$。
像素是 (860, 690)。每次只改一个条件再算:
| 改一个条件 | 像素变成 | 说明什么 | 不能据此推出 |
|---|---|---|---|
| 行人远一倍:$X_w=(22,1,0)$ | (910, 615) | 离图像中心的偏移按 $1/Z_c$ 缩小 | 只看框的大小就能测距(还要知道物体的真实尺寸) |
| 焦距加倍:$f=2000$ | (760, 840) | 偏移和焦距成正比 | 换长焦,单张图就保住了深度 |
| 同一位置、离地 0.5 m 的点 | (860, 640) | 点越高,v 越小 | 像素越靠上,点就越远(只有都在地面上才成立) |
| 相机俯仰变 1°(例如过减速带) | v 约 672 或 708 | 外参的小误差会让像素挪约 18 px | 出厂标定一次就够了 |
反过来:一个像素只给一条射线
反投影先用 $K^{-1}$ 去掉内参:
$$ \begin{bmatrix}x_n\\y_n\\1\end{bmatrix}=K^{-1}\begin{bmatrix}u\\v\\1\end{bmatrix} =\begin{bmatrix}(860-960)/1000\\(690-540)/1000\\1\end{bmatrix} =\begin{bmatrix}-0.1\\0.15\\1\end{bmatrix},\qquad X_c=Z_c\begin{bmatrix}x_n\\y_n\\1\end{bmatrix}. $$
$Z_c$ 取任何正数,投影都落在同一个像素上。要定下它,有三条路:
- 已知平面。 假设这个点在地面上。相机离地 1.5 m、y 轴朝下,地面就是 $Y_c=1.5$,于是 $0.15\,Z_c=1.5$,$Z_c=10$ m,答对了。但离地 0.5 m 的那个点在 v=640,套同一个假设会得到 $Z_c=1.5/0.1=15$ m,远了 50%。平面假设只对真的在平面上的点成立。
- 第二个视角。 两条射线相交处就是这个点,见下面的三角化。
- 学到的先验。 单目深度网络从大量图像里学“东西一般有多远”。相对深度只给远近和比例,度量深度才给米;这些模型放在第 4 篇。
表里那个 1° 俯仰,在地面假设下会把 10 m 变成约 8.9 m 或 11.3 m(看俯仰方向)。所以靠地面平面测距的系统,要么实时估计相机俯仰,要么换一条不依赖地面的线索。
镜头畸变:越靠边越不准
真实镜头不是理想针孔。Zhang 2000 第 3.3 节只取径向畸变的前两项,作用在归一化坐标上:
$$ \breve x=x\,(1+k_1r^2+k_2r^4),\qquad \breve y=y\,(1+k_1r^2+k_2r^4),\qquad r^2=x^2+y^2. $$
取 $k_1=-0.2$、$k_2=0$(桶形畸变,教学数值)。我们的点 $r^2=0.0325$,系数 0.9935,像素只挪约 0.65 px 和 1 px。换成靠近右边缘的点 $(0.9,\,0.5)$:$r^2=1.06$,系数 0.788,u 从 1860 变成约 1669,差了约 190 px。
所以要先去畸变,再套针孔公式。广角和鱼眼镜头需要专门的相机模型,例如 ORB-SLAM3 同时支持针孔和鱼眼两种模型。3D Gaussian splatting 的原始光栅化假设理想针孔,NVIDIA 的 3DGUT 专门把畸变和卷帘快门相机接进来(论文给的是定性说法)。
标定就是估计 $K$、畸变系数和外参。Zhang 的方法只要求相机从至少两个不同朝向看一张平面图案,先闭式求解,再用最大似然做非线性优化。多传感器还要标定时间偏移:车速 20 m/s 时,10 ms 的时间差就是 0.2 m 的位置差;Furgale 等人 2013 把时间和空间一起标定。
两个视角:对极约束把搜索从平面变成一条线
加第二台相机:同样的 $K$,向右平移 0.5 m,不旋转,组成一对双目。在第一台相机的坐标里,第二台的 $R=I$、$t=(-0.5,0,0)$。同一个点在它的坐标里是 $(-1.5,\,1.5,\,10)$,像素是 (810, 690)。
不知道深度时,第一张图里的点会落在第二张图的哪里?那条射线在第二张图里投成一条线,叫极线。用本质矩阵(essential matrix)写:
$$ E=[t]_\times R,\qquad [t]_\times=\begin{bmatrix}0&-t_z&t_y\\t_z&0&-t_x\\-t_y&t_x&0\end{bmatrix},\qquad \hat x'^{\top}E\,\hat x=0, $$
$\hat x,\hat x'$ 是两张图里的归一化坐标(HZ 第 9 章式 9.11)。代入数字:$[t]_\times$ 只有第 2 行第 3 列是 0.5、第 3 行第 2 列是 −0.5,所以 $E\hat x=(0,\;0.5,\;-0.075)$;再和 $\hat x'=(-0.15,\,0.15,\,1)$ 点乘,$0.15\times0.5-0.075=0$,约束成立。
$E\hat x$ 本身就是第二张图里的极线:$0.5\,y'-0.075=0$,即 $y'=0.15$,像素行 $v'=690$。只要沿第 690 行找匹配,二维搜索就变成一维。
这是最简单的情况。相机有旋转时,极线是斜的;纯向前平移时,极点 $e'=K't$ 正好在主点上(HZ 式 9.3),所有极线从图像中心放射出去,行驶中的单目相机接近这种情况。不知道 $K$ 时,用像素坐标写基础矩阵 $F=K'^{-\top}EK^{-1}$,约束变成 $x'^{\top}Fx=0$。HZ 第 9 章给出 $F$ 有 7 个自由度、$E$ 有 5 个,并说明本质矩阵由 Longuet-Higgins 1981 引入计算机视觉(摄影测量文献里更早就有类似的矩阵),$F$ 是去掉“相机已标定”这个假设后的推广。
$E$ 或 $F$ 实际要从匹配点估计。每对匹配点给出 $F$ 的 9 个元素的一个线性方程,8 对以上就能线性求解(八点法),再强制秩为 2。Hartley 1997 的摘要说,先对匹配点坐标做一次平移和缩放的归一化,八点法的结果就能和当时最好的迭代算法相当。错误匹配要用 RANSAC 这类稳健方法剔除(Barfoot 第 2 版 5.4.1 节)。
三角化:把深度找回来
两条射线相交处就是三维点。双目这种只有水平平移的情况最好算:HZ 式 9.6 给出纯平移时 $x'=x+Kt/Z$,代入 $t=(-b,0,0)$ 得到
$$ d=u-u'=\frac{f\,b}{Z}\quad\Longrightarrow\quad Z=\frac{f\,b}{d}. $$
我们的点视差 $d=860-810=50$ px,$Z=1000\times0.5/50=10$ m,和开头对上了。
再看误差。$Z=fb/d$ 对 $d$ 求导,$|\partial Z/\partial d|=Z^2/(fb)$。在 10 m 处,视差错 1 px,深度错 0.2 m;在 40 m 处视差只有 12.5 px,错 1 px 深度就错 3.2 m。三角化的深度误差随距离平方增长,这是双目和多视图测距在远处变差的直接原因。加大基线(baseline) $b$ 或焦距 $f$ 能缓解,代价是近处两台相机的公共视野变小,两张图的外观差得更多,匹配更难。
一般情况(有旋转、多于两个视角)没有这么简洁的公式。有噪声时两条射线并不相交,通常先用线性方法求一个近似点,再最小化重投影误差:让三维点投回每张图时离观测像素最近。把相机位姿也一起放进这个最小二乘,就是 bundle adjustment(Barfoot 第 2 版 10.1 节),第 5 篇从这里接着讲。
什么时候一个 homography 就够
HZ 式 9.7 把第二张图的像素写成两项:$x'=K'RK^{-1}x+K't/Z$。第一项只和旋转、内参有关,第二项随深度 $Z$ 变。哪一项消失或者变得可预测,决定了要用哪种关系:
| 情况 | 两张图之间的关系 | 自由度 | 例子 |
|---|---|---|---|
| 所有点都在一个平面上 | 点到点:$x'=Hx$,$H$ 是 3×3 | 8 | 地面、标定板、文档;Zhang 标定用 $H=K[r_1\;r_2\;t]$ |
| 相机只转不移,$t=0$ | 点到点:$x'=K'RK^{-1}x$,和深度无关 | 由 $K,K',R$ 决定 | 原地转动拍全景 |
| 有平移,场景有起伏 | 点到线:$x'^{\top}Fx=0$ | $F$ 为 7,$E$ 为 5 | 双目、行驶中的单目、机械臂上的相机 |
前面的地面测距用的就是第一行:地面上的点和像素一一对应,点一离开地面就失效。
截至 2026-10:几何没有过时,只是换了算的人
2025–2026 年,前馈三维模型一次前向就能输出相机内外参、深度和点图。VGGT 获 CVPR 2025 最佳论文,作者报告不到 1 秒完成重建;CVPR 2026 最佳论文给了做动态 4D 重建的 D4RT(CVPR 2026 闭幕页)。这些模型输出的仍然是本篇的 $K$、$[R\mid t]$ 和深度;读懂、检查和使用它们,还得靠这一篇的几何。细节见第 4 篇。
这一层也是公开岗位描述里会直接写出来的知识:我们在 2026-10-15 读到的 13 份车、机器人方向的公开岗位描述里,约 5 份点名三维几何视觉、SLAM/VIO、传感器融合或 BEV,有的直接写出针孔模型和对极几何(只汇总知识领域,不点名公司)。
继续读:HZ 样章(第 9 章对极几何免费)、Szeliski 第 2 版(个人使用可免费下载)、CMU 16-385 和 16-822 的课程页。下一篇:状态估计与跟踪。
本页术语 2
- 视图 view
- 同一个对象的一种侧面表示;用户可以同时有画像视图和历史视图
- 基线 baseline
- 用来比较新方法的参考方法或配置