https://pcl.readthedocs.io/projects/tutorials/en/latest/index.html#features
https://pointcloudlibrary.github.io/documentation/group__features.html

3D 特征点概述(1)
3D 特征点概述(2)

PCL点云特征描述与提取(1)
PCL点云特征描述与提取(2)
PCL点云特征描述与提取(3)
PCL点云特征描述与提取(4)

此模块个人代码:https://github.com/HuangCongQing/pcl-learning/tree/master/10features

3D点云特征描述与提取是点云信息处理中最基础也是最关键的一部分,点云的识别,分割,重采样,配准,曲面重建等处理大部分算法,都严重依赖特征描述与提取的结果。从尺度上来分,一般分为

  • 局部特征的描述
    • 局部的法线等几何形状特征的描述
  • 全局特征的描述
    • 全局的拓朴特征的描述

都属于3D点云特征描述与提取的范畴

特征描述与提取相关的概念与算法
1.3D形状内容描述子(3D shape contexts)
利用描述子建立曲面间的对应点在3D物体识别领域有广发的应用,采用一个向量描述曲面上指定点及邻域的形状特征,通过匹配向量的值来建立不同曲面点的对应关系,此相邻则则称为指定点的俄描述子,经典描述子的3D形状内容描述子结构简单,辨别力强,且对噪声不敏感,
2,旋转图像(spin iamge)
旋转图像最早是由johnson提出的特征描述子,主要用于3D场景中的曲面匹配和模型识别,
3,涉及的算法相关的资料
3D形状内容描述子
https://en.wikipedia.org/wiki/Shape_context
www.eecs.berkeley.edu/Research/Projects/CS/vision/shape/belongie-pami02.pdf

特征描述与提取模块和相关类

Classes
class pcl::ShapeContext3DEstimation< PointInT, PointNT, PointOutT >
实现3D形状内容描述子算法
class pcl::BOARDLocalReferenceFrameEstimation< PointInT, PointNT, PointOutT >
实现局部坐标系估计的方法 特别是处理点云边缘或有孔洞有特殊的处理方式
class pcl::BoundaryEstimation< PointInT, PointNT, PointOutT >
实现估计一组点集是否处于指定点的投影区域的边缘位置
class pcl::CRHEstimation< PointInT, PointNT, PointOutT >
实现摄像头旋转直方图描述子,利用概算法主要进行刚体对象的位姿估计
class pcl::CVFHEstimation< PointInT, PointNT, PointOutT >
实现聚类视点直方图CVFH描述子的计算 主要是针对解决有残缺的点云识别问题
class pcl::ESFEstimation< PointInT, PointOutT >
实现ESF描述子,主要用于实时对三维场景中的点云模型进行**分类**而提出的
class pcl::Feature< PointInT, PointOutT > 是所有特征相关模块中其他类的基类
class pcl::FeatureWithLocalReferenceFrames< PointInT, PointRFT >
实现FPFH描述子算法主要针对点云配准过程中对应点而提出的

