一、概述
PCL中的 pcl::registration::CorrespondenceEstimationNormalShooting
函数用于计算目标点云中与输入点云的法向量具有最小距离的对应点。在估算点对应关系时,主要使用点云中的法向量信息,特别是法向量方向,来估算点云之间的对应关系。它在点对应时通过法向量信息,提高配准的精度,尤其在具有曲率或复杂几何形状的点云上效果显著。
核心步骤
1. 法线计算
使用pcl::NormalEstimation
计算源点云和目标点云的法线:pcl::NormalEstimation norm_est;
norm_est.setInputCloud(source_cloud);
norm_est.setSearchMethod(search_tree);
norm_est.setRadiusSearch(0.05); // 法线估计半径
norm_est.compute(*source_normals);2. 法线投影匹配
通过法线方向投影建立对应关系:pcl::registration::CorrespondenceEstimationNormalShooting corr_est;
corr_est.setInputSource(source_cloud);
corr_est.setSourceNormals(source_normals);
corr_est.setInputTarget(target_cloud);
corr_est.setKSearch(10); // 搜索近邻点数
corr_est.determineCorrespondences(*correspondences);
关键参数说明
o 法线一致性约束 :可通过 setNormalDistanceWeight()
设置法线角度差异的权重,值越大对法线方向一致性要求越严格。o 搜索策略 :支持 KdTree
或Octree
加速搜索,需提前初始化:pcl::search::KdTree::Ptr tree(new pcl::search::KdTree);
corr_est.setSearchMethodTarget(tree);
优化建议
1. 法线平滑处理 :对噪声较大的点云,使用 pcl::MovingLeastSquares
进行平滑处理后再计算法线。2. 异常点过滤 :结合 pcl::registration::CorrespondenceRejectorSampleConsensus
移除错误匹配点对。3. 多特征融合 :若需更高精度,可结合FPFH等特征描述子进行混合匹配。
示例输出 :匹配结果存储在
pcl::Correspondences
对象中,每个对应点包含源点索引(index_query
)和目标点索引(index_match
)。
二、代码
#include
#include
#include
#include
#include
#include
#include
int main()
{
// 读取点云
pcl::PointCloud::Ptr source(new pcl::PointCloud); // 源点云
pcl::PointCloud::Ptr target(new pcl::PointCloud); // 目标点云
if (pcl::io::loadPCDFile("lamp.pcd", *source) == -1 ||
pcl::io::loadPCDFile("lamp1.pcd", *target) == -1)
{
PCL_ERROR("Couldn't read the PCD files!\n");
return-1;
}
// 基于法线信息寻找对应点对
pcl::NormalEstimationOMP ne;
pcl::search::KdTree::Ptr tree(new pcl::search::KdTree);
ne.setNumberOfThreads(8);
ne.setInputCloud(source);
ne.setSearchMethod(tree);
ne.setKSearch(50);
pcl::PointCloud::Ptr normals(new pcl::PointCloud);
ne.compute(*normals);
// 获取匹配点对
pcl::registration::CorrespondenceEstimationNormalShooting registration;
registration.setInputSource(source);
registration.setSourceNormals(normals); // 设置源点云法线
registration.setInputTarget(target); // 设置目标点云
registration.setKSearch(50); // 设置邻域搜索的点个数
pcl::Correspondences correspondences;
registration.determineCorrespondences(correspondences, 1.5);// 对应点结果和匹配点之间的最短距离
// 输出结果到渲染窗口可视化
boost::shared_ptr viewer(new pcl::visualization::PCLVisualizer("CorrespondenceEstimationNormalShooting"));
viewer->addPointCloud(source, pcl::visualization::PointCloudColorHandlerCustom(source, 0, 255, 0), "source");
viewer->addPointCloud(target, pcl::visualization::PointCloudColorHandlerCustom(target, 255, 0, 0), "target");
viewer->addCorrespondences(source, target, correspondences, "correspondence");
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return0;
}