欢迎点云相关产学研的学者和团体加入我们。
正如点特征表示法所示,表面法线和曲率估计是某个点周围的几何特征基本表示法。虽然计算非常快速容易,但是无法获得太多信息,因为它们只使用很少的几个参数值来近似表示一个点的k邻域的几何特征。然而大部分场景中包含许多特征点,这些特征点有相同的或者非常相近的特征值,因此采用点特征表示法,其直接结果就减少了全局的特征信息。本小节介绍三维特征描述子中的一位成员:点特征直方图(Point Feature Histograms),我们简称为PFH,本小节将介绍它的理论优势,从PCL实现的角度讨论其实施细节。PFH特征不仅与坐标轴三维数据有关,同时还与表面法线有关。
PFH计算方式通过参数化查询点与邻域点之间的空间差异,并形成一个多维直方图对点的k邻域几何属性进行描述。直方图所在的高维超空间为特征表示提供了一个可度量的信息空间,对点云对应曲面的6维姿态来说它具有不变性,并且在不同的采样密度或邻域的噪音等级下具有鲁棒性。点特征直方图(PFH)表示法是基于点与其k邻域之间的关系以及它们的估计法线,简言之,它考虑估计法线方向之间所有的相互作用,试图捕获最好的样本表面变化情况,以描述样本的几何特征。因此,合成特征超空间取决于每个点的表面法线估计的质量。如图1所示,表示的是一个查询点(Pq)
图1 查询点
为了计算两点Pi和Pj及与它们对应的法线Ni和Nj之间的相对偏差,在其中的一个点上定义一个固定的局部坐标系,如图2所示。
图2 定义一个固定的局部坐标系
使用上图中uvw坐标系,法线
d是两点Ps和Pt之间的欧氏距离,
为每一对点估计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个子区间,并统计落在每个子区间的点数目,因为四分之三的特征在上述中为法线之间的角度计量,在三角化圆上可以将它们的参数值非常容易地归一到相同的区间内。一个统计的例子是:把每个特征区间划分成等分的相同数目,为此在一个完全关联的空间内创建有
图3 点云中不同点的点特征直方图表示法
注意:更多相关信息和数学推导,包括不同几何体表面点云的PFH特征分析,请见[RusuDissertation]。
点特征直方图(PFH)在PCL中的实现是pcl_features模块的一部分。默认PFH的实现使用5个区间分类(例如:四个特征值中的每个都使用5个区间来统计),其中不包括距离(在上文中已经解释过了——但是如果有需要的话,也可以通过用户调用computePairFeatures方法来获得距离值),这样就组成了一个125浮点数元素的特征向量(35),其保存在一个pcl::PFHSignature125的点类型中。以下代码段将对输入数据集中的所有点估计其对应的PFH特征。
#include <pcl/point_types.h> //点类型头文件
#include <pcl/features/pfh.h> //pfh特征估计类头文件
...//其他相关操作
pcl::PointCloud<pcl::PointXYZ>::Ptrcloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptrnormals(new pcl::PointCloud<pcl::Normal>());
...//打开点云文件估计法线等
//创建PFH估计对象pfh,并将输入点云数据集cloud和法线normals传递给它
pcl::PFHEstimation<pcl::PointXYZ,pcl::Normal,pcl::PFHSignature125> pfh;
pfh.setInputCloud(cloud);
pfh.setInputNormals(normals);
//如果点云是类型为PointNormal,则执行pfh.setInputNormals (cloud);
//创建一个空的kd树表示法,并把它传递给PFH估计对象。
//基于已给的输入数据集,建立kdtree
pcl::KdTreeFLANN<pcl::PointXYZ>::Ptrtree(new pcl::KdTreeFLANN<pcl::PointXYZ>());
pfh.setSearchMethod(tree);
//输出数据集
pcl::PointCloud<pcl::PFHSignature125>::Ptrpfhs(new pcl::PointCloud<pcl::PFHSignature125>());
//使用半径在5厘米范围内的所有邻元素。
//注意:此处使用的半径必须要大于估计表面法线时使用的半径!!!
pfh.setRadiusSearch(0.05);
//计算pfh特征值
pfh.compute(*pfhs);
// pfhs->points.size ()应该与input cloud->points.size ()有相同的大小,即每个点都有一个pfh特征向量
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);
此处,cloud变量是包含点的输入点云,normals变量是包含对应cloud的法线的输入点云,indices代表输入点云(点与法线对应)中查询点的k-近邻元素集,nr_split是所分区间的数目,用于每个特征区间的统计过程,pfh_histogram是浮点数向量来存储输出的合成直方图。
敬请关注PCL(Point Cloud Learning)中国更多的点云库PCL(Point Cloud Library)相关官方教程。
1.朱德海、郭浩、苏伟.点云库PCL学习教程(ISBN 978-7-5124-0954-5)北京航空航天出版社 2012-10