【PCL点云库|点云配准】getRemainingCorrespondences() 和 getCorrespondences() 的区别

2023-05-16

文章目录

  • 解析
  • 源码

解析

同时调用 setInputCorrespondences()getCorrespondences() 相当于调用 getRemainingCorrespondences()

以下两段代码对于同一点云数据计算得到的结果是相同的。

pcl::registration::CorrespondenceRejectorSurfaceNormal rejector;  
rejector.initializeDataContainer<pcl::PointNormal, pcl::PointNormal>();// 初始化点类型和普通类型的数据容器对象
rejector.setInputSource<pcl::PointNormal>(source_normals);
rejector.setInputTarget<pcl::PointNormal>(target_normals);
rejector.setInputNormals<pcl::PointNormal, pcl::PointNormal>(source_normals);
rejector.setTargetNormals<pcl::PointNormal, pcl::PointNormal>(target_normals);

float threshold = cos(M_PI * 10 / 180);//计算cos(10°)
rejector.setThreshold(threshold); // 设置法线之间的夹角阈值,输入的是夹角余弦值
boost::shared_ptr<pcl::Correspondences> correspondences_after_rejector(new pcl::Correspondences);

rejector.getRemainingCorrespondences(*all_correspondences, *correspondences_after_rejector);
pcl::registration::CorrespondenceRejectorSurfaceNormal rejector;  
rejector.initializeDataContainer<pcl::PointNormal, pcl::PointNormal>();// 初始化点类型和普通类型的数据容器对象
rejector.setInputSource<pcl::PointNormal>(source_normals);
rejector.setInputTarget<pcl::PointNormal>(target_normals);
rejector.setInputNormals<pcl::PointNormal, pcl::PointNormal>(source_normals);
rejector.setTargetNormals<pcl::PointNormal, pcl::PointNormal>(target_normals);
rejector.setInputCorrespondences(all_correspondences);

float threshold = cos(M_PI * 10 / 180);//计算cos(10°)
rejector.setThreshold(threshold); // 设置法线之间的夹角阈值,输入的是夹角余弦值
pcl::CorrespondencesPtr correspondences_after_rejector(new pcl::Correspondences);

rejector.getCorrespondences(*correspondences_after_rejector);

源码

/*
 * @Auther: 宇宙爆肝锦标赛冠军
 * @Date: 2022-09-05 09:37:42
 * @LastEditors: 宇宙爆肝锦标赛冠军
 * @LastEditTime: 2022-09-05 09:40:09
 * @Description: PCL 法向量夹角剔除错误匹配点对 https://blog.csdn.net/qq_36686437/article/details/115140916
 */

#include <iostream>
#include <pcl/point_types.h> 
#include <pcl/io/pcd_io.h> 
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/correspondence_estimation_normal_shooting.h>
#include <pcl/registration/correspondence_rejection_surface_normal.h>
#include <pcl/registration/transformation_estimation_lm.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>

using namespace std;

void compute_normal(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointNormal>::Ptr& normals)
{
	pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::PointNormal> n;//OMP加速
	//建立kdtree来进行近邻点集搜索
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
	n.setNumberOfThreads(6);//设置openMP的线程数
	//n.setViewPoint(0,0,0);//设置视点,默认为(0,0,0)
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(10);//点云法向计算时,需要所搜的近邻点大小
	//n.setRadiusSearch(0.03);//半径搜素
	n.compute(*normals);//开始进行法向计
}


