PCL 3D-NDT 算法实现点云配准

算法原理

在这里插入图片描述

代码实现

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/ndt.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/console/time.h>  

using namespace std;
int
main(int argc, char** argv)
{
	pcl::console::TicToc time;
	//加载第一次扫描数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile<pcl::PointXYZ>("G.pcd", *target_cloud);
	//加载从新视角得到的第二次扫描数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile<pcl::PointXYZ>("G1.pcd", *input_cloud);
	cout << "从目标点云中读取 " << target_cloud->size() << " 个点" << endl;
	cout << "从源点云中读取 " << input_cloud->size() << " 个点" << endl;
	//将输入的扫描过滤到原始尺寸的大概10%以提高匹配的速度。
	pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
	approximate_voxel_filter.setLeafSize(0.2, 0.2, 0.2);
	approximate_voxel_filter.setInputCloud(input_cloud);
	approximate_voxel_filter.filter(*filtered_cloud);
	cout << "Filtered cloud contains " << filtered_cloud->size()
		<< " data points " << endl;
	//初始化正态分布变换(NDT)
	time.tic();
	pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;
	//设置依赖尺度NDT参数
	//为终止条件设置最小转换差异
	ndt.setTransformationEpsilon(0.01);
	//为More-Thuente线搜索设置最大步长
	ndt.setStepSize(0.1);
	//设置NDT网格结构的分辨率(VoxelGridCovariance)
	ndt.setResolution(1.0);
	//设置匹配迭代的最大次数
	ndt.setMaximumIterations(35);
	// 设置要配准的点云
	ndt.setInputCloud(filtered_cloud);
	//设置点云配准目标
	ndt.setInputTarget(target_cloud);
	/*
	//设置使用机器人测距法得到的初始对准估计结果
	Eigen::AngleAxisf init_rotation(0.6931, Eigen::Vector3f::UnitZ());
	Eigen::Translation3f init_translation(1.79387, 0.720047, 0);
	Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix();*/
	//计算需要的刚体变换以便将输入的点云匹配到目标点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	ndt.align(*output_cloud);
	cout << "NDT has converged:" << ndt.hasConverged()
		<< " score: " << ndt.getFitnessScore() << endl;
	cout << "Applied " << 35 << " NDT iterations in " << time.toc() << " ms" << endl;
	cout << "变换矩阵:\n" << ndt.getFinalTransformation() << endl;
	//使用创建的变换对未过滤的输入点云进行变换
	pcl::transformPointCloud(*input_cloud, *output_cloud, ndt.getFinalTransformation());
	//保存转换的输入点云
	//pcl::io::savePCDFileASCII(".pcd", *output_cloud);
	// 初始化点云可视化界面
	boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer_final(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer_final->setBackgroundColor(0, 0, 0);
	//对源点云着色并可视化
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		source_color(input_cloud, 255, 0, 255);
	viewer_final->addPointCloud<pcl::PointXYZ>(input_cloud, source_color, "source cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "source cloud");
	//对目标点云着色(红色)并可视化
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		target_color(target_cloud, 255, 0, 0);
	viewer_final->addPointCloud<pcl::PointXYZ>(target_cloud, target_color, "target cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "target cloud");
	//对转换后的源点云着色(绿色)并可视化
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		output_color(output_cloud, 0, 255, 0);
	viewer_final->addPointCloud<pcl::PointXYZ>(output_cloud, output_color, "output cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "output cloud");
	// 启动可视化
	//viewer_final->addCoordinateSystem(0.1);
	//viewer_final->initCameraParameters();
	//等待直到可视化窗口关闭。
	while (!viewer_final->wasStopped())
	{
		viewer_final->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
	return (0);
}

结果展示

在这里插入图片描述

官网链接pcl::NormalDistributionsTransform

猜你喜欢

转载自blog.csdn.net/qq_36686437/article/details/105824202