射影几何与齐次坐标
针孔相机的投影要除以深度,是个非线性运算;铁轨在远处会相交,而"过两点的直线""两条直线的交点"在平行线面前又要分情况讨论。给每个点多添一个坐标 w,只在"差一个比例"的意义下看待它,这些麻烦一并消失:投影变成矩阵乘法,平行线交在无穷远点,连线与求交都是同一个叉积。本节把 5.3 节里"补一个 1"的小技巧扩展成射影几何,它是 DLT、单应、对极几何、三角化等后面所有算法的共同语言。
1为什么机器人需要它
10.1 节的针孔模型是 \(u = f_x X/Z + c_x,\ v = f_y Y/Z + c_y\)。分母里的 \(Z\) 使投影成为非线性映射:它不能写成一个矩阵乘法,不能把两个相机的变换连乘,也不能直接取逆。除此之外,你在图像里还会遇到这几件事:
- 平行线会相交。路面上的车道线、桌子的边、走廊的墙角线,在三维里互相平行,在图像里却汇聚到一个消失点。消失点的位置藏着相机的朝向,甚至焦距。
- 点和线的运算有特例。"过两点的直线""两条直线的交点",在普通坐标里要解方程组,还要单独讨论竖直线与平行线。
- 后面的算法都是线性代数。由 4 个角点求单应(10.5)、由 6 个点标定相机(10.4)、由 8 对点求基础矩阵(11.1)、两视图三角化(11.3):它们统统写成"\(A\mathbf h = \mathbf 0\),取零空间"(1.6、1.12),前提是先把问题写成齐次向量上的线性方程。
5.3 节已经用过齐次坐标:补一个 1,让平移也变成矩阵乘法。这一节把末位的数当作一个真正的坐标,并且不再要求它等于 1。这个小小的放松,就是射影几何的全部入口。
2直觉:射影平面 = 过原点的射线
让相机中心 \(O\) 位于原点,成像平面取 \(w = 1\)(10.1 节的归一化像平面,这里把光轴记作第三个坐标 \(w\))。从 \(O\) 出发的每一条射线恰好穿过成像平面一次,所以一个像点就是一条过原点的射线,这条射线上任何一个非零向量 \(\tilde{\mathbf x}=(x,y,w)\) 都可以代表它。把向量放大、缩小,甚至反号,射线没变,点就没变。要读出普通坐标,只需让射线与平面 \(w=1\) 相交:\((x/w,\ y/w)\)。
有意思的是平行于成像平面的射线(\(w=0\)):它们永远打不到平面,却仍然是射线,是齐次向量。这就是无穷远点,它的坐标 \((x,y,0)\) 记录的是方向。而且一族平行线恰好对应这样一个点:每条直线与原点张成一个平面,这一族平面共享同一条射线。下图先拖滑块看一个点,再切到"平行线"看这件事。
- 在"点"模式下把 \(\lambda\) 拖到负数:箭头反向了,可射线上的交点有没有动?这说明 \(\tilde{\mathbf x}\) 和 \(-\tilde{\mathbf x}\) 是什么关系?
- 把 \(\alpha\) 一路拖到 \(90^\circ\):交点飞向哪里?\(w\) 变成多少?此时读数里的"点"变成了什么?
射影平面 \(\mathbb P^2\) 就是 \(\R^3\) 中过原点的直线(射线)的集合。普通点是穿过 \(w=1\) 平面的射线,无穷远点是平行于它的射线,二者在代数上没有区别,只是 \(w\) 恰好为 0。"平行线交于无穷远"不是一个约定,而是一个事实:平行线族对应的平面共享一条射线。
3动手玩:连线、求交与对偶
在齐次坐标里,直线 \(ax+by+c=0\) 就是向量 \(\mathbf l=(a,b,c)\),点 \(\tilde{\mathbf x}\) 在直线上当且仅当 \(\mathbf l^{\top}\tilde{\mathbf x}=0\)。过两点 \(\mathbf a,\mathbf b\) 的直线必须与两者都"垂直"(内积为 0),而叉积恰好给出同时垂直于两个向量的向量(1.8 节),所以 \(\mathbf l=\mathbf a\times\mathbf b\)。两条直线的交点同理:\(\tilde{\mathbf x}=\mathbf l\times\mathbf m\)。连线与求交是同一个运算,只是把点和线的角色对调,这叫对偶。
下图拖动四个点:绿线过 \(\mathbf a,\mathbf b\),紫线过 \(\mathbf c,\mathbf d\),琥珀色点是它们的交点。读数里逐项验证了关联关系 \(\mathbf l^\top\mathbf a=0\) 等。点击"使 m ∥ l"让两线平行,再轻轻拖动一个点。
- 让两条线精确平行(点"使 m ∥ l",或自己拖到网格点上)。交点 \(\tilde{\mathbf x}\) 的第三个分量变成了什么?程序有没有除以它?
- 让交点先在画面很远的一侧,再慢慢转到另一侧(经过平行的位置)。交点是从无穷远"绕回来"的:射影平面是闭合的。
\(\mathbf l^\top\tilde{\mathbf x}=0\) 对 \(\mathbf l\) 和 \(\tilde{\mathbf x}\) 是对称的。读成"点在线上",叉积给出连线;读成"线过点",叉积给出交点。凡是一个关于点和线的射影定理,把"点"与"线"、"共线"与"共点"互换,得到的仍是定理。这也是为什么本课之后会反复出现"一个 3×3 矩阵既可以看作点到点的映射,又可以看作点到线的映射"(11.1 节的基础矩阵就是后者)。
4第二、第三视角:消失点与变换层级
消失点与地平线
三维里方向为 \(\mathbf d\) 的所有平行线,在相机坐标里的方向都是 \(R_{cw}\mathbf d\)。把"方向"当作 \(w=0\) 的齐次点 \((\mathbf d,0)\),投影矩阵作用上去,得到它们共同的像:消失点 \(\tilde{\mathbf v}=K R_{cw}\mathbf d\)(FIG 5 会验证)。几何上,过相机中心、平行于这族直线的那条射线,与像平面的交点就是消失点。地面上所有方向的消失点落在同一条线上,即地平线(地面的消失线);地平线是地面的无穷远线在图像里的像。
下图左边是三维场景:地面、一座"房子"、相机和三条过相机中心的射线(沿 \(x,y,z\) 方向),射线与像平面的交点就是消失点。右边是相机拍到的图像。地平线画的是 \(K^{-\top}\mathbf n_c\)(\(\mathbf n_c\) 为地面法向在相机系中的方向);读数里再用两个消失点的叉积算一遍,两者一致,即使其中一个消失点跑到无穷远,叉积公式依然成立。
- 把方位角调到 0°,让相机正对房子的一面。红色 \(x\) 线在图像里变成什么?\(\tilde{\mathbf v}_x\) 的 \(w\) 是多少?地平线还能算出来吗?
- 把俯仰调到 0°:地平线落在图像的哪一行?再把相机升到 4 m 以上,地平线动了吗,地面网格呢?
两个相互垂直的水平方向(\(x\) 和 \(y\))的消失点还满足 \(\tilde{\mathbf v}_x^\top\omega\,\tilde{\mathbf v}_y=0\),\(\omega=K^{-\top}K^{-1}\);主点已知、像素为方形时,这就是一行公式:\(f^2=-(\mathbf v_x-\mathbf c)\cdot(\mathbf v_y-\mathbf c)\)。读数里的 \(\hat f\) 正是这样算出来的,10.4 节会把它推广成标定方法。
变换的层级:保持什么,丢掉什么
平面上的 3×3 可逆矩阵 \(H\) 作用在齐次点上,叫射影变换(单应)。限制 \(H\) 的形状,得到越来越"刚"的子类:欧氏(刚体)→ 相似 → 仿射 → 射影。每放松一级,多丢掉一些几何性质,也多出几个自由度。下图让你亲手操作这四级,并实时测量哪些量还保持不变。最右的"四角点"模式直接拖动正方形的四个角,由 DLT 反求 \(H\),那就是 10.5 节的单应。
- 选"仿射",把"剪切 k"拉到 0.5 以上:哪几行变成 ✗?平行性呢?
- 选"射影",调 \(v_1\) 或 \(v_2\) 使左右两边在图像里交于有限远的一点(距离 < 8)。这个点是 \(H\) 作用下哪两条线的交点?地平线在哪?
- 选"四角点",把正方形拖成梯形。哪几行永远不会变成 ✗?
同一个三元组可以是:图像点(\(w\neq0\)),方向/消失点(\(w=0\)),直线(用 \(\mathbf l^\top\tilde{\mathbf x}=0\) 的方式读),或者相机坐标系里的射线(\(K^{-1}\tilde{\mathbf x}\),10.1 节的反投影)。区别在于怎么变换:点用 \(H\),线用 \(H^{-\top}\),射线用 \(K^{-1}\)。写代码时给它们分别起名字(甚至用不同的类型),能避免一大类 bug。
5再看数学
提示:悬停在公式中带底色的符号上,FIG 1 和 FIG 2 里对应的元素会被高亮。
齐次坐标与无穷远点
射影平面是非零 3-向量模掉"相差一个非零倍数"的等价关系:
三个数只有两个自由度(去掉一个整体比例)。\(w=0\) 的向量 \((x,y,0)\) 没有对应的普通点,它们是无穷远点,编码方向 \((x,y)\),也就是 5.3 节里"方向用 \((\mathbf d,0)\)"的那个 0。全体无穷远点构成一条线 \(\mathbf l_\infty=(0,0,1)\):\(\mathbf l_\infty^\top\tilde{\mathbf x}=w\)。注意 \(\lambda\) 可以是负数,\(\tilde{\mathbf x}\) 与 \(-\tilde{\mathbf x}\) 是同一个点。
直线、连线与求交
直线 \(ax+by+c=0\) 记作 \(\hl{l}{\mathbf l}=(a,b,c)\),同样只差一个比例。\((a,b)\) 是法向,当 \(\|(a,b)\|=1\) 时 \(\mathbf l^\top\tilde{\mathbf x}\)(\(w=1\))就是点到直线的带符号距离。点与线的关联、连线、求交:
验证:\(\tilde{\mathbf p}^\top(\tilde{\mathbf p}\times\tilde{\mathbf q})=0\),\(\tilde{\mathbf q}^\top(\tilde{\mathbf p}\times\tilde{\mathbf q})=0\)(叉积垂直于两个因子,1.8 节)。当 \(\tilde{\mathbf p}\sim\tilde{\mathbf q}\) 时叉积为 0,连线不唯一;当 \(\mathbf l\sim\mathbf m\) 时同理。这是唯一的退化情形,不再需要"平行""竖直"之类的分类。两条直线 \(ax+by+c_1=0\) 与 \(ax+by+c_2=0\) 平行,叉积为 \((c_2-c_1)\,(b,\,-a,\,0)\),正是方向 \((b,-a)\) 的无穷远点。叉积也是线性的:用 1.8 节的反对称矩阵(第 5 章里的 hat 映射)写成
于是"两个齐次向量表示同一点"可以写成线性方程 \([\mathbf a]_\times\mathbf b=\mathbf 0\)。这是比较齐次向量的正确方式,也是 DLT 的出发点(见下)。
点怎么变换,线怎么变换
可逆 3×3 矩阵 \(H\) 把点映成点:\(\tilde{\mathbf x}'=H\tilde{\mathbf x}\)。线不能直接用 \(H\),而要用 \(H^{-\top}\)。推导只要一行:点在线上的关系必须被保持,\(\mathbf l'^\top\tilde{\mathbf x}'=0\)。
第二个恒等式说:先变换两点再连线,等于先连线再用 \(H^{-\top}\) 变换。FIG 3 里的地平线是它的一个实例:\(K\mathbf r_1\times K\mathbf r_2=\det K\cdot K^{-\top}(\mathbf r_1\times\mathbf r_2)=\det K\cdot K^{-\top}\mathbf r_3\)。对二次曲线 \(\tilde{\mathbf x}^\top C\tilde{\mathbf x}=0\),同理 \(C'=H^{-\top}CH^{-1}\)(读数里不用,只作指针)。若 \(H\) 是纯旋转(\(R^{-\top}=R\)),线和点用同一个矩阵变换,你不会发现差别;刚体运动下的法向量也只按 \(R\) 旋转,同样看不出来。但齐次形式的平面在 \(T\in\mathrm{SE}(3)\) 下仍要用 \(T^{-\top}\)(平移会改变平面的常数项);一旦出现缩放、剪切或透视,差别立刻显现(见"误区 3")。
层级、自由度与不变量
| 类别 | H | 自由度 | 保持不变的量 |
|---|---|---|---|
| 欧氏 | \(\begin{bmatrix}R&\mathbf t\\ \mathbf 0^\top&1\end{bmatrix}\) | 3 | 长度、角度、面积 |
| 相似 | \(\begin{bmatrix}sR&\mathbf t\\ \mathbf 0^\top&1\end{bmatrix}\) | 4 | 角度、长度之比 |
| 仿射 | \(\begin{bmatrix}A&\mathbf t\\ \mathbf 0^\top&1\end{bmatrix}\) | 6 | 平行性、平行线段的长度比、面积比;\(\mathbf l_\infty\) 映到自身 |
| 射影 | \(\begin{bmatrix}A&\mathbf t\\ \mathbf v^\top&1\end{bmatrix}\) | 8 | 关联性(共线、共点)、交比 |
射影类的 \(H\) 有 9 个元素,去掉整体比例剩 8 个自由度。仿射类的最后一行是 \((0,0,1)\),\(\mathbf l_\infty\) 被映到自己,所以平行线仍然平行;射影类的 \(\mathbf v\neq\mathbf 0\),\(\mathbf l_\infty\) 被映成有限远的一条线 \(H^{-\top}\mathbf l_\infty\),这就是地平线(FIG 4 的琥珀色长虚线)。仿射部分 \(A\) 可以分解为旋转、各向异性缩放、旋转(SVD,1.12 节);FIG 4 中用 \(R(\theta)\begin{bmatrix}s_x&k\\0&s_y\end{bmatrix}\) 参数化。
交比:射影变换下仍然不变的"比"
长度比在射影变换下不保持,但共线四点的交比保持。设四点在其所在直线上的一维坐标为 \(t_1,\dots,t_4\):
一维射影变换是 \(t\mapsto(\alpha t+\beta)/(\gamma t+\delta)\),代入后 \(t_i'-t_j'=\det\cdot(t_i-t_j)/\big((\gamma t_i+\delta)(\gamma t_j+\delta)\big)\),分子分母里的 \(\det\) 与 \((\gamma t_i+\delta)\) 恰好抵消。交比是"图像里的尺子":已知三个点的真实间距,可以由图像上的四个点反推第四个点的位置(例如算出路面上某个标记的实际距离)。
相机是 \(\mathbb P^3\to\mathbb P^2\) 的线性映射
三维点也有齐次坐标 \(\tilde{\mathbf X}=(\mathbf X,1)\in\mathbb P^3\),平面是 4-向量 \(\boldsymbol\pi\)(\(\boldsymbol\pi^\top\tilde{\mathbf X}=0\)),无穷远平面是 \(\boldsymbol\pi_\infty=(0,0,0,1)\)。10.3 节的相机矩阵 \(P=K[R\,|\,\mathbf t]\) 是 3×4 矩阵:
第二个式子:无穷远点 \((\mathbf d,0)\) 的像只与 \(KR\) 有关,与平移无关,这就是消失点公式。第三个式子:\(P\) 的秩为 3,所以有一维零空间;相机中心是唯一被映成 \((0,0,0)\)(不是任何像点)的点,因此相机中心 = \(P\) 的右零向量(FIG 5 用 SVD 数值验证,1.12 节)。这里的 \(\lambda\) 是投影深度(带正负号:为负表示点在相机后面),所以在相机里符号是有意义的,下面"误区 2"会再谈。
为什么 DLT 是零空间问题
已知对应点 \(\tilde{\mathbf x}\leftrightarrow\tilde{\mathbf x}'\) 求 \(H\)。不能写 \(\tilde{\mathbf x}'=H\tilde{\mathbf x}\)(只差比例,\(\lambda\) 未知),而应写"平行"条件 \(\tilde{\mathbf x}'\times H\tilde{\mathbf x}=\mathbf 0\),它对 \(H\) 的 9 个元素 \(\mathbf h=(\mathbf h_1;\mathbf h_2;\mathbf h_3)\) 是线性的。设 \(\tilde{\mathbf x}'=(x',y',w')\):
三行里只有两行线性无关(叉积的三个分量满足一个线性关系),所以每对点提供 2 个方程;\(H\) 有 8 个自由度,因此4 对点(任意三点不共线)刚好够。把 \(n\) 对点的方程叠成 \(A\mathbf h=\mathbf 0\),\(\mathbf h\) 是 \(A\) 的零空间,噪声下取最小奇异值对应的右奇异向量(1.12 节)。因为未知量只定义到比例,必须约束 \(\|\mathbf h\|=1\),而不是 \(h_{33}=1\)(后者在 \(h_{33}\approx0\) 时出问题)。同样的做法对相机矩阵 \(P\)(11 个自由度,每个 3D–2D 点对 2 个方程,至少 6 对点,10.4 节)、基础矩阵 \(F\)(\(\tilde{\mathbf x}'^\top F\tilde{\mathbf x}=0\),一个线性方程,11.1 节)都成立。
6机器人中的它:地平线、车道线与"无穷远"
想象一台移动机器人(或一辆车)的前视相机,高度 \(h\),向下俯仰 \(\theta\)。两条车道线平行,向前延伸到无穷远。把车道线上的点写成 \(\tilde{\mathbf X}(w)=(\mathbf d+w\mathbf P_0,\ w)\),\(w=1/s\) 是"离得多远"的倒数:
\(w\) 取 1 时是近处的点;\(w\to0\) 时,点飞向无穷远,像素 \(\tilde{\mathbf x}(w)\) 沿一条直线收敛到 \(KR\mathbf d\),也就是消失点。它在 \(w=0\) 处平滑地"到达",因为齐次坐标把"走到无穷远"变成了 \(w=0\) 这个普通数值。拖动距离滑块,再改变车道的坡度和相机的俯仰:平路的消失点落在地平线上,上坡的消失点跑到地平线之上。左边同时用 SVD 数值求出 \(P\) 的零空间,核对相机中心。
- 把距离拖到 \(w\le0.01\)(100 m 以外):点距离消失点还有多少像素?它还在近处的车道线上吗?
- 把坡度 \(g\) 调到 0.1 以上(约 6° 上坡):消失点和地平线的关系变成了什么?这对"用消失点估计俯仰角"意味着什么?
车道线与路面平面:车道检测常用"逆透视映射"(IPM)把前视图变成俯视图,它就是一个由相机高度、俯仰和内参决定的单应;地平线决定了哪里是路面的尽头。由消失点估计姿态:室内走廊和楼宇环境(Manhattan 世界)里,三个正交方向的消失点给出相机的旋转,也能给出焦距,用于无标定相机的初始化。基准标记:AprilTag、ArUco 的角点与标记平面之间是一个单应,OpenCV 的 findHomography、warpPerspective、solvePnP 都建立在这套齐次坐标的工具上。SLAM 前端:ORB-SLAM 一类系统的单目初始化会同时估计单应和基础矩阵,并用 DLT 三角化地图点,这些都是本课的"零空间问题";OpenCV 提供 convertPointsToHomogeneous / convertPointsFromHomogeneous,Eigen 则是 .homogeneous() / .hnormalized()。图形学:GPU 里的裁剪坐标 \((x,y,z,w)\) 与"透视除法"正是同一件事(12.3 节)。tf / SE(3):ROS tf 里的坐标变换(常被当作 4×4 矩阵处理)是 5.3 节的刚体变换,其中的 1 不能随意缩放;这里的齐次坐标则允许任意缩放,二者形式相似,含义不同。
7常见误区
\(w=0\) 是合法的点(无穷远点),\(w\approx0\) 的点除出来是一个巨大的数,误差被整体放大。尽量把运算留在齐次形式里,最后才除,并在除之前检查 \(|w|\) 相对于 \(\|\tilde{\mathbf x}\|\) 是否足够大(FIG 2 的判据就是这样写的)。更微妙的是:射影变换不保持"线段"。一条线段若跨过 \(w=0\)(比如 FIG 4 里把 \(v_1\) 拉得很大),它的像不是一段,而是穿过无穷远的两段,画图时必须在 \(w\) 变号处断开。
\((2,4,2)\) 与 \((1,2,1)\) 是同一个点,\((-1,-2,-1)\) 也是,所以不能直接逐元素比较,也不能用 allclose。正确的做法是各自归一化后比较(并处理符号),或检查 \(\tilde{\mathbf a}\times\tilde{\mathbf b}\approx\mathbf 0\)。但在相机里符号有物理意义:\(P\tilde{\mathbf X}\) 的第三分量为负,说明点在相机后面,却会投影到画面里(针孔相机看不见,而射影几何并不知道)。需要区分前后时,要用"定向射影几何"的思路或单独检查深度("手性检查",11.1、11.4 节)。
线、平面、法向量要用 \(H^{-\top}\)。旋转矩阵碰巧满足 \(R^{-\top}=R\),所以只做旋转、或者只变换法向量时这个错误不会暴露(带平移的齐次平面照样需要 \(T^{-\top}\));一旦 \(H\) 含有缩放、剪切或透视(相机内参 \(K\)!),错误的线就不再过变换后的点。FIG 4 的"平行性"一行正是用 \(H^{-\top}\) 变换左右两条边再求交。验证方法永远是:变换后检查 \(\mathbf l'^\top\tilde{\mathbf x}'\approx0\)。
像素坐标是 \(10^3\) 量级而 \(w=1\),叠成 \(A\mathbf h=\mathbf 0\) 后各列数量级相差 \(10^6\),SVD 解出的 \(H\) 精度很差。DLT 之前要做 Hartley 归一化:把点平移到质心、缩放到平均距离 \(\sqrt2\)(10.5 节),做完再变换回来。另一个陷阱是两条几乎平行的线:它们的叉积很小,交点在很远处,位置对线的微小误差极度敏感(夹角为 \(\epsilon\) 时误差放大 \(1/\epsilon\) 倍)。消失点估计因此要用很多条线做最小二乘,而不是两条线求交。
5.3 节里 \(T\in\mathrm{SE}(3)\) 的 4×4 矩阵,最后一个分量必须保持 1:把 \(T\) 乘以 2,就不再是刚体变换。本节的 \(H\) 乘以任何非零常数都是同一个变换。反过来,用 SE(3) 的求逆公式 \(T^{-1}=[R^\top,-R^\top\mathbf t]\) 去求逆一个射影矩阵是错的,射影矩阵要用通用的 3×3 或 4×4 求逆。相机矩阵 \(P\) 的左 3×3 块也不是旋转(它是 \(KR\)),用 RQ 分解(如 OpenCV 的 decomposeProjectionMatrix)来拆分,而不是把它当成位姿。
8小练习
9延伸阅读
- R. Hartley & A. Zisserman, Multiple View Geometry in Computer Vision, 2nd ed., Cambridge University Press, 2004, Ch. 2 and Ch. 3 — 本课内容的标准出处:射影平面、对偶、变换层级、交比、三维射影几何;第 4 章的 DLT 与归一化
- Y. Ma, S. Soatto, J. Košecká & S. S. Sastry, An Invitation to 3-D Vision, Springer, 2004, Ch. 3 — 图像形成与透视投影的齐次坐标表述
- R. Szeliski, Computer Vision: Algorithms and Applications, 2nd ed., Springer, 2022, §2.1 — 几何基元与变换的层级,图文并茂的简明版本,可免费在线阅读
- J. Richter-Gebert, Perspectives on Projective Geometry, Springer, 2011 — 纯几何视角的射影几何,适合想理解"为什么对偶、交比成立"的读者
- J. Stolfi, Oriented Projective Geometry: A Framework for Geometric Computations, Academic Press, 1991 — 区分 \(\tilde{\mathbf x}\) 与 \(-\tilde{\mathbf x}\) 的"定向"射影几何,对应上面的误区 2