配准结果
红色是目标点云(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