简介
主成分分析(Principal Component Analysis, PCA)是三维点云处理中最基础也最核心的数学工具。它贯穿了法向量估计、点云降噪、特征提取、数据压缩等几乎所有点云算法。
PCA 的核心思想是:找到一个方向,使得数据点在该方向上的投影方差最大。投影方差越大,意味着数据在该方向上的"展开程度"越高,保留的信息越多。
主成分分析的应用包括:
- 降维:将高维数据投影到特定方向,保留原始信息分布。
- 法向量估计:与PCA方法类似。
- 分类:PCA及核PCA可用于分类任务,无需依赖深度神经网络。
- 关键点检测
- 特征点描述
一、物理直觉:投影与方差
1.1 向量内积与投影
两个向量 和 的内积(点积)定义为:
当 为单位向量()时,内积 恰好等于 在 方向上的标量投影。

1.2 从单点内积到矩阵乘法
当我们将单个点的内积推广到包含 个数据点的矩阵 (矩阵的每一行代表一个中心化后的数据点 )时:
- 行视角(投影物理意义):方向向量 依次作用于(点积于)数据矩阵的每一行(每个数据点),一次性批量计算出所有数据点在该方向上的标量投影。
- 列视角(线性组合视角):若将矩阵按特征列写成 ,则 ,即数据矩阵各特征列按 的分量进行线性组合。
1.3 最大投影方差 = 最多信息
在二维和三维情况下,主成分分析的物理意义是将数据点投影到具有特征性的方向上。每个数据点在该向量上的投影即为该方向的主成分。三维情况下,椭圆的三个轴即为其主成分。