理论

  1. 在原始表示形式下,点的定义是用笛卡尔坐标系坐标 x, y, z 相对于一个给定的原点来简单表示的三维映射系统的概念,假定坐标系的原点不随着时间而改变,这里有两个点p1p2分别在时间t1t2捕获,有着相同的坐标,对这两个点作比较其实是属于不适定问题(illposed problem),因为虽然相对于一些距离测度它们是相等的,但是它们取样于完全不同的表面,因此当把它们和临近的其他环境中点放在一起时,它们表达着完全不同的信息,这是因为在t1t2之间局部环境有可能发生改变。一些获取设备也许能够提供取样点的额外数据,例如强度或表面反射率等,甚至颜色,然而那并不能完全解决问题,单从两个点之间来 对比仍然是不适定问题。**由于各种不同需求需要进行对比以便能够区分曲面空间的分布情况,应用软件要求更好的特征度量方式,因此作为一个单一实体的三维点概念和笛卡尔坐标系被淘汰了,出现了一个新的概念取而代之:****局部描述子(locl descriptor)****。**<br />文献中对这一概念的描述有许多种不同的命名,如:形状描述子(shape descriptors)或几何特征(geometric features),文本中剩余部分都统称为点特征表示。通过包括周围的领域,特征描述子能够表征采样表面的几何 性质,它有助于解决不适定的对比问题,理想情况下相同或相似表面上的点的特征值将非常相似(相对特定度量准则),而不同表面上的点的特征描述子将有明显差异。下面几个条件,**通过能否获得相同的局部表面特征值,可以判定点特征表示方式的优劣:**<br />(1)刚体变换-----即三维旋转和三维平移变化 不会影响特征向量F估计,即**特征向量具有平移旋转不变性**。<br />(2)改变采样密度-----原则上,一个局部表面小块的采样密度无论是大还是小,都应该有相同的特征向量值,即**特征向量具有抗密度干扰性。**<br />(3)噪声---数据中有轻微噪声的情况下,点特征表示在它的特征向量中必须保持相同或者极其相似的值,即**特征向量对点云噪声具有稳定性。**<br />通常,PCL中特征向量**利用快速kd-tree查询** ,使用近似法来计算查询点的最近邻元素,通常有两种查询类型:**K邻域查询,半径搜索两中方法**<br />**

1 法向量(法线)估计实例 How 3D Features work in PCL

一旦确定邻域以后,查询点的邻域点可以用来估计一个局部特征描述子,它用查询点周围领域点描述采样面的几何特征,描述几何表面图形的一个重要属性,首先是推断它在坐标系中的方位,也就是估计他的法线,表面法线是表面的一个重要的属性,在许多领域都有重要的应用,如果用光源来生成符合视觉效果的渲染等,

代码解析:normal_estimation.cpp
(实现对输入点云数据集中的点估计一组表面法线)执行的操作是:对应点云P中每一个点p得到p点最近邻元素,计算p点的表面的法线N,检查N的方向是否指向视点如果不是则翻转
视点默认坐标是(0,0,0)可使用setViewPoint(float vpx,float vpy,float vpz)来更换

代码实现

创建文件:normal_estimation.cpp
准备资源:../table_scene_lms400.pcd
编译执行:./normal_estimation

个人代码:10features特征

/*
 * @Description: 法向量估计(运行耗时2min)。:https://www.cnblogs.com/li-yao7758258/p/6479255.html
 * @Author: HCQ
 * @Company(School): UCAS
 * @Date: 2020-10-19 16:33:43
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2020-10-19 14:34:00
 * @FilePath: /pcl-learning/10features特征/1法向量估计/normal_estimation.cpp
 */
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/integral_image_normal.h>  //法线估计类头文件
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>

int
main ()
 {
//打开点云代码
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile ("../table_scene_lms400.pcd", *cloud);

//创建法线估计估计向量
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud(cloud);
//创建一个空的KdTree对象,并把它传递给法线估计向量
//基于给出的输入数据集,KdTree将被建立
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
ne.setSearchMethod(tree);
//存储输出数据
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
//使用半径在查询点周围3厘米范围内的所有临近元素
ne.setRadiusSearch(0.03);
//计算特征值
ne.compute(*cloud_normals);
// cloud_normals->points.size ()应该与input cloud_downsampled->points.size ()有相同的尺寸

// 存储特征值为点云
pcl::PCDWriter writer;
writer.write<pcl::Normal> ( "../table_cloud_normals.pcd" , *cloud_normals, false); // 保存文件
//可视化
pcl::visualization::PCLVisualizer viewer("PCL Viewer");
viewer.setBackgroundColor (0.0, 0.0, 0.0);
viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, cloud_normals); // 将估计的点云表面法线添加到屏幕。

while (!viewer.wasStopped ())
{
     viewer.spinOnce ();
}

return 0;
}

输出结果

实现效果

各个方向的法向量都有

oridial result
image.png image.png

2 表面估计 Estimating Surface Normals in a PointCloud

