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

news2024/12/1 13:37:55

主要数学原理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.coloradmin.cn/o/2251136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

shell编程7,bash解释器的 for循环+while循环

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

【人工智能】Python常用库-TensorFlow常用方法教程

TensorFlow 是一个广泛应用的开源深度学习框架&#xff0c;支持多种机器学习任务&#xff0c;如深度学习、神经网络、强化学习等。以下是 TensorFlow 的详细教程&#xff0c;涵盖基础使用方法和示例代码。 1. 安装与导入 安装 TensorFlow&#xff1a; pip install tensorflow…

wxFormBuilder:可视化设计、学习wxWidgets自带UI控件的好工具

wxFormBuilder很快就能拼出一个界面&#xff0c;而且可以直接出对应的代码&#xff0c;拷贝到项目里小改一下就能用。

Vim操作

1. Vim的模式 2.正常模式->编辑模式 在上⽅插⼊⼀⾏&#xff1a; O在下⽅插⼊⼀⾏&#xff1a; o (open)在当前光标前插⼊&#xff1a; i在⾏⾸插⼊&#xff1a; I在当前光标后插⼊&#xff1a; a在⾏尾插⼊&#xff1a; A 3.常见命令行 1、拷贝当前行 yy ,拷贝当前行向下…

阿里云服务器(centos7.6)部署前后端分离项目(MAC环境)

Jdk17安装部署 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ 选择自己需要的jdk版本进行下载。 通过mac终端scp命令上传下载好的jdk17到服务器的/usr/local目录下 scp -r Downloads/jdk-17.0.13_linux-x64_bin.tar.gz 用户名服务器ip地址:/us…

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…

Python系列 - MQTT协议

Python系列 - MQTT协议 资源连接 MQTT的介绍和应用场景的示例说明 一、什么是MQTT 百度关于MQTT的介绍如下&#xff1a; MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布订阅范式的消息协议。它工作在 TCP/IP协议之上&#xff0c;是为硬件性能低下的远程设…

ipad项目 蓝湖宽度

ipad项目 横屏状态时 蓝湖宽度设置930px media screen and (orientation: portrait) {/* 竖屏时的样式 */ } media screen and (orientation: landscape) {/* 默认是 横屏时的样式 */ }

理解Java集合的基本用法—Collection:List、Set 和 Queue,Map

本博文部分参考 博客 &#xff0c;强烈推荐这篇博客&#xff0c;写得超级全面&#xff01;&#xff01;&#xff01; 图片来源 Java 集合框架 主要包括两种类型的容器&#xff0c;一种是集合&#xff08;Collection&#xff09;&#xff0c;存储一个元素集合&#xff08;单列…

搭建深度学习框架+nn.Module

一、搭建项目框架&#xff08;YOLO框架的简约版本&#xff09; 最终成品的项目框架如下图&#xff0c;最终实现的效果&#xff0c;通过自己配置的框架函数&#xff0c;对模型进行定义与参数调配。同时在参数配置的过程中可选择是否进行模型初始化参数的使用。适用于YOLO框架的…

FFmpeg 简介与编译

1. ffmpeg 简介&#xff1a; FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec&#xff0c;为了保证高可移…

打latex公式可以练到像手写一样快吗?

这里分享两个Python Latex工具latexify和handcalcs。 latexify生成LaTeX 数学公式 import math import latexify @latexify.with_latex #调用latexify的装饰器 def solve(a, b, c):return (-b + math.sqrt(b**2 - 4*a*c)) / (2*a)solve 更多例子.......

【Linux】磁盘 | 文件系统 | inode

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 模电好难啊&#xff…

AntFlow 0.20.0版发布,增加多数据源多租户支持,进一步助力企业信息化,SAAS化

传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大&#xff0c;也被企业广泛采用&#xff0c;然后也存着在诸如学习曲线陡峭&#xff0c;上手难度大&#xff0c;流程设计操作需要专业人员&#xff0c;普通人无从下手等问题。。。引入工作流引擎往往需要企业储…

Scrapy管道设置和数据保存

1.1 介绍部分&#xff1a; 文字提到常用的Web框架有Django和Flask&#xff0c;接下来将学习一个全球范围内流行的爬虫框架Scrapy。 1.2 内容部分&#xff1a; Scrapy的概念、作用和工作流程 Scrapy的入门使用 Scrapy构造并发送请求 Scrapy模拟登陆 Scrapy管道的使用 Scrapy中…

洛谷 B3626 跳跃机器人 C语言 记忆化搜索

题目&#xff1a; https://www.luogu.com.cn/problem/B3626 题目描述 地上有一排格子&#xff0c;共 n 个位置。机器猫站在第一个格子上&#xff0c;需要取第 n 个格子里的东西。 机器猫当然不愿意自己跑过去&#xff0c;所以机器猫从口袋里掏出了一个机器人&#xff01;这…

docker快速部署gitlab

文章目录 场景部署步骤默认账号密码效果 场景 新增了一台机器, 在初始化本地开发环境&#xff0c;docker快速部署gitlab 部署步骤 编写dockerfile version: 3.7services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwayshostname: gitlabenviron…

计算机视觉工程师紧张学习中!

在当今这个日新月异的科技时代&#xff0c;计算机视觉作为人工智能的重要分支&#xff0c;正以前所未有的速度改变着我们的生活和工作方式。为了紧跟时代步伐&#xff0c;提升自我技能&#xff0c;一群怀揣梦想与热情的计算机视觉设计开发工程师们聚集在了本次线下培训活动中。…

RabbitMq死信队列(详解)

死信队列的概念 死信(dead message)简单理解就是因为种种原因&#xff0c;无法被消费的信息&#xff0c;就是死信。 有死信&#xff0c;自然就有死信队列。当消息在⼀个队列中变成死信之后&#xff0c;它能被重新被发送到另⼀个交换器中&#xff0c;这个交换器就是DLX( Dead L…

30分钟学会正则表达式

正则表达式是对字符串操作的一种逻辑公式&#xff0c;就是用事先定义好的一些特定字符、及这些特定字符的组合&#xff0c;组成一个“规则字符串”&#xff0c;这个“规则字符串”用来表达对字符串的一种过滤逻辑。 作用 匹配 查看一个字符串是否符合正则表达式的语法 搜索 正…