Skip to content

简介 ​

主成分分析(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 主成分的完整结论 ​

对协方差矩阵 进行特征值分解:

其中 (按降序排列), 为正交矩阵。

特征值与主成分的对应关系λ1 ≥ λ2 ≥ ... ≥ λd ≥ 0第 1 主成分 v1→方差最大方向 (数据最展开的方向)第 2 主成分 v2→与 v1 正交的方差次大方向第 d 主成分 vd→方差最小方向 (对于表面点云即为法线方向)

三、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 实现 ​

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 封装了这一功能:

python
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 在非线性数据分布下的局限性。

基于 VitePress 强力驱动 | 记录技术与生活