点云配准6:tricp算法在pcl上的实现

点云配准6:tricp算法在pcl上的实现目录配准结果点云配准系列准备完整项目文件参数设定及说明数据参数代码结果Bunnyhippo算法小结参考及感谢完配准结果红色是目标点云(target),绿色是源点云(source),蓝色是配准后的源点云。对Bunny成功实现配准点云配准系列点云配准1:配准基础及icp算法点云配准2:icp算法在PCL1.10.0上的实现+源码解析点云配准3:3d-ndt算法在pcl上的实现以及参数设置点云配准4:cloudcompare的使用以及点云配准功能点云配准5:4pcs算法在pcl上的实现点云配

配准结果

红色是目标点云(target),绿色是源点云(source),蓝色是配准后的源点云。
对Bunny成功实现配准
在这里插入图片描述

点云配准系列

点云配准1:配准基础及icp算法
点云配准2:icp算法在PCL1.10.0上的实现+源码解析
点云配准3:3d-ndt算法在pcl上的实现以及参数设置
点云配准4:cloudcompare的使用以及点云配准功能
点云配准5:4pcs算法在pcl上的实现
点云配准6:tricp算法在pcl上的实现
点云配准论文阅读笔记–Efficient Variants of the ICP Algorithm
点云配准论文阅读笔记–Comparing ICP variants on real-world data sets
点云配准论文阅读笔记–(4PCS)4-Points Congruent Sets for Robust Pairwise Surface Registration
点云配准论文阅读笔记–3d-dnt博士论文

准备

本实例是在visual studio2019+pcl1.10.0上进行,环境配置方法在之前的博客已进行详细说明:
vs2019配置pcl1.10.0+点云可视化示例

完整项目文件

免费下载地址:share_noel/PCL/tricp/tricp_registration_carlos20201226.zip
https://blog.csdn.net/qq_41102371/article/details/125646840
愿意用c币支持的朋友也可在此下载:
tricp_registration_carlos20201226.zip
(上述下载链接中csdn与网盘的文件完全相同,只不过网盘免费下载)

参数设定及说明

数据

配准点云来自斯坦福的兔子点云,本文使用其中0度及45度扫描点云,但经过放大处理,xyz都放大了100倍。
本文将45度点云配准至0度点云。
Bunny所有扫描角度点云下载地址:
Stanford官方:http://graphics.stanford.edu/data/3Dscanrep/
或:share_noel/PCL/dataset/stanford_bunny https://blog.csdn.net/qq_41102371/article/details/125646840,pcd格式与原ply格式都有。

参数

tricp的参数设置较3d-ndt与4pcs来说要容易得多,设置重叠度就能实现了
这里的0.7就是重叠度(靠视觉大致推断),配准的结果也就是变换矩阵放在transformation_matrix里面。

tricp.align(*filtered_cloud, (int)filtered_cloud->size() * 0.7f, transformation_matrix);

代码

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <pcl/recognition/trimmed_icp.h>//tricp头文件
#include <time.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/filter.h>


using namespace std;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;