表面法线是几何体表面一个十分重要的属性,例如:在进行光照渲染时产生符合可视习惯的效果时需要表面法线的信息才能正常进行,对于一个已经知道的几何体表面,根据垂直于点表面的的矢量,因此推推出表面某一点的法线方向比较容易,然而由于我们获取的点云的数据集在真实的物体的表面表现为一组定点的样本,这样就会有两种方法解决:

  1. 使用曲面重建技术,从获取的点云数据中得到采样点对应的曲面,然后从曲面模型中计算出表面法线
  2. 直接从点云数据中近似推断表面法线

    3 使用积分图进行法线估计Normal Estimation Using Integral Images

    三种法线估计方法

  • COVARIANCE_MATRIX 模式从具体某个点的局部邻域的协方差矩阵创建9个积分,来计算这个点的法线
  • AVERAGE_3D_GRADIENT 模式创建6个积分图来计算水平方向和垂直方向的平滑后的三维梯度并使用两个梯度间的向量积计算法线
  • AVERAGE_DEPTH——CHANGE 模式只创建了一个单一的积分图,从而平局深度变化计算法线

代码实现

创建文件:normal_estimation_using_integral_images.cpp
准备资源:../table_scene_mug_stereo_textured.pcd
编译执行:./normal_estimation_using_integral_images

个人代码:10features特征

/*
 * @Description: 为输入数据集中的点的子集估计一组表面法线。https://pcl.readthedocs.io/projects/tutorials/en/latest/how_features_work.html#how-3d-features-work
 * @Author: HCQ
 * @Company(School): UCAS
 * @Email: 1756260160@qq.com
 * @Date: 2020-10-19 15:04:50
 * @LastEditTime: 2020-10-19 18:34:17
 * @FilePath: /pcl-learning/10features特征/2估计点云子集的表面法线(error)/normal_estimation_subdset_points.cpp
 */
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
// 下面报错 error: ‘shared_ptr’ is not a member of ‘pcl’

int main ()
 {
//打开点云代码
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile ("../table_scene_lms400.pcd", *cloud);

  // //创建一组要使用的索引。为简单起见,我们将使用云中前10%的点
  std::vector<int> indices (std::floor (cloud->size () / 10));
  for (std::size_t i = 0; i < indices.size (); ++i) indices[i] = i;

  // //创建NormalEstimation类,并将输入数据集传递给它
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud (cloud);

  // 传递索引
  // std::shared_ptr<std::vector<int> > indicesptr (new std::vector<int> (indices)); // 报错
  pcl::shared_ptr<std::vector<int> > indicesptr (new std::vector<int> (indices)); // 报错
  ne.setIndices (indicesptr);

  // 创建一个空的kdtree表示形式,并将其传递给normal estimation 对象
  // 它的内容将根据给定的输入数据集填充到对象内部(因为未提供其他搜索表面)。
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  ne.setSearchMethod (tree);

  // Output datasets
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

  // 在半径3cm的范围内近邻
  ne.setRadiusSearch (0.03);

  // 计算特征
  ne.compute (*cloud_normals);

  // cloud_normals->size () should have the same size as the input indicesptr->size ()
}

输出结果

实现效果

image.png image.png

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

PCL点云特征描述与提取(2)
https://www.codenong.com/cs105922110/看这个
https://pcl.readthedocs.io/projects/tutorials/en/latest/pfh_estimation.html#pfh-estimation
正如点特征表示法所示,表面法线和曲率估计是某个点周围的几何特征基本表示法。虽然计算非常快速容易,但是无法获得太多信息,因为它们只使用很少的几个参数值来近似表示一个点的k邻域的几何特征。
然而大部分场景中包含许多特征点,这些特征点有相同的或者非常相近的特征值,因此采用点特征表示法,其直接结果就减少了全局的特征信息
那么三维特征描述子中一位成员:点特征直方图(Point Feature Histograms),我们简称为PFH,从PCL实现的角度讨论其实施细节。**PFH特征不仅与坐标轴三维数据有关,同时还与表面法线有关。**

