利用PCL实现点云配准

一、介绍

This document demonstrates using the Iterative Closest Point algorithm in your code which can determine if one PointCloud is just a rigid transformation of another by minimizing the distances between the points of two pointclouds and rigidly transforming them.

使用ICP算法实现点云的配准,刚性变换4*4矩阵。

How to use the Normal Distributions Transform (NDT) algorithm to determine a rigid transformation between two large point clouds, both over 100,000 points.

使用NDT算法实现大数据的点云配准,刚性变换4*4矩阵。

二、代码

1、ICP算法

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>

int main()
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>(5, 1));
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);

	for (auto& point : *cloud_in)
	{
		point.x = 1024 * rand() / (RAND_MAX + 1.0f);
		point.y = 1024 * rand() / (RAND_MAX + 1.0f);
		point.z = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	std::cout << "cloud_in num = " << cloud_in->size() << " ################## " << std::endl;
	for (auto& point : *cloud_in)
		std::cout << point << std::endl;

	*cloud_out = *cloud_in;
	for (auto& point : *cloud_out)
		point.x += 0.7f;
	std::cout << "cloud_out num = " << cloud_out->size() << " ################## " << std::endl;
	for (auto& point : *cloud_out)
		std::cout << point << std::endl;

	pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
	icp.setInputSource(cloud_in);
	icp.setInputTarget(cloud_out);

	pcl::PointCloud<pcl::PointXYZ> Final;
	icp.align(Final);
	std::cout << "Final num = " << Final.size() << " ################## " << std::endl;
	for (auto& point : Final)
		std::cout << point << std::endl;

	std::cout << "has converged:" << icp.hasConverged() << " score: " << icp.getFitnessScore() << std::endl;
	std::cout << icp.getFinalTransformation() << std::endl;

	return (0);
}

2、NDT算法

    数据链接:链接:https://pan.baidu.com/s/1jR7k5iI-acVyyehKcYbetA?pwd=mr16
    提取码:mr16

#include <iostream>
#include <thread>
#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>

using namespace std::chrono_literals;
using namespace std;

int main()
{
	// Loading first scan of room.
	pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("room_scan1.pcd", *target_cloud) == -1)
	{
		PCL_ERROR("Couldn't read file room_scan1.pcd \n");
		return (-1);
	}
	cout << "Loaded " << target_cloud->size() << " data points from room_scan1.pcd" << endl;

	// Loading second scan of room from new perspective.
	pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("room_scan2.pcd", *input_cloud) == -1)
	{
		PCL_ERROR("Couldn't read file room_scan2.pcd \n");
		return (-1);
	}
	cout << "Loaded " << input_cloud->size() << " data points from room_scan2.pcd" << endl;

	// Filtering input scan to roughly 10% of original size to increase speed of registration.
	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 from room_scan2.pcd" << endl;

	// Initializing Normal Distributions Transform (NDT).
	pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;

	// Setting scale dependent NDT parameters
	// Setting minimum transformation difference for termination condition.
	ndt.setTransformationEpsilon(0.01);
	// Setting maximum step size for More-Thuente line search.
	ndt.setStepSize(0.1);
	// Setting Resolution of NDT grid structure (VoxelGridCovariance).
	ndt.setResolution(1.0);
	// Setting max number of registration iterations.
	ndt.setMaximumIterations(35);
	// Setting point cloud to be aligned.
	ndt.setInputSource(filtered_cloud);
	// Setting point cloud to be aligned to.
	ndt.setInputTarget(target_cloud);

	// Set initial alignment estimate found using robot odometry.
	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();
	cout << init_guess << endl;

	// Calculating required rigid transform to align the input cloud to the target cloud.
	pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	ndt.align(*output_cloud, init_guess);
	cout << ndt.getFinalTransformation() << endl;
	cout << "NDT has converged:" << ndt.hasConverged() << " score: " << ndt.getFitnessScore() << endl;

	// Transforming unfiltered input cloud using found transform.
	pcl::transformPointCloud(*input_cloud, *output_cloud, ndt.getFinalTransformation());
	cout << "transformResult " << output_cloud->size() << " data points from room_scan2.pcd" << endl;

	// Saving transformed input cloud.
	pcl::io::savePCDFileASCII("room_scan2_transformed.pcd", *output_cloud);

	// Initializing point cloud visualizer
	pcl::visualization::PCLVisualizer::Ptr
	viewer_final(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer_final->setBackgroundColor(0, 0, 0);

	// Coloring and visualizing target cloud (red).
	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");

	// Coloring and visualizing transformed input cloud (green).
	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");

	// Starting visualizer
	viewer_final->addCoordinateSystem(1.0, "global");
	viewer_final->initCameraParameters();

	// Wait until visualizer window is closed.
	while (!viewer_final->wasStopped())
	{
		viewer_final->spinOnce(100);
		this_thread::sleep_for(100ms);
	}

	return (0);
}

三、结论

1、ICP

参考:How to use iterative closest point — Point Cloud Library 0.0 documentation 

2、NDT

参考:How to use Normal Distributions Transform — Point Cloud Library 0.0 documentation

四、ICP配准

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/registration/icp.h>
#include <thread>

using namespace std::chrono_literals;

int main()
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
	if (-1 == pcl::io::loadPLYFile("bun000.ply", *cloud1))
	{
		std::cout << "read ply file error!" << std::endl;
	}
	std::cout << "cloud1 size = " << cloud1->points.size() << std::endl;  // 204800

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);
	if (-1 == pcl::io::loadPLYFile("bun045.ply", *cloud2))
	{
		std::cout << "read ply file error!" << std::endl;
	}
	std::cout << "cloud2 size = " << cloud2->points.size() << std::endl;  // 204800

	pcl::PointCloud<pcl::PointXYZ> source;
	for (auto point : *cloud1)
	{
		if (isfinite(point.x) && isfinite(point.y) && isfinite(point.z))
		{
			source.push_back(point);
		}
	}
	source.width = source.size();
	source.height = 1;
	source.is_dense = false;
	std::cout << "source size = " << source.points.size() << std::endl;

	pcl::PointCloud<pcl::PointXYZ> target;
	for (auto point : *cloud2)
	{
		if (isfinite(point.x) && isfinite(point.y) && isfinite(point.z))
		{
			target.push_back(point);
		}
	}
	target.width = target.size();
	target.height = 1;
	target.is_dense = false;
	std::cout << "target size = " << target.points.size() << std::endl;

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudSource = source.makeShared();
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTarget = target.makeShared();

	pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
	icp.setInputSource(cloudSource);
	icp.setInputTarget(cloudTarget);
	pcl::PointCloud<pcl::PointXYZ> Final;
	icp.align(Final);
	std::cout << "Final num = " << Final.size() << std::endl;
	std::cout << "has converged:" << icp.hasConverged() << " score: " << icp.getFitnessScore() << std::endl;
	std::cout << icp.getFinalTransformation() << std::endl;

	pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::transformPointCloud(*cloudSource, *output, icp.getFinalTransformation());

	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer->setBackgroundColor(0, 0, 0);

	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> target_color(cloudTarget, 255, 0, 0);
	viewer->addPointCloud<pcl::PointXYZ>(cloudTarget, target_color, "target cloud");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target cloud");

	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> output_color(cloudSource, 0, 255, 0);
	viewer->addPointCloud<pcl::PointXYZ>(cloudSource, output_color, "output cloud");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "output cloud");

	// viewer->addCoordinateSystem(0.1, "global");
	viewer->initCameraParameters();
	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		std::this_thread::sleep_for(100ms);
	}

	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/Goodness2020/article/details/132187181