pcl里面的点特征直方图(PFH)

表面法线和曲率可以好的代表一个点的几何特征。然而它们算得很快,而且算法简单,但是它们不能捕获细节,它们只是点的近邻的几何特征的近似估计。作为一个直接的结论,大多数的场景往往会包括很多有着相似特征的点,这会减少它们所带来的消息量。

这次我们将引进一个叫做PFH(point feature histgrams)的3D特征描述器,同时还将显示出它的一些理论优势,并讨论它的一些实现细节。

PFH的目标是通过使用一个点周围的多维直方图的平均曲率来编码一个点的k个最近邻的几何属性。这个高维空间提供了一些有用的特征代表,同时关于6位位姿不变的,同时和可以很好的应对不同的采样密度和近邻的噪声水平。

一个点特征直方图是与点的最近邻和法线有关的,简单的说,它企图通过考虑各个预测法线方向之间的影响来捕获最好的采样平面。最终的高维空间因此和每个点的表面法线的方向有关。

下面的图展示了一个PFH在计算Pq这个点时候的影响区域图,Pq这个点用红色标记并放在半径为r的圆圈的中央,然后它的所有近邻(离点的距离小于半径r)都通过一个网格来间接的相邻着。下面的PFH描述器作为了一个直方图计算了所有匹配的点之间的关系,有一个O(k方)的复杂度。

计算pi和pj之间的绝对差,和与它们相关联的法线ns和nj,我们定义了一个固定的坐标系在某个点上。

我发现官网里面的上面的式子与下面的图对应不上,以图为标准,式子里面的那个v向量的方向和大小与图里面的都对不上。使用上面的uvw的坐标系,ns法线和ni法线的差可以化解为下面的3个角度的差异(因为他们的模都是一样的):

d是两点距离的平方,是每对点的4要素,这样就把原来的12个值(2x每个点的{(x,y,z),(nx,ny,nz)})减低为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 
下面是使用PCL库实现汉明距离特征匹配的代码示例。 ```cpp #include <pcl/features/shot.h> #include <pcl/registration/correspondence_estimation.h> #include <pcl/registration/correspondence_rejection_one_to_one.h> #include <pcl/registration/correspondence_rejection_sample_consensus.h> #include <pcl/registration/transformation_estimation_svd.h> pcl::PointCloud<pcl::PointXYZ>::Ptr cloudA(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloudB(new pcl::PointCloud<pcl::PointXYZ>); // 读取云A和云B pcl::io::loadPCDFile<pcl::PointXYZ>("cloudA.pcd", *cloudA); pcl::io::loadPCDFile<pcl::PointXYZ>("cloudB.pcd", *cloudB); // 计算云A和云B的SHOT特征 pcl::SHOTEstimation<pcl::PointXYZ, pcl::SHOT352> shot; pcl::PointCloud<pcl::SHOT352>::Ptr descriptorsA(new pcl::PointCloud<pcl::SHOT352>); pcl::PointCloud<pcl::SHOT352>::Ptr descriptorsB(new pcl::PointCloud<pcl::SHOT352>); shot.setInputCloud(cloudA); shot.compute(*descriptorsA); shot.setInputCloud(cloudB); shot.compute(*descriptorsB); // 初始化特征匹配器 pcl::registration::CorrespondenceEstimation<pcl::SHOT352, pcl::SHOT352> est; est.setInputSource(descriptorsA); est.setInputTarget(descriptorsB); // 计算云A和云B之间的匹配 pcl::Correspondences correspondences; est.determineCorrespondences(correspondences); // 剔除1对N和N对1的匹配 pcl::registration::CorrespondenceRejectorOneToOne rejector; rejector.setInputCorrespondences(correspondences); rejector.getCorrespondences(correspondences); // 使用RANSAC算法剔除离群并计算变换矩阵 pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> te; pcl::registration::CorrespondenceRejectorSampleConsensus<pcl::PointXYZ> ransac(&te); ransac.setInputSource(cloudA); ransac.setInputTarget(cloudB); ransac.setInputCorrespondences(correspondences); ransac.setMaximumIterations(1000); ransac.setInlierThreshold(0.05); ransac.getCorrespondences(correspondences); Eigen::Matrix4f transform = ransac.getBestTransformation(); // 将变换矩阵应用于云A pcl::PointCloud<pcl::PointXYZ>::Ptr transformed(new pcl::PointCloud<pcl::PointXYZ>); pcl::transformPointCloud(*cloudA, *transformed, transform); // 可视化匹配结果 pcl::visualization::PCLVisualizer viewer("Matching result"); viewer.addPointCloud(cloudA, "cloudA"); viewer.addPointCloud(cloudB, "cloudB"); viewer.addPointCloud(transformed, "transformed"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "cloudA"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 0.0, "cloudB"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.0, 1.0, "transformed"); viewer.spin(); ``` 需要注意的是,上述代码中使用的是SHOT特征来描述云的局部特征,而不是汉明距离。SHOT特征是一种基于对关系的局部特征描述子,可以有效地捕获云的几何信息。在计算SHOT特征后,可以使用PCL中提供的特征匹配和变换估计算法来实现云配准。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值