首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【PCL自学:Feature3】PFH点特征直方图的概念和使用 (持续更新)

  • 23-11-18 01:41
  • 2332
  • 7844
blog.csdn.net

一、点特征直方图(PFH)描述子介绍

  Point Feature Histograms (PFH) 称为点特征直方图。
  随着点特征的研究不断深入,利用点周围的邻近点估计表面法向和曲率的基本操作逐渐被点特征直方图取代,虽然表面法向和曲率的估计速度很快,但是他们缺失了很多细节,因为它们仅用很少的值近似一个点的k-邻域的几何形状。但是大多数场景将包含许多具有相同或非常相似特征值的点,从而使它们的信息特征不具有唯一性。
  本文介绍了一组3D特征描述符PFH(点特征直方图),介绍了它们的理论优势,并从PCL的角度讨论了实现细节。作为先决条件,请先阅读第三章有关表面法线计算的相关内容,因为PFH描述子既依赖于xyz 3D数据,也依赖于表面法线的估计结果。

1、点特征直方图理论基础

  PFH的目标是通过使用多维直方图来泛化点周围的平均曲率进而编码点的k邻域几何属性。这种高维的超空间为特征表示提供了信息特征,对表面的6D位姿是不变的,并且可以很好地应对不同的采样密度或邻域存在的噪声。
点特征直方图表示是基于k-邻域中的点和它们估计的表面法线之间的关系。简单地说,它试图通过考虑估计法线方向之间的所有相互作用来尽可能地捕捉采样表面的变化。因此,合成的超空间依赖于每个点的表面法线估计的质量。
  下图呈现出PFH的计算区域图,待计算点为 p q p_q pq​, 点 p q p_q pq​标有红色并放置在一个半径为r的3d球体当中,和所有k邻域内的点(距离小于半径r)完全互联。最终的PFH描述符被计算为邻域内所有点对之间关系的直方图,因此计算复杂度为O( k 2 k^2 k2)。
在这里插入图片描述
  为了计算两点 p i p_i pi​和 p j p_j pj​及其相关法线 n i n_i ni​和 n j n_j nj​之间的相对差,我们在其中一点上定义一个固定的坐标系(见下图)。
在这里插入图片描述
在这里插入图片描述
  利用上述uvw框架,两法线n_s和n_t的差可以表示为一组角特征,如下所示:
在这里插入图片描述
  其中d为两点 ( p s ) ({p}_s) (ps​)与 ( p t ) ({p}_t) (pt​)之间的欧氏距离,d= ∣ ∣ p t − p s ∥ 2 {||{p}_t-{p}_s\|}_2 ∣∣pt​−ps​∥2​。对k-邻域中的每一对点计算四元组的 ⟨ \langle ⟨ α \alpha α, ϕ \phi ϕ, θ \theta θ, d ⟩ \rangle ⟩范围,因此将这两点的12个信息值(xyz和法线信息)可以减少到使用上述4个信息值表示。
  要估计一对点的4信息PFH,使用如下代码:其中f1~f4为输出的4元组信息

computePairFeatures (const Eigen::Vector4f &p1, const Eigen::Vector4f &n1,
                     const Eigen::Vector4f &p2, const Eigen::Vector4f &n2,
                     float &f1, float &f2, float &f3, float &f4);
  • 1
  • 2
  • 3

  为了为待计算点创建最终的PFH表示,所有4元组的集合被归类到直方图中。统计过程将每个feature的取值范围划分为b个子区间,并统计每个子区间出现的次数。由于上述四个特征中有三个是法线之间角度的度量,它们的值可以很容易地归一化到相同区间。例如,将每个特征区间划分为相同数量的相等部分,因此在完全相关的空间中创建一个具有 b 4 b^4 b4个格子的直方图。在这个空间中,一个直方图格子增量对应于一个点,它的所有4个特征都有一定的值。下图展示了点云中不同点的点特征直方图的例子。

在这里插入图片描述
  细心的同学会发现,使用传感器获取点云后,对于d这个参数,对于距离视点较近的点集更为密集,较远的则较为稀疏,因此,对于局部点密度因视点变化的情况,省略d参数是更有益的。