int
main(int argc, char** argv)
{
	// 加载目标点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr target(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *target) == -1)
	{
		PCL_ERROR("读取目标点云失败 \n");
		return (-1);
	}
	cout << "从目标点云中读取 " << target->size() << " 个点" << endl;

	// ----------------------加载源点云-----------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr source(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[2], *source) == -1)
	{
		PCL_ERROR("读取源标点云失败 \n");
		return (-1);
	}
	cout << "从源点云中读取 " << source->size() << " 个点" << endl;

	//-------------------------法线估计--------------------------
	pcl::PointCloud<pcl::PointNormal>::Ptr source_normals(new pcl::PointCloud<pcl::PointNormal>);
	compute_normal(source,source_normals);

	pcl::PointCloud<pcl::PointNormal>::Ptr target_normals(new pcl::PointCloud<pcl::PointNormal>);
	compute_normal(target, target_normals);
	//----------------------获取匹配点对-------------------------
	pcl::registration::CorrespondenceEstimationNormalShooting<pcl::PointXYZ, pcl::PointXYZ, pcl::PointNormal>core;
	core.setInputSource(source);
	core.setSourceNormals(source_normals);
	core.setInputTarget(target);
	core.setKSearch(10);
	pcl::CorrespondencesPtr all_correspondences(new pcl::Correspondences);
	core.determineCorrespondences(*all_correspondences, 10);//输入的是源点云上法线与目标点云上对应点之间的最大距离
	//core.determineReciprocalCorrespondences(*all_correspondences);   //确定输入点云与目标点云之间的交互对应关系。
	//-------------------剔除错误匹配点对-----------------------
	pcl::registration::CorrespondenceRejectorSurfaceNormal rejector;  
	rejector.initializeDataContainer<pcl::PointNormal, pcl::PointNormal>();// 初始化点类型和普通类型的数据容器对象
	rejector.setInputSource<pcl::PointNormal>(source_normals);
	rejector.setInputTarget<pcl::PointNormal>(target_normals);
	rejector.setInputNormals<pcl::PointNormal, pcl::PointNormal>(source_normals);
	rejector.setTargetNormals<pcl::PointNormal, pcl::PointNormal>(target_normals);
	rejector.setInputCorrespondences(all_correspondences);

	float threshold = cos(M_PI * 10 / 180);//计算cos(10°)
	rejector.setThreshold(threshold); // 设置法线之间的夹角阈值,输入的是夹角余弦值
	pcl::CorrespondencesPtr correspondences_after_rejector(new pcl::Correspondences);
	rejector.getCorrespondences(*correspondences_after_rejector);
	//cout << "Correspondences (After) : " << correspondences_after_rejector->size() << "\n";

	Eigen::Matrix4f transformation = Eigen::Matrix4f::Identity();

	pcl::registration::TransformationEstimationLM<pcl::PointXYZ, pcl::PointXYZ> trans_est_lm;
	trans_est_lm.estimateRigidTransformation(*source, *target, *correspondences_after_rejector, transformation);
	pcl::PointCloud<pcl::PointXYZ>::Ptr out(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::transformPointCloud(*source, *out, transformation);
	pcl::io::savePCDFile("left.pcd", *out);
	cout << "原始匹配点对有:" << all_correspondences->size() << "对" << endl;
	cout << "剔除错误点对后有:" << correspondences_after_rejector->size() << "对" << endl;
	cout <<"LM求解的变换矩阵为:\n"<< transformation << endl;

	//---------------------------可视化-------------------------
	boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("显示点云"));
	viewer->setBackgroundColor(0, 0, 0);  //设置背景颜色为黑色
	// 对源点云着色可视化 (green).
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>input_color(source, 0, 255, 0);
	viewer->addPointCloud<pcl::PointXYZ>(source, input_color, "source");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "source");
	// 对目标点云着色可视化 (red).
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(target, 255, 0, 0);
	viewer->addPointCloud<pcl::PointXYZ>(target, target_color, "target");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target");

	//----------------------对应关系可视化---------------------
	viewer->addCorrespondences<pcl::PointXYZ>(source, target, *correspondences_after_rejector, "correspondence");
	viewer->initCameraParameters();
	viewer->addText("RejectorSurfaceNormal", 10, 10, "text");
	viewer->spin();
	
	return 0;
}
/*
 * @Auther: 宇宙爆肝锦标赛冠军
 * @Date: 2022-09-05 14:29:02
 * @LastEditors: 宇宙爆肝锦标赛冠军
 * @LastEditTime: 2022-09-05 14:30:20
 * @Description: 调用其他函数,测试效果是否相同
 */

#include <iostream>
#include <pcl/point_types.h> 
#include <pcl/io/pcd_io.h> 
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/correspondence_estimation_normal_shooting.h>
#include <pcl/registration/correspondence_rejection_surface_normal.h>
#include <pcl/registration/transformation_estimation_lm.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>

using namespace std;

void compute_normal(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointNormal>::Ptr& normals)
{
	pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::PointNormal> n;//OMP加速
	//建立kdtree来进行近邻点集搜索
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
	n.setNumberOfThreads(6);//设置openMP的线程数
	//n.setViewPoint(0,0,0);//设置视点,默认为(0,0,0)
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(10);//点云法向计算时,需要所搜的近邻点大小
	//n.setRadiusSearch(0.03);//半径搜素
	n.compute(*normals);//开始进行法向计
}


