1.原理
类似于2D下的反投影法,即基于某个特征的直方图数据,用已知图像的某些特征来突出其它图像中此类特征的一种方法。
(1)统计已知图像某个特征的直方图,PCL中通常用法向量特征来统计直方图,并把直方图表示为概率的形式。
(2)经过滤波处理后的投影数据被反投影回物体空间。这个过程是通过计算每个投影角度下射线穿过物体的路径,并将滤波后的投影数据按照这些路径均匀地分布回去,从而得到一个初步的结果。
(3)计算源点云和目标点云的直方图数据,并对二者进行点对匹配,得到最终结果。
用2D中两个手掌图像举例子:
(1)已知手掌图像A,然后通过反投影法计算它的特征直方图A_FEATURE:
(2)对另一只手掌图像B,也通过反投影法计算它的特征直方图B_FEATURE:
(3)匹配两个手掌图像的直方图特征,得到mask图像,即得到最终的点对匹配结果:
2.关键函数
(1)本类类定义
pcl::registration::CorrespondenceEstimationBackProjection<pcl::PointXYZ, pcl::PointXYZ, pcl::Normal> registration;
(2)设置源点云及目标点云法线
registration.setSourceNormals(normalsSc); // 设置源点云法线
registration.setTargetNormals(normalsTr); // 设置目标点云法线
(3)设置邻域搜索的点个数
registration.setKSearch(50);
(4)对应点结果和匹配点之间的最短距离
pcl::Correspondences correspondences;
registration.determineCorrespondences(correspondences, 5); // 对应点结果和匹配点之间的最短距离
3.代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/correspondence_estimation_backprojection.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
int main()
{
/****************基于反投法寻找对应点对********************/
pcl::PointCloud<pcl::PointXYZ>::Ptr source(new pcl::PointCloud<pcl::PointXYZ>); // 源点云
pcl::PointCloud<pcl::PointXYZ>::Ptr target(new pcl::PointCloud<pcl::PointXYZ>); // 目标点云
pcl::io::loadPCDFile("D:/code/csdn/data/person2.pcd", *source);
pcl::io::loadPCDFile("D:/code/csdn/data/person3.pcd", *target);
// 基于反投法寻找对应点对
// 对源点云进行法线估计
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> neSc;
pcl::search::KdTree<pcl::PointXYZ>::Ptr treeSc(new pcl::search::KdTree<pcl::PointXYZ>);
neSc.setNumberOfThreads(8);
neSc.setInputCloud(source);
neSc.setSearchMethod(treeSc);
neSc.setKSearch(50);
pcl::PointCloud<pcl::Normal>::Ptr normalsSc(new pcl::PointCloud<pcl::Normal>);
neSc.compute(*normalsSc);
// 对目标点云进行法线估计
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> neTr;
pcl::search::KdTree<pcl::PointXYZ>::Ptr treeTr(new pcl::search::KdTree<pcl::PointXYZ>);
neTr.setNumberOfThreads(8);
neTr.setInputCloud(target);
neTr.setSearchMethod(treeTr);
neTr.setKSearch(50);
pcl::PointCloud<pcl::Normal>::Ptr normalsTr(new pcl::PointCloud<pcl::Normal>);
neTr.compute(*normalsTr);
// 获取匹配点对
pcl::registration::CorrespondenceEstimationBackProjection<pcl::PointXYZ, pcl::PointXYZ, pcl::Normal> registration;
registration.setInputSource(source);
registration.setSourceNormals(normalsSc); // 设置源点云法线
registration.setTargetNormals(normalsTr); // 设置目标点云法线
registration.setInputTarget(target); // 设置目标点云
registration.setKSearch(50); // 设置邻域搜索的点个数
pcl::Correspondences correspondences;
registration.determineCorrespondences(correspondences, 5); // 对应点结果和匹配点之间的最短距离
/****************展示********************/
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("CorrespondenceEstimationBackProjection"));
viewer->addPointCloud<pcl::PointXYZ>(source, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(source, 0, 255, 0), "source");
viewer->addPointCloud<pcl::PointXYZ>(target, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(target, 255, 0, 0), "target");
viewer->addCorrespondences<pcl::PointXYZ>(source, target, correspondences, "correspondence");
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return 0;
}
4.结果展示
相关原理解释: