pcl调用icp算法拼接两个点云

pcl调用icp算法拼接两个点云


浏览了一圈,发现有些程序看似读取了两个点云进行拼接实则是将第一个点云进行旋转拼接,这??

丰衣足食靠自己。

PCL:1.8.1
IDE:vs2017
拼接两个角度的点云 main.cpp.


#include <iostream>                 //标准输入输出头文件
#include <pcl/io/pcd_io.h>          //I/O操作头文件
#include <pcl/point_types.h>        //点类型定义头文件
#define BOOST_TYPEOF_EMULATION  //要加在#include <pcl/registration/icp.h>前
#include <pcl/registration/icp.h>   //ICP配准类相关头文件
#include <pcl/visualization/cloud_viewer.h>//点云查看窗口头文件
#include <pcl/visualization/pcl_visualizer.h>//可视化头文件

typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;

bool next_iteration = false;

void print4x4Matrix(const Eigen::Matrix4d & matrix)    //打印旋转矩阵和平移矩阵
{
	printf("Rotation matrix :\n");
	printf("    | %6.3f %6.3f %6.3f | \n", matrix(0, 0), matrix(0, 1), matrix(0, 2));
	printf("R = | %6.3f %6.3f %6.3f | \n", matrix(1, 0), matrix(1, 1), matrix(1, 2));
	printf("    | %6.3f %6.3f %6.3f | \n", matrix(2, 0), matrix(2, 1), matrix(2, 2));
	printf("Translation vector :\n");
	printf("t = < %6.3f, %6.3f, %6.3f >\n\n", matrix(0, 3), matrix(1, 3), matrix(2, 3));
}

void KeyboardEventOccurred(const pcl::visualization::KeyboardEvent& event, void* nothing)
{  //使用空格键来增加迭代次数,并更新显示
	if (event.getKeySym() == "space" && event.keyDown())
		next_iteration = true;
}


