欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ICP配准算法研究

程序员文章站 2024-03-17 18:41:28
...

       最近,在学习PCL当中的ICP配准算法,对点云数据进行配准。整体来讲,迭代最近点算法是已经很成熟的配准算法,但是,仍有相关研究者对其进行进一步的改进。在我最近阶段看的文章中,对于改进的该算法的方面重在于:①直接缩短ICP算法运行的时间;②.改进相应的分割算法,为后续ICP配准缩短时间;③.改进初始配准算法,使得源点云与目标点云之间的距离更进,ICP在配准过程中,迭代次数大大减少;④.改进拓扑关系(K-d树、Octree)等等。但是,对ICP本身算法的改进少。个人认为,ICP算法已相当成熟,若能够开发出基于PCL的ICP算法的动态调试参数的方法,就能自动算出最优解。这是很理想的,但是难度大。若有哪位博友想做动态参数计算设计算法的,我们可以合作。

      以下,是我最近做的一部分ICP算法的最基本的代码程序,希望各位博友能指点。其中,源点云与目标点云我已经预处理过了,所以相应的预处理代码就没有上传到这篇博文中。

      在程序中,显示那块,出现了问题,不知是我的vtk有问题,还是哪里。但是程序运行编译是没有任何问题的,VS13+PCL1.8。

      源点云与目标点云我不能打包成文件上传,各位博友研究者可以联系我,再发给各位吧。

      在程序的最后,我将配准完以后的点云,存储在“C://Users//YCJ//Desktop//pcd文件夹//aaaaa.pcd”这里,但是最后用Cloudcompare显示的时候,确只是显示了一个点云,按理说应该是两幅配准完以后的完整点云,我就很不明白,这是为什么?难道不能这么写么?还是说icp.align(*cloud_source_registration);这一步当中,最后配准完以后的点云没有存储在cloud_source_registration当中?我也希望各位博友能提出自己的解决方案,共同完成并优化程序。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include<pcl\visualization\cloud_viewer.h>


int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_source(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_target(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_source_registration(new pcl::PointCloud<pcl::PointXYZRGB>);


	// 检查参数
	/*if(argc != 3) {
	std::cout << "ERROR: the number of arguments is illegal!" << std::endl;
	return -1;
	}*/

	// 载入点云文件
	if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("C://Users//YCJ//Desktop//pcd文件夹//rabbit_t11.pcd", *cloud_source) == -1) { 
		std::cout << "load source failed!" << std::endl;                //载入源点云
		return -1;
	}
	std::cout << "source loaded!" << std::endl;

	if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("C://Users//YCJ//Desktop//pcd文件夹//rabbit12.pcd", *cloud_target) == -1) { 
		std::cout << "load target failed!" << std::endl;                //载入目标点云
		return -1;
	}
	std::cout << "target loaded!" << std::endl;

	// ICP配准
	pcl::IterativeClosestPoint<pcl::PointXYZRGB, pcl::PointXYZRGB> icp;       //设置迭代最近点的对象icp
	pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree1(new pcl::search::KdTree<pcl::PointXYZRGB>);
	tree1->setInputCloud(cloud_source);                                  //设置源点云的kd-tree
	pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZRGB>);
	tree2->setInputCloud(cloud_target);                                  //设置目标点云的kd-tree
	icp.setSearchMethodSource(tree1);        //设置源点云的搜索方法
	icp.setSearchMethodTarget(tree2);        //设置目标点云的搜索方法
	icp.setInputSource(cloud_source);        //输入源点云
	icp.setInputTarget(cloud_target);        //输入目标点云
	icp.setMaxCorrespondenceDistance(1500);   //设置最大的对应点距离
	icp.setTransformationEpsilon(1e-10);      //设置精度
	icp.setEuclideanFitnessEpsilon(0.01);
	icp.setMaximumIterations(300);            //设置最大的迭代次数
	icp.align(*cloud_source_registration);    //开始配准
	std::cout << "获取最终的刚体变换矩阵:" << std::endl;
	Eigen::Matrix4f transformation = icp.getFinalTransformation();
	std::cout << transformation << std::endl;

	pcl::PCDWriter writer;
	writer.write<pcl::PointXYZRGB>("C://Users//YCJ//Desktop//pcd文件夹//aaaaa.pcd", *cloud_source_registration, false);

	//pcl::visualization::CloudViewer viewer("cloud_source_registration");
	//viewer.showCloud(cloud_source_registration);

	// 显示
	//pcl::visualization::PCLVisualizer p;
	//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_r_h(cloud_source_registration, 255, 0, 0);
	//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> tgt_h(cloud_target, 0, 255, 0);
	//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h(cloud_source, 0, 0, 255);
	//p.addPointCloud(cloud_source_registration, src_r_h, "source_r");
	//p.addPointCloud(cloud_target, tgt_h, "target");
	//p.addPointCloud(cloud_source, src_h, "source");
	//p.spin();
	return 0;
}

      运行结果如下所示:

      编译成功

ICP配准算法研究

      运行成功

  ICP配准算法研究

     运行结果

ICP配准算法研究