PFH计算方式通过参数化查询点与邻域点之间的空间差异,并形成一个多维直方图对点的k邻域几何属性进行描述。直方图所在的高维超空间为特征表示提供了一个可度量的信息空间,对点云对应曲面的6维姿态来说它具有不变性,并且在不同的采样密度或邻域的噪音等级下具有鲁棒性。
点特征直方图(PFH)表示法是基于点与其k邻域之间的关系以及它们的估计法线,简言之,它考虑估计法线方向之间所有的相互作用,试图捕获最好的样本表面变化情况,以描述样本的几何特征。因此,合成特征超空间取决于每个点的表面法线估计的质量。
如图所示,表示的是一个查询点(Pq) 的PFH计算的影响区域,Pq 用红色标注并放在圆球的中间位置,半径为r, (Pq)的所有k邻元素(即与点Pq的距离小于半径r的所有点)全部互相连接在一个网络中。最终的PFH描述子通过计算邻域内所有两点之间关系而得到的直方图,因此存在一个O(k) 的计算复杂性。

   ![](https://cdn.nlark.com/yuque/0/2020/png/232596/1603096317440-8066b761-6b50-4f24-899b-87c7777e6dd4.png#align=left&display=inline&height=225&margin=%5Bobject%20Object%5D&originHeight=225&originWidth=400&size=0&status=done&style=none&width=400)

为了计算两点Pi和Pj及与它们对应的法线Ni和Nj之间的相对偏差,在其中的一个点上定义一个固定的局部坐标系,如图2所示。
10features特征 - 图5 10features特征 - 图6
使用上图中uvw坐标系,法线 和 之间的偏差可以用一组角度来表示,如下所示:
10features特征 - 图7

估计PFH特征
点特征直方图(PFH)在PCL中的实现是pcl_features模块的一部分。默认PFH的实现使用5个区间分类(例如:四个特征值中的每个都使用5个区间来统计),
以下代码段将对输入数据集中的所有点估计其对应的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);

PFHEstimation类的实际计算程序内部只执行以下:
对点云P中的每个点p
1.得到p点的最近邻元素
2.对于邻域内的每对点,计算其三个角度特征参数值
3.将所有结果统计到一个输出直方图中

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

结果

ERROR

[pcl::PFHEstimation::initCompute] The number of points in the input dataset (307200) differs from the number of points in the dataset containing the normals (0)!
image.png

5 快速点特征直方图(FPFH)描述子Fast Point Feature Histograms (FPFH) descriptors

[PCL]计算关键点处的特征并且可视化(iss/sift+fpfh/pfh/shot)
My Blog
PCL点云特征描述与提取(3)
PCL库之快速点特征直方图(FPFH)描述子

【PCL学习笔记】之快速点特征直方图FPFH - pcl

PFH和FPFH计算方式之间的主要区别总结如下:

1.FPFH没有对全互连 点的所有邻近点的计算参数进行统计,从图中可以看到,因此可能漏掉了一些重要的点对,而这些漏掉的对点可能对捕获查询点周围的几何特征有贡献。 2.PFH特征模型是对查询点周围的一个精确的邻域半径内,而FPFH还包括半径r范围以外的额外点对(不过在2r内); 3.因为重新权重计算的方式,所以FPFH结合SPFH值,重新捕获邻近重要点对的几何信息; 4.由于大大地降低了FPFH的整体复杂性,因此FPFH有可能使用在实时应用中; 5.通过分解三元组,简化了合成的直方图。也就是简单生成d分离特征直方图,对每个特征维度来单独绘制,并把它们连接在一起

快速点特征直方图FPFH在点云库中的实现可作为pcl_features库的一部分。默认的FPFH实现使用11个统计子区间(例如:四个特征值中的每个都将它的参数区间分割为11个),特征直方图被分别计算然后合并得出了浮点值的一个33元素的特征向量,这些保存在一个pcl::FPFHSignature33点类型中。以下代码段将对输入数据集中的所有点估计一组FPFH特征值。

估视点特征直方图Estimating VFH signatures for a set of points

7 从一个深度图像提取NARF特征How to extract NARF Features from a range image

PCL点云特征描述与提取(4)

http://www.pclcn.org/study/shownews.php?lang=cn&id=97

Moment of inertia and eccentricity based descriptors基于惯性矩和偏心率的描述符

RoPs (Rotational Projection Statistics) feature

Globally Aligned Spatial Distribution (GASD) descriptors