二、数学推导:从优化问题到特征值分解
2.1 数据中心化
给定 个 维数据点 ,首先计算均值并中心化:
中心化后的数据矩阵记为:
2.2 协方差矩阵
中心化数据的协方差矩阵定义为:
协方差矩阵是一个实对称半正定矩阵,其对角元素是各维度的方差,非对角元素是两两维度间的协方差。
对于三维点云数据(),协方差矩阵为一个 的对称矩阵:
2.3 转化为瑞利商最优化问题
数据点 在单位方向 上的投影为 ,投影方差为:
第一主成分的优化问题是:
这正是经典的瑞利商 (Rayleigh Quotient) 极值问题。根据线性代数理论(详细推导参见 [00-核心概念辨析与扩展知识补充 (数学先修课)](file:///i:/Nutstore/1/blog/point-cloud/00-supplementary-knowledge.md)),在单位球面约束下, 的极值只能在 的特征向量处取得:
- 要使投影方差最大,方向 必须是 的最大特征值对应的特征向量。
2.5 主成分的完整结论
对协方差矩阵 进行特征值分解:
其中 (按降序排列), 为正交矩阵。
三、SVD 与 PCA 的等价性
3.1 奇异值分解(SVD)
任意矩阵 都可以进行奇异值分解:
其中:
- :左奇异向量矩阵(正交)
- :奇异值对角矩阵
- :右奇异向量矩阵(正交)
3.2 SVD 的几何意义
矩阵乘法 可以理解为三步变换:旋转 → 缩放 → 再旋转。

3.3 SVD 与 PCA 的联系
协方差矩阵可以写成:
因此:
- SVD 的右奇异向量 就是 PCA 的主成分方向(特征向量)
- SVD 的奇异值的平方除以 就是 PCA 的特征值(方差)
在实际计算中,NumPy 的 np.linalg.svd 比 np.linalg.eigh 在数值稳定性上通常更好。
四、PCA 降维与数据压缩
4.1 降维公式
选取前 个主成分(),将数据从 维降到 维:
其中 。
重构(近似还原)公式为:

4.2 信息保留率
前 个主成分保留了多少信息,可以用累积方差贡献率衡量:
通常选择使贡献率达到 95% 或 99% 的 值。
4.3 图像压缩示例
以 像素的手写数字图片为例:
| 步骤 | 操作 | 维度 |
|---|---|---|
| 向量化 | 展开为行向量 | 维 |
| PCA 降维 | 选取前 个主成分 | 维 |
| 重构还原 | 维 |

五、Python 实现
import numpy as np
def pca(data, n_components=None):
"""
对数据矩阵执行 PCA。
:param data: N x d 的数据矩阵,每行是一个数据点
:param n_components: 保留的主成分数量,None 表示保留全部
:return: eigenvalues, eigenvectors, projected_data, mean
"""
# 1. 计算均值并中心化
mean = np.mean(data, axis=0)
centered = data - mean
# 2. 计算协方差矩阵
cov_matrix = np.cov(centered, rowvar=False)
# 3. 特征值分解 (eigh 保证实对称矩阵返回实数特征值)
eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix)
# 4. 按特征值降序排列
idx = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]
# 5. 选取前 n_components 个主成分
if n_components is not None:
eigenvectors = eigenvectors[:, :n_components]
# 6. 投影到主成分空间
projected = centered @ eigenvectors
return eigenvalues, eigenvectors, projected, mean
def reconstruct(projected, eigenvectors, mean):
"""从低维投影重构原始数据"""
return projected @ eigenvectors.T + mean
### 5.1 NumPy 基础实现 (2D 演示)
```python
# 生成带有相关性的二维数据
np.random.seed(42)
theta = np.pi / 6 # 旋转 30 度
R = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
raw = np.random.randn(200, 2) @ np.diag([3, 0.5]) # 长轴:短轴 = 6:1
data = raw @ R.T # 旋转
eigenvalues, eigenvectors, proj, mean = pca(data)
print("特征值 (方差):", eigenvalues)
print("第一主成分方向:", eigenvectors[:, 0])
print("第二主成分方向:", eigenvectors[:, 1])
print(f"第一主成分贡献率: {eigenvalues[0]/sum(eigenvalues)*100:.1f}%")5.2 工程实战:基于 PCA 提取点云的定向包围盒 (OBB)
在自动驾驶中,我们需要将聚类后的点云(如一辆汽车)用一个紧凑的 3D 框包围起来。这正是 PCA 的典型应用:通过 PCA 找到点云的三个主轴方向,以此构建定向包围盒 (Oriented Bounding Box, OBB)。
Open3D 内部已经利用 PCA 封装了这一功能:
import open3d as o3d
import numpy as np
# 1. 生成模拟的车辆点云 (长条形)
np.random.seed(0)
points = np.random.randn(1000, 3) @ np.diag([4.0, 1.8, 1.5]) # 长宽高
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
pcd.paint_uniform_color([0.6, 0.6, 0.6])
# 2. 利用 PCA 提取定向包围盒 (OBB)
# 底层逻辑:计算点云协方差矩阵 -> 特征值分解 -> 特征向量作为 OBB 的旋转矩阵
obb = pcd.get_oriented_bounding_box()
obb.color = (1, 0, 0) # 红色框
# 3. 提取轴对齐包围盒 (AABB, 不用 PCA,直接取 XYZ 极值) 作为对比
aabb = pcd.get_axis_aligned_bounding_box()
aabb.color = (0, 1, 0) # 绿色框
print("OBB 旋转矩阵 (即 PCA 的特征向量):")
print(obb.R)
# 可视化对比
# o3d.visualization.draw_geometries([pcd, obb, aabb])实战经验:对于自动驾驶中的车辆,OBB 比 AABB 紧凑得多,能准确反映车辆的真实朝向(Heading),这对于碰撞检测和轨迹预测至关重要。
六、PCA 在三维点云中的双重应用
在三维点云处理中,PCA 有两种截然不同的用法:
| 应用场景 | 选取的特征向量 | 物理含义 |
|---|---|---|
| 全局主方向提取 | 最大特征值 的特征向量 | 点云整体延展最开的方向(主轴) |
| 局部法向量估计 | 最小特征值 的特征向量 | 局部表面的法线方向(详见第五章) |
关键区分:不要混淆这两者!最大特征值方向是点云最"展开"的方向(切平面主轴),而最小特征值方向是点云最"薄"的方向(法线方向)。这个混淆是许多开源代码中最常见的 bug。
总结
| 概念 | 数学表达 | 物理意义 |
|---|---|---|
| 第一主成分 | 最大特征值的特征向量 | 数据方差最大的方向 |
| 第 主成分 | 第 大特征值的特征向量 | 与前 个正交的方差最大方向 |
| 特征值 | 第 主成分方向上的方差 | |
| 降维投影 | 保留前 个主成分的低维表示 | |
| 重构 | 从低维表示近似还原原始数据 |
下一章我们将学习 Kernel PCA(核主成分分析),解决 PCA 在非线性数据分布下的局限性。