PCL教程指南-PFH与FPFH特征描述子

PCL教程指南-PFH与FPFH特征描述子

  • PFH官方文档
  • FPFH官方文档
  • 两种描述子主要思想是利用局部邻域内点之间的角度距离特征组成直方图的思想,具体原理文档和相关论文有详解
  • 注释文档代码,并扩展其中用法

1.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) ...

  //PFH估计类,其中pcl::PFHSignature125为输出类型为直方图数据
  pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
  pfh.setInputCloud (cloud);
  pfh.setInputNormals (normals);
  //根据点云类型不同,比如可使用pointNormal类型,则 pfh.setInputNormals (cloud);

  // Kdtree搜索类,直接设置给pfh类
  // 搜索直接按照pfh内部数据计算
  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);

  // 输出结果集,即每个点都对应一个125个向量数据
  pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs (new pcl::PointCloud<pcl::PFHSignature125> ());

  // 设置半径,用于fph邻域计算
  // 注意: 这个半径必须大于估计法线时的搜索半径
  pfh.setRadiusSearch (0.05);

  // 计算pfh特征
  pfh.compute (*pfhs);

  // pfhs->size () should have the same size as the input cloud->size ()*
}
  • 其中pcl::PFHSignature125为直方图输出结果类型,125的含义是 这个类中特征选取了三个角度值,而没有距离信息(需要距离信息需要computePairFeatures方法计算),且角度在构建直方图时默认采用了5个间隔(bin),通俗来讲就是 有三个角度,每个角度有5份,穷举可能出现的结果构建直方图,即每个角度选一份出来组成一块,排列组合A15 * A15 * A15 即文档中所说的5 * 5 * 5=5^3
    直方图125组合
  • 有时需要单独求某两点的特征信息,或者只求一个点的pfh特征,pcl提供了以下两种方法
//计算两点之间的三个角度和一个距离信息
bool pcl::PFHEstimation< PointInT, PointNT, PointOutT >::computePairFeatures	(	
const pcl::PointCloud< PointInT > & 	cloud,//输入 包含这两点的点云指针
const pcl::PointCloud< PointNT > & 	normals,//输入 点云的法向指针
int 	p_idx,//输入 点1索引
int 	q_idx,//输入 点2索引
float & 	f1,//输出 nq_idx 和 u的投影角度 
float & 	f2,//输出 nq_idx 和 v的角度
float & 	f3,//输出  np_idx 和 |p_idx - q_idx|的角度
float & 	f4 //输出 距离
)	
//计算某个点的pfh角度特征数据
void pcl::PFHEstimation< PointInT, PointNT, PointOutT >::computePointPFHSignature	(	
const pcl::PointCloud< PointInT > & 	cloud,//点云
const pcl::PointCloud< PointNT > & 	normals,//法向
const pcl::Indices & 	indices,// 某点的邻域内所有点的索引
int 	nr_split,//角度数据的分割数目 (bin数)
Eigen::VectorXf & 	pfh_histogram //输出的pfh向量  即如果bin是5,那么输出含125个数据的向量
)	

2.FPFH

相比PFH,FPFH为了计算快速,计算时没有使用邻域网络交叉计算,而是通过邻域各点的SPFH加权得到结果。
SPFH即针对某点,只计算此点与邻域间的特征角度和距离信息,不必计算邻域内点间的特征信息。

#include <pcl/point_types.h>
#include <pcl/features/fpfh.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) ...

  // FPFH估计类,其中pcl::FPFHSignature33为输出类型为直方图数据
  pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh;
  fpfh.setInputCloud (cloud);
  fpfh.setInputNormals (normals);
 
  //以下类似于FPH代码
  pcl::search::KdTree<PointXYZ>::Ptr tree (new pcl::search::KdTree<PointXYZ>);
  fpfh.setSearchMethod (tree);

 //输出结果
  pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs (new pcl::PointCloud<pcl::FPFHSignature33> ());

  fpfh.setRadiusSearch (0.05);

  fpfh.compute (*fpfhs);

  // fpfhs->size () should have the same size as the input cloud->size ()*
}
  • 其中pcl::FPFHSignature33,33的含义是3个角度,默认分割11份,不像PFH125那样穷举,而是直接独立拼凑到一起,即11+11+11=33
  • 类比PFH单独计算特征信息的方法FPFH同样实现了,类似方法不再赘述
