PCL 计算PFH并可视化【2024最新版】

264 篇文章 ¥19.90 ¥99.00
本文详细介绍了PCL库中的PFH(Point Feature Histograms)特征计算原理,包括邻域点集的参数直方图计算,以及算法的具体流程。PFH通过点与邻域点的空间差异和法向量信息建立多维直方图,对点云的局部几何特征进行描述,具有良好的姿态不变性和抗噪声能力。此外,文章还涵盖了PFH的计算过程,涉及邻域点的选取、坐标系定义和直方图构造。最后,文章提及了代码实现和结果展示部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

本文由CSDN点云侠原创,原文链接,首发于:2021年2月7日。博客长期更新,本文最近一次更新时间为:2024年10月10日,代码在PCL1.14.1测试通过。抄袭狗把自己当个狗!!!

一、 算法原理

1、原理概述

pcl::PFHEstimation

  • 无差别地计算邻域点集总体的参数直方图
  • 对关键点,获取它的近邻,并计算这些近邻点的所有成对组合关系的直方图
  • 用到近邻点的局部法向量信息
  • 计算速度慢,
<think>我们被要求计算PFH特征可视化,同时提供数学公式。根据引用[1][2][3],PFH(Point Feature Histograms)是一种描述点云局部几何特征的方法。与FPFH不同,PFH计算更全面但计算量更大。下面将分步骤说明。 ### 一、PFH算法原理 PFH通过描述点与其邻域点之间的几何关系来构建特征直方图。对于点云中的每个点,考虑其邻域内所有点对(包括该点自身与邻域点,以及邻域点之间的组合),计算这些点对的四个特征值,统计成直方图。 #### 数学公式推导 对于两个点$p_s$和$p_t$($p_s$为源点,$p_t$为目标点)及其法向量$\vec{n_s}$和$\vec{n_t}$,在点$p_s$上定义一个局部坐标系: - $u = \vec{n_s}$ - $v = (p_t - p_s) \times u$ - $w = u \times v$ 然后计算以下四个特征: 1. **角度特征1**:$\alpha = v \cdot \vec{n_t}$ 2. **角度特征2**:$\phi = u \cdot \frac{(p_t - p_s)}{\|p_t - p_s\|}$ 3. **角度特征3**:$\theta = \arctan(w \cdot \vec{n_t}, u \cdot \vec{n_t})$(注意:这里使用两个参数的arctan函数,即atan2) 4. **距离特征**:$d = \|p_t - p_s\|$ 但在实际应用中,通常忽略距离特征$d$,因为其对尺度敏感,而主要使用三个角度特征。每个特征被量化为b个区间(通常b=5,则总维度为$b^3=125$维)。 #### PFH计算步骤 1. 对于点云中的每个点$p$,找到其半径为$r$的邻域内所有点。 2. 对于邻域内每对点(包括$p$与邻域点$q_i$,以及邻域点$q_i$与$q_j$),计算上述三个角度特征$(\alpha, \phi, \theta)$。 3. 将这三个特征值分别分配到对应的直方图区间中(每个特征划分为b个bin)。 4. 统计所有点对的特征值,归一化得到该点的PFH描述子。 注意:PFH计算复杂度为$O(nk^2)$,其中$n$为点数,$k$为邻域内平均点数。 ### 二、PCL实现步骤 #### 1. 计算法线 首先需要估计点云中每个点的法线。 ```cpp #include <pcl/point_types.h> #include <pcl/features/normal_3d.h> pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 假设cloud已经填充了数据 pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud); ne.setRadiusSearch(0.05); // 法线估计的邻域半径 ne.compute(*normals); ``` #### 2. 计算PFH特征 使用PCLPFHEstimation类计算PFH特征。 ```cpp #include <pcl/features/pfh.h> pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs(new pcl::PointCloud<pcl::PFHSignature125>()); pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh; pfh.setInputCloud(cloud); pfh.setInputNormals(normals); pfh.setRadiusSearch(0.1); // PFH计算的邻域半径 // 可选:设置搜索方法(如KD树) #include <pcl/search/kdtree.h> pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); pfh.setSearchMethod(tree); pfh.compute(*pfhs); ``` #### 3. 关键参数说明 | 参数 | 说明 | |------|------| | `setRadiusSearch(r)` | 设置邻域搜索半径(影响特征描述能力) | | `setNrSubdivisions(b1, b2, b3)` | 设置三个角度特征的bin数(默认各5个) | ### 三、PFH特征可视化 #### 1. 直方图可视化 使用PCL的直方图可视化工具显示单个点的PFH特征。 ```cpp #include <pcl/visualization/histogram_visualizer.h> pcl::visualization::PCLHistogramVisualizer hist_vis; // 显示第index个点的PFH特征(共125维) int index = 100; hist_vis.addFeatureHistogram<pcl::PFHSignature125>(*pfhs, index); hist_vis.spin(); ``` #### 2. 点云颜色映射 将PFH特征值映射到点云颜色(例如,取前三个bin的值作为RGB): ```cpp #include <pcl/visualization/pcl_visualizer.h> pcl::visualization::PCLVisualizer viewer("PFH Viewer"); viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud"); // 创建自定义颜色处理器(取前三个特征作为RGB) pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>); colored_cloud->resize(pfhs->size()); for (size_t i = 0; i < pfhs->size(); ++i) { pcl::PointXYZRGB point; point.x = cloud->points[i].x; point.y = cloud->points[i].y; point.z = cloud->points[i].z; // 将前三个bin的值归一化到[0,255]作为RGB point.r = static_cast<uint8_t>(255 * pfhs->points[i].histogram[0]); point.g = static_cast<uint8_t>(255 * pfhs->points[i].histogram[1]); point.b = static_cast<uint8_t>(255 * pfhs->points[i].histogram[2]); colored_cloud->points[i] = point; } viewer.addPointCloud<pcl::PointXYZRGB>(colored_cloud, "colored_cloud"); viewer.spin(); ``` #### 3. 关键点特征展示 在关键点位置显示特征向量(通过文本标签): ```cpp // 假设已经提取了关键点 pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZ>); // ... 关键点提取代码 for (size_t i = 0; i < keypoints->size(); ++i) { // 在关键点位置添加文本标签(显示该点的PFH特征索引) std::stringstream ss; ss << "PFH_" << i; viewer.addText3D(ss.str(), keypoints->points[i], 0.02, 1,0,0, ss.str()); } ``` ### 四、应用场景 - **点云配准**:通过PFH特征匹配找到对应点,再用RANSAC去除误匹配[^1] - **物体识别**:建立模型库的PFH特征,与场景特征匹配 - **点云分割**:利用PFH特征相似性进行区域生长 ### 五、常见问题 1. **邻域半径选择**:半径过小导致特征过于局部化,过大则包含无关结构。经验值:点云平均间距的5-10倍。 2. **法线估计质量**:法线方向一致性对特征计算至关重要,需使用`pcl::NormalEstimation`的`setViewPoint`设置统一视角。 3. **计算效率**:PFH计算复杂度高,对大规模点云可考虑使用FPFH替代。 §§相关问题§§ 1. PFH与FPFH特征的主要区别是什么? 2. 如何提高PFH特征的计算效率? 3. PFH特征在点云配准中的具体应用流程是什么? 4. 除了PFHPCL还支持哪些特征描述子? 5. 如何处理点云法线估计不准确对PFH的影响?</think>### PCL 计算PFH特征可视化方法及数学公式 #### 一、PFH算法原理概述 PFH (Point Feature Histogram) 是PCL中的**局部特征描述子**,通过统计点邻域内的几何关系生成旋转不变性特征。其核心特点是: 1. **全面描述**:考虑邻域内所有点对关系 2. **旋转不变性**:基于局部参考坐标系实现 3. **高区分度**:生成125维特征向量 4. **计算复杂度**:$O(nk^2)$(n为点数,k为邻域点数) ```mermaid graph TD A[输入点云] --> B[法线估计] B --> C[邻域点对选择] C --> D[特征角度计算] D --> E[直方图统计] E --> F[特征可视化] ``` #### 二、数学原理与公式 ##### 1. 局部坐标系建立(基于引用[1]) 对于点$p_s$(源点)和$p_t$(目标点): - $\mathbf{u} = \mathbf{n}_s$(源点法线) - $\mathbf{v} = \mathbf{u} \times \frac{(p_t - p_s)}{\|p_t - p_s\|}$ - $\mathbf{w} = \mathbf{u} \times \mathbf{v}$(完成右手坐标系) ##### 2. 特征角度计算(基于引用[2]) 计算四个特征值: 1. $\alpha = \mathbf{v} \cdot \mathbf{n}_t$ 2. $\phi = \mathbf{u} \cdot \frac{(p_t - p_s)}{\|p_t - p_s\|}$ 3. $\theta = \arctan(\mathbf{w} \cdot \mathbf{n}_t, \mathbf{u} \cdot \mathbf{n}_t)$ 4. $d = \|p_t - p_s\|$(通常被忽略) 其中$\alpha, \phi, \theta$三个角度特征被量化到直方图: $$ \text{bin}_i = \left\lfloor \frac{\text{value} - \text{min}}{\text{max} - \text{min}} \times b \right\rfloor $$ $b$为bin数量(默认各维度5个bin,总维度$5^3=125$) ##### 3. 直方图统计 对于每个点$p$: 1. 选择半径$r$内的邻域点 2. 计算$p$与所有邻域点的特征三元组$(\alpha, \phi, \theta)$ 3. 统计邻域内所有点对的组合(包括邻域点之间) 4. 生成归一化的125维直方图[^1] #### 三、PCL实现步骤 ##### 1. 计算法线估计 ```cpp #include <pcl/features/normal_3d.h> pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud); ne.setRadiusSearch(0.05); // 法线估计半径 ne.compute(*normals); ``` ##### 2. 计算PFH特征 ```cpp #include <pcl/features/pfh.h> pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs(new pcl::PointCloud<pcl::PFHSignature125>()); pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh; pfh.setInputCloud(cloud); pfh.setInputNormals(normals); pfh.setSearchMethod(pcl::search::KdTree<pcl::PointXYZ>::Ptr(new pcl::search::KdTree<pcl::PointXYZ>)); pfh.setRadiusSearch(0.1); // 特征计算半径 pfh.compute(*pfhs); ``` ##### 3. 关键参数说明 | 参数 | 默认值 | 作用 | |------|--------|------| | `setRadiusSearch()` | 必选 | 邻域搜索半径 | | `setNrSubdivisions()` | (5,5,5) | 各维度bin数 | #### 四、特征可视化方法 ##### 1. 单点特征直方图可视化 ```cpp #include <pcl/visualization/histogram_visualizer.h> pcl::visualization::PCLHistogramVisualizer hist_vis; hist_vis.addFeatureHistogram(*pfhs, 125, 50); // 显示第50个点的特征 hist_vis.spin(); ``` ##### 2. 点云特征颜色映射 ```cpp #include <pcl/visualization/pcl_visualizer.h> // 创建带颜色的点云 pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>); colored_cloud->resize(cloud->size()); // 将PFH特征映射到RGB颜色 for (size_t i = 0; i < cloud->size(); ++i) { colored_cloud->points[i].x = cloud->points[i].x; colored_cloud->points[i].y = cloud->points[i].y; colored_cloud->points[i].z = cloud->points[i].z; // 取前三个bin作为RGB分量 colored_cloud->points[i].r = static_cast<uint8_t>(255 * pfhs->points[i].histogram[0]); colored_cloud->points[i].g = static_cast<uint8_t>(255 * pfhs->points[i].histogram[1]); colored_cloud->points[i].b = static_cast<uint8_t>(255 * pfhs->points[i].histogram[2]); } pcl::visualization::PCLVisualizer viewer("PFH Viewer"); viewer.addPointCloud<pcl::PointXYZRGB>(colored_cloud, "colored_cloud"); viewer.spin(); ``` ##### 3. 关键点特征分析 ```cpp // 访问PFH特征数据 for (size_t i = 0; i < pfhs->size(); ++i) { std::cout << "Point " << i << " feature: "; for (int j = 0; j < 125; ++j) { std::cout << pfhs->points[i].histogram[j] << " "; } std::cout << std::endl; } ``` #### 五、应用场景 1. **点云配准**:PFH特征匹配+RANSAC粗配准[^1] 2. **物体识别**:特征数据库匹配 3. **点云分割**:基于特征相似性的区域生长 4. **三维重建**:多视角特征关联 #### 六、性能优化建议 1. **降采样处理**:使用VoxelGrid滤波减少点数 2. **邻域搜索加速**:KDTree优化搜索效率 3. **特征选择**:仅计算关键点的PFH 4. **计算**:OpenMP多线程加速
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值