2、示例代码分析

  点特征直方图是作为pcl_features库的一部分在PCL中实现的。默认PFH的实现使用5元细分和不包括距离的细分(如上解释尽管computePairFeatures方法可以调用用户获得的距离),其结果是一个125字节的数组(5^3)的浮点值。这些存储在pcl::PFHSignature125类型中。下面的代码片段将估计输入数据集中所有点的PFH描述子。

 #include 
 #include 
 
 {
   pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
   pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal> ());
 
	 /*
		 此处通过读取PCD或者创造一组有法向特征的点云。不再赘述
 	*/
 	
  	// 创建PFH估计类,并将输入数据集和法线传递给类
 	pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
	pfh.setInputCloud (cloud);
 	pfh.setInputNormals (normals);
 	// 或者, 如果点云类型是 PointNormal, 使用pfh.setInputNormals (cloud);

 	// 创建一个空的kdtree表示,并将其传递给PFH对象。
 	// 树的内容将根据给定的输入数据集填充到对象内部(因为没有给出其他搜索面)。
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
	//PCL1.5以下版本使用这个指令
 	//pcl::KdTreeFLANN::Ptr tree (new pcl::KdTreeFLANN ()); 
  pfh.setSearchMethod (tree);
  // 输出PFH描述子
  pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs (new pcl::PointCloud<pcl::PFHSignature125> ());

  // 使用半径为5cm的球面上的所有邻点
  // 重要:这里使用的半径必须大于用来估计表面法线的半径!!!例如表面法向估计半径为0.02,此处为0.05
  pfh.setRadiusSearch (0.05);

  // 计算PFH描述子
  pfh.compute (*pfhs);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

pfhestimate类的实际计算调用在内部没有做任何事情,除了以下操作:

//伪代码
for each point p in cloud P

  1. get the nearest neighbors of p  //获取p的邻域点

  2. for each pair of neighbors, compute the three angular values //计算每个邻点对的三个角度参数值

  3. bin all the results in an output histogram //将所有结果插入输出的直方图中
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  当计算单个点的PFH时,可采用如下指令:

computePointPFHSignature (const pcl::PointCloud<PointInT> &cloud,
                          const pcl::PointCloud<PointNT> &normals,
                          const std::vector<int> &indices,
                          int nr_split,
                          Eigen::VectorXf &pfh_histogram);
  • 1
  • 2
  • 3
  • 4
  • 5

  输入的点云是包含法线的点云(如果PointInT = PointNT = PointNormal也可以),索引indices代表的是点云中参与计算PFH的点云集合,nr_split是用于每个特征区间的分块细分数量,pfh_histogram是输出的结果直方图,是一个浮点值数组。

  拓展:有时我们考虑到效率问题,选择不检查法线是否包含NaN或infinite值。将这些值传递给compute(),但是这将导致未知输出。建议至少在参数设置和程序编写时,增加检查正常值的步骤。这可以通过在调用compute()之前插入以下代码来实现:

for (int i = 0; i < normals->size(); i++)
{
  if (!pcl::isFinite<pcl::Normal>((*normals)[i]))
  {
    PCL_WARN("normals[%d] is not finite\n", i);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  在代码编写中,应该设置预处理步骤和参数,使法线是有限的否则将引发错误。

总结:
  本篇文章介绍了什么是PFH点特征直方图,并通过示例程序分析了如何使用Feature模块点特征直方图计算的流程。下一章节将介绍PFH的升级版,FPFH快速点特征直方图。


【博主简介】
  斯坦福的兔子,男,95,天津大学机械工程工学硕士。21年毕业至今从事光学三维成像及点云处理相关工作。因工作中使用的三维处理库为公司内部库,不具有普遍适用性,遂自学开源PCL库及其相关数学知识以备使用。谨此将自学过程与君共享。
博主才疏学浅,尚不具有指导能力,如有问题还请各位在评论处留言供大家共同讨论。
若前辈们有工作机会介绍欢迎私信。

注:本文转载自blog.csdn.net的斯坦福的兔子的文章"https://blog.csdn.net/weixin_41966507/article/details/122792952"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top