点特征直方图(PFH)描述(Point Feature Histograms (PFH) descriptors)

#点特征直方图(PFH)描述符
随着点特征表示的进行,曲面法线和曲率估计在它们围绕特定点的几何图形的表示中是相当基本的。虽然计算起来非常快速和容易,但它们不能捕获太多的细节,因为它们只能用几个值来逼近点的k邻域的几何。直接的结果是,大多数场景将包含许多具有相同或非常相似的特征值的点,从而降低了它们的信息特征。

为了简单起见,本教程介绍了一系列创建PFH(点特征直方图)的3D特征描述符,展示了它们的理论优势,并从PCL的角度讨论了实现细节。作为先决条件,请继续阅读PointCloud教程中的估算曲面法线,因为PFH签名既依赖于 xyz 3D data,也依赖于曲面法线

#理论引入
PFH公式的目标是通过使用值的多维直方图推广点周围的平均曲率来编码点的k邻域几何特性。这个高度空间超空间为特征表示提供了信息签名,对于下面的表面的6D姿态是不变的,并且可以很好地处理邻域中存在的不同采样密度或噪声水平。

点特征直方图表示基于k邻域中的点与其估计的表面法线之间的关系。简而言之,它试图通过考虑所估计的法线的方向之间的所有相互作用来尽可能最好地捕获取样的表面变化。由此产生的超空间依赖于每个点处的表面法线估计的质量。

下图给出了查询点(p_q)的PFH计算的影响区域图,用红色标记,放置在半径为r的圆形(sphere in 3D)中,所有k个邻居(距离小于半径r)完全互连在一个网格中。最终PFH描述符被计算为邻域中所有点对之间关系的直方图,因此具有的计算复杂度为 O(k^2) 。

_images/pfh_diagram.png

为了计算两个点之间的相对差P_I和 p_j与它们相关联的法线你和n_j,我们在点(参见下图)中的一个限定固定的坐标系。

{\ mathsf u} =&\ boldsymbol {n} _s \ {\ mathsf v} =&{\ mathsf u} \ times \ frac {(\ boldsymbol {p} _t- \ boldsymbol {p} _s)} {{ \ | \ boldssmbol {p} _t- \ boldsymbol {p} _s \ |} _ {2}} \ {\ mathsf w} =&{\ mathsf u} \ times {\ mathsf v}

_images / pfh_frame.png

使用上述UVW帧,两个法线之间的差 N_S,并N_T可以如下表示为一组的角度的特点:

\ alpha {\ mathsf v} \ cdot \ boldsymbol {n} _t \ \ phi&= {\ mathsf u} \ cdot \ frac {(\ boldsymbol {p} _t - \ boldsymbol {p} _s)} { d} \ \ theta&= \ arctan({\ mathsf w} \ cdot \ boldsymbol {n} _t,{\ mathsf u} \ cdot \ boldsymbol {n} _t)\

其中d是两个点之间的欧几里得距离 \ boldsymbol {P} _s和\ boldsymbol {P} _t, d = {\ | \ boldsymbol {P} _t- \ boldsymbol {P} _s \ |} _2。\ langle \ alpha,\ phi,\ theta,d \ rangle对于k邻域中的每一对两点计算四元组,因此将两点和它们的法线的12个值(xyz和正常信息)减少到4。

要估算一对点的PFH四联体,请使用:


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);

有关更多详细信息,请参阅API文档。

为了创建查询点的最终PFH表示,所有四元组的集合被组合成一个直方图。合并过程将每个特征的值范围划分为b个子范围,并计算每个子范围内出现的次数。由于上述四个特征中的三个是法线之间角度的测量值,所以它们的值可以很容易地在三角圆上归一化到相同的间隔。装仓示例是将每个特征区间划分为相同数目的相同部分,因此创建一个直方图 b^4在完全相关的空间中的垃圾箱。在这个空间中,直方图仓增量对应于其所有4个特征具有特定值的点。下图给出了云中不同点的点特征直方图表示的例子。

在某些情况下,第四个特征d对于2.5D数据集并不具有极端重要性,通常在机器人中获取,因为相邻点之间的距离从视点增加。因此,对于局部点密度影响该特征维度的扫描省略d已被证明是有益的。

_images/example_pfhs.jpg

    注意:
    有关更多信息和数学推导(包括不同表面几何形状的PFH特征分析),请参阅[Rusu论文](http://pointclouds.org/documentation/tutorials/how_features_work.php#rusudissertation)。

#估算PFH功能
点特征直方图是作为pcl_features库的一部分在PCL中实现的。

默认的PFH实现使用5个binning细分(例如,四个特征值中的每一个将使用它的值间隔中的这个多个bin),并且不包括距离(如上所述 - 虽然computePairFeatures方法可以由用户调用如果需要,也可以获得距离),从而得到5^3浮点值的125字节数组。这些存储在pcl::PFHSignature125点类型中。

下面的代码片段将为输入数据集中的所有点估计一组PFH特征。

#include <pcl/point_types.h>
#include <pcl/features/pfh.h>

{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal> ());

  ... read, pass in or create a point cloud with normals ...
  ... (note: you can create a single PointCloud<PointNormal> if you want) ...

  // Create the PFH estimation class, and pass the input dataset+normals to it
  pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
  pfh.setInputCloud (cloud);
  pfh.setInputNormals (normals);
  // alternatively, if cloud is of tpe PointNormal, do pfh.setInputNormals (cloud);

  // Create an empty kdtree representation, and pass it to the PFH estimation object.
  // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  //pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<pcl::PointXYZ> ()); -- older call for PCL 1.5-
  pfh.setSearchMethod (tree);

  // Output datasets
  pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs (new pcl::PointCloud<pcl::PFHSignature125> ());

  // Use all neighbors in a sphere of radius 5cm
  // IMPORTANT: the radius used here has to be larger than the radius used to estimate the surface normals!!!
  pfh.setRadiusSearch (0.05);

  // Compute the features
  pfh.compute (*pfhs);

  // pfhs->points.size () should have the same size as the input cloud->points.size ()*
}

来自PFHEstimation类的实际计算调用在内部不做任何事情,但是:

for each point p in cloud P

  1. get the nearest neighbors of p

  2. for each pair of neighbors, compute the three angular values

  3. bin all the results in an output histogram

要计算k邻域中的单个PFH表示,请使用:

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

其中cloud是包含点的输入点云,normals是包含法线的输入点云(如果PointInT=PointNT=PointNorm,则可以等于云 ),indices代表来自云的k个最近邻居的集合,nr_split是用于每个特征间隔的装仓过程的细分数目,而pfh_histogram是作为浮点值数组的输出结果直方图。

   注意:
   出于效率原因,`PFHEstimation`中的计算方法不检查法线是否包含`NaN`或`无限值`。将这些值传递给`compute()`会导致未定义的输出。建议检查法线,至少在加工链的设计或设置参数时。这可以通过在调用`compute()`之前插入以下代码来完成:
for (int i = 0; i < normals->points.size(); i++)
{
  if (!pcl::isFinite<pcl::Normal>(normals->points[i]))
  {
    PCL_WARN("normals[%d] is not finite\n", i);
  }
}
   在生产代码中,应该设置预处理步骤和参数,使法线是有限的或产生错误。

Point Feature Histograms (PFH) descriptors

猜你喜欢

转载自blog.csdn.net/RuoQiQingCheDi/article/details/83959240