当前位置: 首页 > news >正文

点云处理中obb算法原理和法向量求解方法

主要数学原理PCA

PCA(Principal Component Analysis,主成分分析)是数据分析中的一种重要技术,通过它可以将高维数据投影到低维空间,找到数据的主要结构。在点云分析中,PCA 可以帮助我们提取点云数据中的主成分方向法向量方向。接下来,我们将详细推导 PCA 的数学原理,特别是如何通过特征值分解来计算主成分方向和法向量方向。

1. 协方差矩阵的计算

假设我们有一个数据矩阵 X,其中每行代表一个样本(数据点),每列代表一个特征(维度)。设 X 是一个 n × m 的矩阵,其中 n 是样本数,m 是特征数。

X = [ x 11 x 12 … x 1 m x 21 x 22 … x 2 m ⋮ ⋮ ⋱ ⋮ x n 1 x n 2 … x n m ] X = \begin{bmatrix} x_{11} & x_{12} & \dots & x_{1m} \\ x_{21} & x_{22} & \dots & x_{2m} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \dots & x_{nm} \end{bmatrix} X= x11x21xn1x12x22xn2x1mx2mxnm

为了使得每个特征的均值为 0,我们需要对数据进行去均值化处理。对于每个特征列(每个维度),计算其均值,并从数据中减去该均值:

X ~ = X − X ˉ \tilde{X} = X - \bar{X} X~=XXˉ

其中,( \bar{X} ) 是每列(特征)的均值向量:

X ˉ = 1 n ∑ i = 1 n x i \bar{X} = \frac{1}{n} \sum_{i=1}^{n} x_i Xˉ=n1i=1nxi

然后,协方差矩阵 ( C ) 的计算公式为:

C = 1 n − 1 X ~ T X ~ C = \frac{1}{n-1} \tilde{X}^T \tilde{X} C=n11X~TX~

协方差矩阵 ( C ) 是一个 m × m 的方阵,它衡量了各个特征之间的相关性。矩阵的元素 ( C_{ij} ) 表示第 i 个特征与第 j 个特征之间的协方差。

2. 特征值分解

接下来,我们对协方差矩阵 ( C ) 进行特征值分解,得到其特征值和特征向量。特征值分解的目标是找到一个正交矩阵 ( V ) 和一个对角矩阵 Λ \Lambda Λ,使得:

C V = V Λ C V = V \Lambda CV=VΛ

其中:

  • ( V ) 是特征向量矩阵,每列是一个特征向量 ( v_i ),它们是数据的主成分方向。
  • Λ \Lambda Λ是特征值矩阵,对角线上的元素 ( l a m b d a i ) ( lambda_i ) (lambdai) 是每个特征向量对应的特征值,表示数据在该方向上的方差。

特征值分解得到的特征向量 ( v 1 , v 2 , … , v m ) ( v_1, v_2, \dots, v_m) (v1,v2,,vm) 表示数据方差最大的方向,特征值 $$ \lambda_1, \lambda_2, \dots, \lambda_m $$ 则表示在这些方向上的方差大小。

3. 排序特征值和特征向量

特征值 λ 1 , λ 2 , … , λ m \lambda_1, \lambda_2, \dots, \lambda_m λ1,λ2,,λm 按照从大到小的顺序排序。对应的特征向量 v 1 , v 2 , … , v m v_1, v_2, \dots, v_m v1,v2,,vm 也根据特征值的大小进行排序:

λ 1 ≥ λ 2 ≥ ⋯ ≥ λ m \lambda_1 \geq \lambda_2 \geq \dots \geq \lambda_m λ1λ2λm

  • 主成分方向:对应于最大的特征值 λ 1 \lambda_1 λ1的特征向量 v_1 表示数据的主要变化方向(即主成分方向)。
  • 法向量方向:对应于最小的特征值 λ m \lambda_m λm 的特征向量 v m v_m vm 表示数据变化最小的方向,通常对应于点云的法线方向。
4. 主成分方向和法向量方向
  • 主成分方向:数据方差最大的方向。它对应于协方差矩阵 ( C ) 中特征值最大的特征向量。这个方向通常表示数据的主轴,或者说是数据中方差最大的那条方向。数学上,它就是特征值分解中对应最大特征值的特征向量:

v 1 = argmax ( λ 1 ) v_1 = \text{argmax}(\lambda_1) v1=argmax(λ1)

  • 法向量方向:数据方差最小的方向。它对应于协方差矩阵 ( C ) 中特征值最小的特征向量,即 ( v_m ),通常表示数据的法线方向。法向量方向是数据变化最小的方向,通常与点云表面的法线方向对齐:

v m = argmin ( λ m ) v_m = \text{argmin}(\lambda_m) vm=argmin(λm)
pca主成分方向图

5. 数据投影

一旦我们找到了主成分方向和法向量方向,我们可以通过将原始数据投影到这些方向来实现数据的降维。假设我们得到的特征向量矩阵为 V = [ v 1 , v 2 , … , v m ] V = [v_1, v_2, \dots, v_m] V=[v1,v2,,vm],那么我们可以将原始数据投影到新的坐标系中,得到新的数据表示:

Y = X V Y = X V Y=XV
其中:

  • ( Y ) 是投影后的数据矩阵,表示原始数据在新坐标系下的表示。
  • ( V ) 是特征向量矩阵,其中每列是一个特征向量(即主成分方向)。

在投影后的数据 ( Y ) 中,第一列对应主成分方向,第二列对应次主成分方向,依此类推。我们可以选择前 ( k ) 个主成分来实现数据的降维。

点云数据中的应用:主成分方向与法向量

在点云数据处理中,主成分方向通常是点云的主轴,而法向量方向通常与点云表面或物体表面的法线方向对齐。通过计算协方差矩阵的特征值和特征向量,我们可以提取出这些关键的几何特征。

  • 主成分方向:反映了点云数据的主要分布方向,通常用于描述物体的长轴
  • 法向量方向:反映了数据在某个平面上的分布,它通常用于表示点云表面的法线方向

代码

1. 计算 OBB 包围框

OBB 是一个定向包围盒,可以紧密包围点云数据,并且它的方向与数据的主成分方向对齐。在 PCA 中,我们通过特征值分解得到的特征向量,可以用来构建 OBB 包围框。

代码示例:计算 OBB 包围框
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/moment_of_inertia_estimation.h>int main() {// 创建点云指针并加载点云数据pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("path_to_your_point_cloud.pcd", *cloud) == -1) {PCL_ERROR("Couldn't read file point_cloud.pcd\n");return -1;}// 计算点云的惯性矩估计pcl::MomentOfInertiaEstimation<pcl::PointXYZ> feature_extractor;feature_extractor.setInputCloud(cloud);// 执行惯性矩估计feature_extractor.compute();// 获取点云的 OBB 包围盒pcl::PointXYZ min_point, max_point;Eigen::Matrix3f rotation_matrix;feature_extractor.getOBB(min_point, max_point, rotation_matrix);// 输出 OBB 的信息std::cout << "OBB Min Point: (" << min_point.x << ", " << min_point.y << ", " << min_point.z << ")\n";std::cout << "OBB Max Point: (" << max_point.x << ", " << max_point.y << ", " << max_point.z << ")\n";std::cout << "Rotation Matrix (主成分方向): \n" << rotation_matrix << std::endl;return 0;
}

解释:

  1. 惯性矩估计pcl::MomentOfInertiaEstimation 类计算点云的惯性矩,用来估计点云的包围盒。这个类会利用 PCA 来计算点云的主成分方向。
  2. getOBB():该方法返回点云的 OBB 包围盒,包括包围盒的最小点 (min_point)、最大点 (max_point),以及包围盒的旋转矩阵 (rotation_matrix),旋转矩阵反映了点云的主成分方向。

2. 计算法向量

法向量通常是点云表面上某一点的方向,PCA 可以用来估计这些法向量。在每个点周围的邻域中计算主成分,PCA 的法向量方向是方差最小的方向。

代码示例:计算法向量
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>int main() {// 创建点云指针并加载点云数据pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("path_to_your_point_cloud.pcd", *cloud) == -1) {PCL_ERROR("Couldn't read file point_cloud.pcd\n");return -1;}// 创建法向量估计对象pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;ne.setInputCloud(cloud);// 使用搜索方法(例如 KdTree)来查找点云的邻域pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());ne.setSearchMethod(tree);// 估算法向量pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());ne.compute(*normals);// 输出法向量信息for (size_t i = 0; i < normals->points.size(); ++i) {std::cout << "Point " << i << ": Normal (" << normals->points[i].normal_x << ", " << normals->points[i].normal_y << ", " << normals->points[i].normal_z << ")\n";}return 0;
}

解释:

  1. 法向量估计pcl::NormalEstimation 类用于估计点云中的法向量。在每个点的邻域内,算法计算其主成分方向,并且法向量对应的是方差最小的特征向量。
  2. setSearchMethod:这里我们使用了 KdTree 方法来查找每个点的邻域,KdTree 是一种常用的空间查找结构,可以有效地查找点云中的邻居点。
  3. 法向量输出:输出每个点的法向量,即点云中每个点的主成分方向之一。

http://www.mrgr.cn/news/78676.html

相关文章:

  • 计算机网络--根据IP地址和路由表计算下一跳
  • 邻接表深度优先遍历和广度优先遍历计算方法
  • C#跨窗口传递Halcon图像/参数
  • 一种可复用的AI提效方案:AI点灯
  • 深入了解 SSL/TLS 协议及其工作原理
  • 数据结构-顺序表
  • PVE中VLAN的设置要点
  • 第十六届蓝桥杯模拟赛第二期题解—Java
  • 11 设计模式之代理模式(送资料案例)
  • 「Mac畅玩鸿蒙与硬件38」UI互动应用篇15 - 猜数字增强版
  • 2024前端面试经验分享
  • 【大模型实战篇】基于大模型GLM的Function Call实践
  • SQL进阶技巧:如何寻找同一批用户 | 断点分组应用【最新面试题】
  • 12 设计模式之工厂方法模式
  • 二叉搜索树讲解
  • 【C++笔记】位图和布隆过滤器
  • 开发一套ERP 第九弹 前后整合
  • burp2
  • 五:OpenStack环境准备-compute node
  • 芯片测试-射频中的单位
  • 腾讯阅文集团Android面试题及参考答案
  • AI - 如何构建一个大模型中的Tool
  • ⽂件操作详解
  • Day1 生信新手笔记
  • 如何估算自然对流传热系数
  • [GKCTF 2021]签到