void visualize_pcd(PointCloud::Ptr pcd_src, PointCloud::Ptr pcd_tgt, PointCloud::Ptr pcd_final)
{ 
   
	pcl::visualization::PCLVisualizer viewer("registration Viewer");
	//原始点云绿色
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h(pcd_src, 0, 255, 0);
	//目标点云红色
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> tgt_h(pcd_tgt, 255, 0, 0);
	//匹配好的点云蓝色
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> final_h(pcd_final, 0, 0, 255);

	viewer.setBackgroundColor(255, 255, 255);
	viewer.addPointCloud(pcd_src, src_h, "source cloud");
	viewer.addPointCloud(pcd_tgt, tgt_h, "target cloud");
	viewer.addPointCloud(pcd_final, final_h, "result cloud");
	while (!viewer.wasStopped())
	{ 
   
		viewer.spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

}

int main(int argc, char** argv)
{ 
   
	//加载点云文件
	PointCloud::Ptr cloud_source(new PointCloud);
	PointCloud::Ptr cloud_target(new PointCloud);

	//std::string filename = "point_source/hippo1-1224_s100.pcd";//
	std::string filename = "point_source/bun000_s100.pcd";//

	if (pcl::io::loadPCDFile<pcl::PointXYZ>(filename, *cloud_target) == -1)//*打开点云文件

	{ 
   
		PCL_ERROR("Couldn't read file test_pcd.pcd\n");
		return(-1);
	}

	//filename = "point_source/hippo2-1224_s100.pcd";//
	filename = "point_source/bun045_s100.pcd";//

	if (pcl::io::loadPCDFile<pcl::PointXYZ>(filename, *cloud_source) == -1)//*打开点云文件

	{ 
   
		PCL_ERROR("Couldn't read file test_pcd.pcd\n");
		return(-1);
	}
	pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);//定义降采样后点云
	*filtered_cloud = *cloud_source;

	//体素降采样
	pcl::VoxelGrid<pcl::PointXYZ> voxel_grid;
	voxel_grid.setLeafSize(0.5, 0.5, 0.5);//bunny
	//voxel_grid.setLeafSize(2.0, 2.0, 2.0);//hippo
	voxel_grid.setInputCloud(filtered_cloud);
	voxel_grid.filter(*filtered_cloud);
	std::cout << "down size input_cloud to" << filtered_cloud->size() << endl;//显示降采样后的点云数量

	pcl::recognition::TrimmedICP<PointT, double> tricp;
	tricp.init(cloud_target);//target

	Eigen::Matrix4d transformation_matrix = Eigen::Matrix4d::Identity();
	clock_t start = clock(); 
	/*align(source, num_source_points_to_use, guess_and_result) * source是输入待配准点云(源点云) * num_source_points_to_use就是点云乘以重叠度,不同点云模型重叠度 * guess_and_result是输出算法得到的变换矩阵 */
	tricp.align(*filtered_cloud, (int)filtered_cloud->size() * 0.7f, transformation_matrix);
	clock_t end = clock();

	cout << "time:" << (double)(end - start) / (double)CLOCKS_PER_SEC << " s" << endl;
	cout << "matrix:" << endl << transformation_matrix << endl << endl << endl;

	PointCloud::Ptr cloud_end(new PointCloud);
	pcl::transformPointCloud(*cloud_source, *cloud_end, transformation_matrix);

	visualize_pcd(cloud_source, cloud_target, cloud_end);
	return (0);
}

结果

Bunny

配准成功,且效果较好
在这里插入图片描述
在这里插入图片描述

hippo

配准失败,陷入局部最优
在这里插入图片描述
在这里插入图片描述

算法小结

1、初始位置不好的时候,tricp容易陷入局部最优,比如hippo;
2、但是在初始位置良好的情况下,比如0°和45°的Bunny,tricp使用起来比3d-ndt与4pcs都要方便,设置个重叠度就好,而3d-ndt与4pcs要手动调节参数才能配准。
3、有的点云对初始位置差距太大(比如90°的Bunny配准到0°或者45°的Bunny,3个算法都没法实现),导致这3d-ndt与4pcs也无法得到正确的结果,这时往往不知道是因为点云的问题还是参数设置的问题,就会浪费更多调节参数的时间。

参考及感谢

paper:
Paul J. Besl, Neil D. McKay. A method for registration of 3-D shapes[J]. IEEE Transactions on Pattern Analysis and Machine Intelligence, 1992. 14(2): 239-256.
Chetverikov D, Stepanov D, Krsek P. Robust Euclidean alignment of 3D point sets: the trimmed iterative closest point algorithm[J]. Image and Vision Computing, 2005, 23(3):299-309.
blog:
PCD格式、Trimmed ICP实现、旋转矩阵四元数欧拉角

边学边用,如有错漏,敬请指正
——————————————————————————————–诺有缸的高飞鸟20201226

今天的文章点云配准6:tricp算法在pcl上的实现分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/28789.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注