int main(int argc, char** argv)
{
	// 创建点云指针
	PointCloudT::Ptr cloud_in(new PointCloudT);  // 原始点云
	PointCloudT::Ptr cloud_icp(new PointCloudT);  // ICP 输出点云
	PointCloudT::Ptr cloud_tr(new PointCloudT);  // 匹配点云

	//读取pcd文件
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("YourPCDFile01.pcd", *cloud_in) == -1)
	{
		PCL_ERROR("Couldn't read file1 \n");
		return (-1);
	}
	std::cout << "Loaded " << cloud_in->size() << " data points from file1" << std::endl;

	if (pcl::io::loadPCDFile<pcl::PointXYZ>("YourPCDFile02.pcd", *cloud_icp) == -1)
	{
		PCL_ERROR("Couldn't read file2 \n");
		return (-1);
	}
	std::cout << "Loaded " << cloud_icp->size() << " data points from file2" << std::endl;

	int iterations = 1;  // 默认的ICP迭代次数
	*cloud_tr = *cloud_icp;
	//icp配准
	pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; //创建ICP对象,用于ICP配准
	icp.setMaximumIterations(iterations);    //设置最大迭代次数iterations=true
	icp.setInputCloud(cloud_tr); //设置输入点云
	icp.setInputTarget(cloud_in); //设置目标点云(输入点云进行仿射变换,得到目标点云)
	icp.align(*cloud_icp);          //匹配后源点云
	//pcl::io::savePLYFile("Final.ply",*cloud_icp); //保存
	icp.setMaximumIterations(1);  // 设置为1以便下次调用
	std::cout << "Applied " << iterations << " ICP iteration(s)" << std::endl;
	if (icp.hasConverged())//icp.hasConverged ()=1(true)输出变换矩阵的适合性评估
	{
		std::cout << "\nICP has converged, score is " << icp.getFitnessScore() << std::endl;
		std::cout << "\nICP transformation " << iterations << " : cloud_icp -> cloud_in" << std::endl;
	}
	else
	{
		PCL_ERROR("\nICP has not converged.\n");
		return (-1);
	}


	//可视化
	pcl::visualization::PCLVisualizer viewer("ICP demo");
	// 创建两个观察视点
	int v1(0);
	int v2(1);
	viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);
	// 定义显示的颜色信息
	float bckgr_gray_level = 0.0;  // Black
	float txt_gray_lvl = 1.0 - bckgr_gray_level;
	// 原始的点云设置为白色的
	pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_in_color_h(cloud_in, (int)255 * txt_gray_lvl, (int)255 * txt_gray_lvl,
		(int)255 * txt_gray_lvl);

	viewer.addPointCloud(cloud_in, cloud_in_color_h, "cloud_in_v1", v1);//设置原始的点云都是显示为白色
	viewer.addPointCloud(cloud_in, cloud_in_color_h, "cloud_in_v2", v2);

	// 转换后的点云显示为绿色
	pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_tr_color_h(cloud_tr, 20, 180, 20);
	viewer.addPointCloud(cloud_tr, cloud_tr_color_h, "cloud_tr_v1", v1);

	// ICP配准后的点云为红色
	pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_icp_color_h(cloud_icp, 180, 20, 20);
	viewer.addPointCloud(cloud_icp, cloud_icp_color_h, "cloud_icp_v2", v2);

	// 加入文本的描述在各自的视口界面
	//在指定视口viewport=v1添加字符串“white 。。。”其中"icp_info_1"是添加字符串的ID标志,(10,15)为坐标16为字符大小 后面分别是RGB值
	viewer.addText("White: Original point cloud\nGreen: Matrix transformed point cloud", 10, 15, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "icp_info_1", v1);
	viewer.addText("White: Original point cloud\nRed: ICP aligned point cloud", 10, 15, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "icp_info_2", v2);

	std::stringstream ss;
	ss << iterations;            //输入的迭代的次数
	std::string iterations_cnt = "ICP iterations = " + ss.str();
	viewer.addText(iterations_cnt, 10, 60, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "iterations_cnt", v2);

	// 设置背景颜色
	viewer.setBackgroundColor(bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v1);
	viewer.setBackgroundColor(bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v2);

	// 设置相机的坐标和方向
	viewer.setCameraPosition(-3.68332, 2.94092, 5.71266, 0.289847, 0.921947, -0.256907, 0);
	viewer.setSize(1280, 1024);  // 可视化窗口的大小

	// 注册按键回调函数
	viewer.registerKeyboardCallback(&KeyboardEventOccurred, (void*)NULL);

	//显示
	while (!viewer.wasStopped())
	{
		viewer.spinOnce();

		//按下空格键的函数
		if (next_iteration)
		{
			// 最近点迭代算法
			icp.align(*cloud_icp);
			if (icp.hasConverged())
			{
				printf("\033[11A");  // Go up 11 lines in terminal output.
				printf("\nICP has converged, score is %+.0e\n", icp.getFitnessScore());
				std::cout << "\nICP transformation " << ++iterations << " : cloud_icp -> cloud_in" << std::endl;

				ss.str("");
				ss << iterations;
				std::string iterations_cnt = "ICP iterations = " + ss.str();
				viewer.updateText(iterations_cnt, 10, 60, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "iterations_cnt");
				viewer.updatePointCloud(cloud_icp, cloud_icp_color_h, "cloud_icp_v2");
			}
			else
			{
				PCL_ERROR("\nICP has not converged.\n");
				return (-1);
			}
		}
		next_iteration = false;
	}


	return 0;
}

因为原始数据就还不错,就没有做sac
运行如右图结果:
迭代了30次