//计算两点间相关特征值
bool 	computePairFeatures (const pcl::PointCloud< PointInT > &cloud, const pcl::PointCloud< PointNT > &normals, int p_idx, int q_idx, float &f1, float &f2, float &f3, float &f4)


//计算某点的SPFH,返回各角度特征的矩阵形式; 比如计算第一个点row=0,那么矩阵只有第一行有值,以此类推
void pcl::FPFHEstimation< PointInT, PointNT, PointOutT >::computePointSPFHSignature	(	
const pcl::PointCloud< PointInT > & 	cloud,
const pcl::PointCloud< PointNT > & 	normals,
int 	p_idx,//查询点索引
int 	row,//矩阵的第几行,具体的行指邻域内SPFH计算所在的点,row则指查询点邻域内第row个点
const std::vector< int > & 	indices,//邻域索引
Eigen::MatrixXf & 	hist_f1,//输出 f1的直方图矩阵
Eigen::MatrixXf & 	hist_f2,//输出 f2的直方图矩阵
Eigen::MatrixXf & 	hist_f3 //输出 f3的直方图矩阵
)	


//加权SPFH求得单点的FPFH (此方法甚用!,他是配合PCL源码所用,单独使用需要注意indeices参数!)
void pcl::FPFHEstimation< PointInT, PointNT, PointOutT >::weightPointSPFHSignature	(	
const Eigen::MatrixXf & 	hist_f1,//输入 f1邻域各点的直方图矩阵
const Eigen::MatrixXf & 	hist_f2,//输入 f2邻域各点的直方图矩阵
const Eigen::MatrixXf & 	hist_f3,//输入 f3邻域各点的直方图矩阵
//
******源码中此方法以indices中的值当作hist_f1,23的行索引即用了邻域点在点云中的索引数,显然直接使用会出错**********
******此方法在源码使用时,增加了一个过渡方法computeSPFHSignatures,保存了邻域点在点云的索引和在矩阵中行索引的映射向量**********
const std::vector< int > & 	indices, //输入 邻域索引  
//
const std::vector< float > & 	dists,//输入 与邻域间距离
Eigen::VectorXf & 	fpfh_histogram 
)	


******源码中的过渡方法computeSPFHSignatures**********
//计算全局索引indices_,即提前设置的setIndex需要计算特征的点,映射向量和特征矩阵
void pcl::FPFHEstimation< PointInT, PointNT, PointOutT >::computeSPFHSignatures	(	
std::vector< int > & 	spf_hist_lookup, //输出 邻域点在点云的索引和在矩阵中行索引的映射向量
Eigen::MatrixXf & 	hist_f1,//输出
Eigen::MatrixXf & 	hist_f2,//输出
Eigen::MatrixXf & 	hist_f3 //输出
)	

说明:PCL提供的其他方法,主要是为了方便代码组织,封装了各种功能的小方法,本质就是方法的互相调用简化代码使得更加清晰,不过因为继承的关系,想要理清这些方法的作用,需要明确PCL的模块的继承组织结构,单独使用时需谨慎。综上,FPFH提供的小方法过于耦合不建议用户单独使用
(PCL为了用户使用方便,不难发现特征计算都最后使用了compute方法,他则是统一重写,其中就是调用了内部的各种小方法,使得用户不管计算什么特征,代码都是类似的,体现了多态的好处)

  • 相比PFH类,FPFH类提供了用户自定义分割Bin数量方法
//三个角度可自定义BIN数量
void pcl::FPFHEstimation< PointInT, PointNT, PointOutT >::setNrSubdivisions	(	
int 	nr_bins_f1,
int 	nr_bins_f2,
int 	nr_bins_f3 
)		
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值