int
main(int argc, char** argv)
{
	// 加载目标点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr target(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *target) == -1)
	{
		PCL_ERROR("读取目标点云失败 \n");
		return (-1);
	}
	cout << "从目标点云中读取 " << target->size() << " 个点" << endl;

	// ----------------------加载源点云-----------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr source(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[2], *source) == -1)
	{
		PCL_ERROR("读取源标点云失败 \n");
		return (-1);
	}
	cout << "从源点云中读取 " << source->size() << " 个点" << endl;

	//-------------------------法线估计--------------------------
	pcl::PointCloud<pcl::PointNormal>::Ptr source_normals(new pcl::PointCloud<pcl::PointNormal>);
	compute_normal(source,source_normals);

	pcl::PointCloud<pcl::PointNormal>::Ptr target_normals(new pcl::PointCloud<pcl::PointNormal>);
	compute_normal(target, target_normals);
	//----------------------获取匹配点对-------------------------
	pcl::registration::CorrespondenceEstimationNormalShooting<pcl::PointXYZ, pcl::PointXYZ, pcl::PointNormal>core;
	core.setInputSource(source);
	core.setSourceNormals(source_normals);
	core.setInputTarget(target);
	core.setKSearch(10);
	boost::shared_ptr<pcl::Correspondences> all_correspondences(new pcl::Correspondences);
	core.determineCorrespondences(*all_correspondences, 10);//输入的是源点云上法线与目标点云上对应点之间的最大距离
	//core.determineReciprocalCorrespondences(*all_correspondences);   //确定输入点云与目标点云之间的交互对应关系。
	//-------------------剔除错误匹配点对-----------------------
	pcl::registration::CorrespondenceRejectorSurfaceNormal rejector;  
	rejector.initializeDataContainer<pcl::PointNormal, pcl::PointNormal>();// 初始化点类型和普通类型的数据容器对象
	rejector.setInputSource<pcl::PointNormal>(source_normals);
	rejector.setInputTarget<pcl::PointNormal>(target_normals);
	rejector.setInputNormals<pcl::PointNormal, pcl::PointNormal>(source_normals);
	rejector.setTargetNormals<pcl::PointNormal, pcl::PointNormal>(target_normals);
	// rejector.setInputCorrespondences(all_correspondences);

	float threshold = cos(M_PI * 10 / 180);//计算cos(10°)
	rejector.setThreshold(threshold); // 设置法线之间的夹角阈值,输入的是夹角余弦值
	boost::shared_ptr<pcl::Correspondences> correspondences_after_rejector(new pcl::Correspondences);
	// rejector.getCorrespondences(*correspondences_after_rejector);
	rejector.getRemainingCorrespondences(*all_correspondences, *correspondences_after_rejector);
	//cout << "Correspondences (After) : " << correspondences_after_rejector->size() << "\n";

	Eigen::Matrix4f transformation = Eigen::Matrix4f::Identity();

	pcl::registration::TransformationEstimationLM<pcl::PointXYZ, pcl::PointXYZ> trans_est_lm;
	trans_est_lm.estimateRigidTransformation(*source, *target, *correspondences_after_rejector, transformation);
	pcl::PointCloud<pcl::PointXYZ>::Ptr out(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::transformPointCloud(*source, *out, transformation);
	pcl::io::savePCDFile("left.pcd", *out);
	cout << "原始匹配点对有:" << all_correspondences->size() << "对" << endl;
	cout << "剔除错误点对后有:" << correspondences_after_rejector->size() << "对" << endl;
	cout <<"LM求解的变换矩阵为:\n"<< transformation << endl;

	//---------------------------可视化-------------------------
	boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("显示点云"));
	viewer->setBackgroundColor(0, 0, 0);  //设置背景颜色为黑色
	// 对源点云着色可视化 (green).
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>input_color(source, 0, 255, 0);
	viewer->addPointCloud<pcl::PointXYZ>(source, input_color, "source");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "source");
	// 对目标点云着色可视化 (red).
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(target, 255, 0, 0);
	viewer->addPointCloud<pcl::PointXYZ>(target, target_color, "target");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target");

	//----------------------对应关系可视化---------------------
	viewer->addCorrespondences<pcl::PointXYZ>(source, target, *correspondences_after_rejector, "correspondence");
	viewer->initCameraParameters();
	viewer->addText("RejectorSurfaceNormal", 10, 10, "text");
	viewer->spin();
	
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【PCL点云库|点云配准】getRemainingCorrespondences() 和 getCorrespondences() 的区别 的相关文章

随机推荐