好的,下面是用PCL实现fpfh+icp点云配准算法的代码。 首先,我们需要包含PCL库的头文件和一些必要的命名空间: ```cpp #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/registration/icp.h> #include <pcl/features/normal_3d.h> #include <pcl/features/fpfh.h> ``` 然后,我们定义一些类型和变量: ```cpp typedef pcl::PointXYZ PointT; typedef pcl::PointCloud<PointT> PointCloudT; PointCloudT::Ptr source, target; // 源点云和目标点云 PointCloudT::Ptr source_keypoints, target_keypoints; // 源点云和目标点云的关键点 pcl::PointCloud<pcl::Normal>::Ptr source_normals, target_normals; // 源点云和目标点云的法线 pcl::FPFHEstimation<PointT, pcl::Normal, pcl::FPFHSignature33>::Ptr fpfh_estimator; // FPFH 估计器 pcl::IterativeClosestPoint<PointT, PointT> icp; // ICP 配准器 ``` 接着,我们加载源点云和目标点云,并对它们进行下采样: ```cpp source.reset(new PointCloudT); target.reset(new PointCloudT); // 加载源点云和目标点云 pcl::io::loadPCDFile("source.pcd", *source); pcl::io::loadPCDFile("target.pcd", *target); // 对源点云和目标点云进行下采样 pcl::VoxelGrid<PointT> sor; sor.setLeafSize(0.01f, 0.01f, 0.01f); sor.setInputCloud(source); sor.filter(*source); sor.setInputCloud(target); sor.filter(*target); ``` 然后,我们对源点云和目标点云算法线和关键点,并计算FPFH特征描述子: ```cpp // 计算源点云和目标点云的法线 pcl::NormalEstimation<PointT, pcl::Normal> ne; pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>()); ne.setSearchMethod(tree); ne.setInputCloud(source); ne.setKSearch(20); source_normals.reset(new pcl::PointCloud<pcl::Normal>); ne.compute(*source_normals); ne.setInputCloud(target); target_normals.reset(new pcl::PointCloud<pcl::Normal>); ne.compute(*target_normals); // 计算源点云和目标点云的关键点 pcl::UniformSampling<PointT> uniform_sampling; uniform_sampling.setInputCloud(source); uniform_sampling.setRadiusSearch(0.02f); source_keypoints.reset(new PointCloudT); uniform_sampling.compute(*source_keypoints); uniform_sampling.setInputCloud(target); target_keypoints.reset(new PointCloudT); uniform_sampling.compute(*target_keypoints); // 计算源点云和目标点云的 FPFH 特征描述子 fpfh_estimator.reset(new pcl::FPFHEstimation<PointT, pcl::Normal, pcl::FPFHSignature33>); fpfh_estimator->setInputCloud(source_keypoints); fpfh_estimator->setInputNormals(source_normals); fpfh_estimator->setSearchMethod(tree); fpfh_estimator->setRadiusSearch(0.05f); pcl::PointCloud<pcl::FPFHSignature33>::Ptr source_features(new pcl::PointCloud<pcl::FPFHSignature33>); fpfh_estimator->compute(*source_features); fpfh_estimator->setInputCloud(target_keypoints); fpfh_estimator->setInputNormals(target_normals); pcl::PointCloud<pcl::FPFHSignature33>::Ptr target_features(new pcl::PointCloud<pcl::FPFHSignature33>); fpfh_estimator->compute(*target_features); ``` 最后,我们使用ICP进行点云配准: ```cpp // 设置ICP参数 icp.setInputSource(source_keypoints); icp.setInputTarget(target_keypoints); icp.setMaxCorrespondenceDistance(0.1f); icp.setMaximumIterations(50); icp.setTransformationEpsilon(1e-8); icp.setEuclideanFitnessEpsilon(1e-6); // 设置ICP的匹配特征 pcl::PointCloud<pcl::PointNormal>::Ptr aligned_source(new pcl::PointCloud<pcl::PointNormal>); pcl::concatenateFields(*source_keypoints, *source_normals, *aligned_source); pcl::PointCloud<pcl::PointNormal>::Ptr aligned_target(new pcl::PointCloud<pcl::PointNormal>); pcl::concatenateFields(*target_keypoints, *target_normals, *aligned_target); icp.setSourceFeatures(source_features); icp.setTargetFeatures(target_features); icp.align(*aligned_source); // 输出配准结果 std::cout << "ICP has converged with score: " << icp.getFitnessScore() << std::endl; std::cout << "Transformation matrix:" << std::endl << icp.getFinalTransformation() << std::endl; ``` 以上就是用PCL实现fpfh+icp点云配准算法的完整代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值