4、齐次坐标:为什么引入齐次坐标?齐次坐标的数学原理

说到坐标变换,很多初学者都会卡在一个地方——齐次坐标。

我第一次接触这个概念时,心里也犯嘀咕:好好的三维坐标不用,非要搞个四维?这不是自找麻烦吗?

后来在实际项目中踩了坑,才明白这玩意儿有多重要。今天我就跟你聊聊,齐次坐标到底解决了什么问题,它的数学原理又是什么。

4.1 一个绕不开的痛点

先问你一个问题:在三维空间中,我们能不能用一个矩阵,同时完成旋转、缩放和平移?

你可能会说:当然可以啊,不就是把变换矩阵乘起来吗?

嗯,问题就在这里。

旋转和缩放可以用 3×3 矩阵表示,但平移不行。平移本质上是加法,不是乘法。你想想看:

  • 旋转:p' = R · p(乘法)
  • 缩放:p' = S · p(乘法)
  • 平移:p' = p + t(加法)

这就尴尬了。如果你想把旋转、缩放、平移组合成一个变换,就得先做乘法,再做加法。没法用一个矩阵搞定。

核心矛盾:3×3 矩阵只能表示线性变换(旋转、缩放、剪切),无法表示平移这种仿射变换。

我在做机器人运动学仿真时,就遇到过这个问题。当时要计算机械臂末端执行器的位姿,需要把多个关节的旋转和平移串起来。如果用 3×3 矩阵,每做一次平移就得单独加一个向量,代码写起来又臭又长,还容易出错。

4.2 齐次坐标的解决方案

那怎么办?

聪明的前辈们想了一个办法:升维。

把三维坐标 (x, y, z) 变成四维坐标 (x, y, z, w),其中 w 通常取 1。这就是齐次坐标。

这样一来,平移也能写成矩阵乘法的形式了:

// 三维平移 (tx, ty, tz) 的齐次矩阵
| 1  0  0  tx |
| 0  1  0  ty |
| 0  0  1  tz |
| 0  0  0  1  |

你看,平移变成了矩阵乘法。旋转和缩放也升级成 4×4 矩阵:

// 绕 Z 轴旋转 θ 角的齐次矩阵
| cosθ  -sinθ  0  0 |
| sinθ   cosθ  0  0 |
| 0      0     1  0 |
| 0      0     0  1 |

// 缩放 (sx, sy, sz) 的齐次矩阵
| sx  0   0   0 |
| 0   sy  0   0 |
| 0   0   sz  0 |
| 0   0   0   1 |

现在,所有变换都可以用矩阵乘法统一表示了。组合变换就是矩阵相乘,简单粗暴。

我的习惯:在写仿真代码时,我一般把所有变换都统一成 4×4 齐次矩阵。这样代码结构清晰,调试也方便。你想想看,如果变换链里有 10 个步骤,用齐次坐标就是连乘 10 个矩阵,一步到位。

4.3 齐次坐标的数学原理

齐次坐标的本质,是把 仿射变换 转化为 线性变换。

仿射变换的通用形式是:

p' = A · p + b

其中 A 是 3×3 矩阵(旋转+缩放),b 是平移向量。

引入齐次坐标后,变成:

| p' |   =   | A  b |   ·   | p |
| 1  |       | 0  1 |       | 1 |

说白了,就是把平移向量塞进矩阵的最后一列,用额外的维度 w=1 来承载它。

这里有个细节要注意:齐次坐标的 w 分量不一定总是 1。当 w ≠ 1 时,对应的三维坐标是 (x/w, y/w, z/w)。这个操作叫归一化。

我曾经踩过的坑:在做相机投影变换时,w 分量会变成深度值。如果不做归一化就直接用,坐标会完全错乱。记住:在把齐次坐标转回三维坐标之前,一定要除以 w。

4.4 齐次坐标的几何意义

从几何角度看,齐次坐标其实是在描述射影空间中的点。

在三维欧氏空间中,平行线永不相交。但在射影空间中,平行线在无穷远处相交。齐次坐标恰好能表示这个「无穷远点」——当 w = 0 时,对应的就是方向向量,表示无穷远处的点。

举个例子:

  • (1, 2, 3, 1) 表示三维空间中的点 (1, 2, 3)
  • (1, 2, 3, 0) 表示方向向量 (1, 2, 3),没有位置信息

这个特性在仿真中很有用。比如你要表示一个光源的方向,用 w=0 的齐次坐标,变换时就不会被平移影响。

4.5 知识体系总览

下面这张图帮你理清齐次坐标的核心逻辑:

齐次坐标知识体系 核心问题 平移无法用3×3矩阵表示 解决方案 升维:3D → 4D齐次坐标 结果 统一为矩阵乘法 数学原理 几何意义 工程应用 仿射变换 → 线性变换 p' = A·p + b ↓ 升维 |p'| = |A b| · |p| |1 | |0 1| |1| 射影空间中的点 w=1:普通点 w=0:方向向量 w≠1:需归一化 (x/w, y/w, z/w) 仿真中的典型场景 • 机器人运动学 • 相机投影变换 • 3D图形渲染 • 多坐标系变换链 一句话总结 齐次坐标通过升维,把仿射变换统一成线性变换 让所有坐标变换都能用矩阵乘法一步完成

4.6 代码示例:用齐次坐标做变换

下面我用 Python 演示一下,齐次坐标怎么用:

import numpy as np

# 定义一个点 (2, 3, 4)
p = np.array([2, 3, 4, 1])  # 齐次坐标,w=1

# 定义平移矩阵:沿 X 轴移动 5 个单位
T = np.array([
    [1, 0, 0, 5],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1]
])

# 定义旋转矩阵:绕 Z 轴旋转 90 度
theta = np.pi / 2
R = np.array([
    [np.cos(theta), -np.sin(theta), 0, 0],
    [np.sin(theta),  np.cos(theta), 0, 0],
    [0,              0,             1, 0],
    [0,              0,             0, 1]
])

# 组合变换:先旋转,再平移
M = T @ R  # 矩阵乘法

# 应用变换
p_transformed = M @ p

# 归一化
p_result = p_transformed[:3] / p_transformed[3]

print(f"原始点: {p[:3]}")
print(f"变换后: {p_result}")
# 输出: 原始点: [2 3 4]
#       变换后: [-3.  2.  4.]

我的建议:在实际项目中,尽量用现成的库(比如 NumPy、Eigen、GLM)来处理齐次坐标。手写矩阵运算容易出错,尤其是符号和角度方向。我早期做仿真时,就因为旋转方向搞反了,调试了整整一个下午。

4.7 小结

齐次坐标的核心价值就一句话:用升维换统一。

  • 把 3D 坐标升到 4D,平移就变成了矩阵乘法
  • 所有变换(旋转、缩放、平移、投影)都能用 4×4 矩阵表示
  • 组合变换就是矩阵连乘,简单、高效、不易出错

嗯,这就是齐次坐标。下次你在仿真代码里看到 4×4 矩阵时,应该能明白它为什么存在了。

记住:齐次坐标不是数学家的玩具,它是工程实践中解决「变换统一」问题的利器。用好它,你的仿真代码会干净很多。

可可精品资料库