首页 > 其他分享 >SAC-IA+ICP配准

SAC-IA+ICP配准

时间:2024-03-30 13:31:42浏览次数:26  
标签:src include tgt SAC fpfh PointCloud pcl IA ICP

         SAC-IA(Sample Consensus Initial Alignment)和ICP(Iterative Closest Point)是点云配准中常用的两个算法,可以使用 SAC-IA进行粗配准结合ICP进行精配准。

1.核心思想

  1. SAC-IA

    • 作用:SAC-IA用于粗配准,估计两个点云之间的初始变换矩阵。
    • 流程
      1. 随机选择源点云中的一组点作为初始匹配点对。
      2. 在目标点云中查找与这组点最接近的点。
      3. 使用基于快速点特征直方图(FPFH)的SAC-IA算法,实现粗配准。
      4. 返回初始变换矩阵。
    • 特点:SAC-IA对于匹配的阈值和点对的质量有一定要求。
  2. ICP

    • 作用:ICP用于精确配准,进一步优化位姿。
    • 流程
      1. 使用SAC-IA得到的初始变换矩阵。
      2. 迭代优化变换矩阵,使点云对齐。
      3. ICP通过最小化点云之间的距离来优化变换矩阵。
    • 特点:ICP适用于点云的局部配准,但容易陷入局部最优解。

2.整体流程

  • 首先,使用SAC-IA估计初始的点云位姿。
  • 然后,使用ICP迭代优化变换矩阵,使点云更准确地对齐。

3.相关程序

#include <pcl/registration/ia_ransac.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/fpfh.h>
#include <pcl/search/kdtree.h>
#include <pcl/io/ply_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/filter.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <time.h>
#include <pcl/registration/registration.h>
#include <vector>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/registration.h>
using namespace std;
using pcl::NormalEstimation;
using pcl::search::KdTree;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;


int
main(int argc, char** argv)
{
    PointCloud::Ptr cloud_src_o(new PointCloud);
    pcl::io::loadPLYFile("C:/Users/17927/Desktop/QYQ/D1-2.ply", *source);
    PointCloud::Ptr cloud_tgt_o(new PointCloud);
    pcl::io::loadPLYFile("C:/Users/17927/Desktop/QYQ/D1-1.ply", *target);

    clock_t start = clock();

    pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne_src;
    ne_src.setInputCloud(source);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_src(new pcl::search::KdTree<pcl::PointXYZ>());
    ne_src.setSearchMethod(tree_src);
    pcl::PointCloud<pcl::Normal>::Ptr cloud_src_normals(new pcl::PointCloud<pcl::Normal>);
    ne_src.setRadiusSearch(0.02);
    ne_src.setNumberOfThreads(6); 
    ne_src.compute(*source_normals);


    pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne_tgt;
    ne_tgt.setInputCloud(target);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_tgt(new pcl::search::KdTree<pcl::PointXYZ>());
    ne_tgt.setSearchMethod(tree_tgt);
    pcl::PointCloud<pcl::Normal>::Ptr cloud_tgt_normals(new pcl::PointCloud<pcl::Normal>);
    ne_tgt.setRadiusSearch(0.02);
    ne_tgt.setNumberOfThreads(6); 
    ne_tgt.compute(*target_normals);

    //----------------------计算FPFH------------------------------
    pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh_src;
    fpfh_src.setInputCloud(source);
    fpfh_src.setInputNormals(source_normals);
    pcl::search::KdTree<PointT>::Ptr tree_src_fpfh(new pcl::search::KdTree<PointT>);
    fpfh_src.setSearchMethod(tree_src_fpfh);
    pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs_src(new pcl::PointCloud<pcl::FPFHSignature33>());
    fpfh_src.setRadiusSearch(0.05);
    fpfh_src.compute(*fpfhs_src);
    std::cout << "compute *source fpfh" << endl;

    pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh_tgt;
    fpfh_tgt.setInputCloud(target);
    fpfh_tgt.setInputNormals(target_normals);
    pcl::search::KdTree<PointT>::Ptr tree_tgt_fpfh(new pcl::search::KdTree<PointT>);
    fpfh_tgt.setSearchMethod(tree_tgt_fpfh);
    pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs_tgt(new pcl::PointCloud<pcl::FPFHSignature33>());
    fpfh_tgt.setRadiusSearch(0.05);
    fpfh_tgt.compute(*fpfhs_tgt);
    std::cout << "compute *target fpfh" << endl;

    //---------------------------SAC配准-----------------------------
    pcl::SampleConsensusInitialAlignment<pcl::PointXYZ, pcl::PointXYZ, pcl::FPFHSignature33> scia;
    scia.setInputSource(source);
    scia.setInputTarget(target);
    scia.setSourceFeatures(fpfhs_src);
    scia.setTargetFeatures(fpfhs_tgt);
    PointCloud::Ptr sac_result(new PointCloud);
    scia.align(*sac_result);
    std::cout << "sac has converged:" << scia.hasConverged() << "  score: " << scia.getFitnessScore() << endl;
    Eigen::Matrix4f sac_trans;
    sac_trans = scia.getFinalTransformation();
    std::cout << sac_trans << endl;
    clock_t sac_time = clock();

    //--------------------------ICP配准----------------------------
    PointCloud::Ptr icp_result(new PointCloud);
    pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
    icp.setInputSource(source);
    icp.setInputTarget(target);
    icp.setMaxCorrespondenceDistance(100);
    icp.setMaximumIterations(100);
    icp.setTransformationEpsilon(1e-10);
    icp.setEuclideanFitnessEpsilon(0.001);
    icp.align(*icp_result, sac_trans);

    clock_t end = clock();
    cout << "total time: " << (double)(end - start) / (double)CLOCKS_PER_SEC << " s" << endl;
    cout << "sac time: " << (double)(sac_time - start) / (double)CLOCKS_PER_SEC << " s" << endl;
    cout << "icp time: " << (double)(end - sac_time) / (double)CLOCKS_PER_SEC << " s" << endl;

    std::cout << "ICP has converged:" << icp.hasConverged()
        << " score: " << icp.getFitnessScore() << std::endl;
    Eigen::Matrix4f icp_trans;
    icp_trans = icp.getFinalTransformation();
    std::cout << icp_trans << endl;
    pcl::transformPointCloud(*cloud_src_o, *icp_result, icp_trans);
    pcl::io::savePLYFileASCII("sac-ia_icp.ply", *icp_result);
    //--------------------可视化------------------------
    	boost::shared_ptr<pcl::visualization::PCLVisualizer>
		viewer_final(new pcl::visualization::PCLVisualizer("配准结果"));
	viewer_final->setBackgroundColor(0, 0, 0);  
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		target_color(target, 255, 0, 0);
	viewer_final->addPointCloud<pcl::PointXYZ>(target, target_color, "target cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "target cloud");
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
		output_color(icp_result, 0, 0, 255);
	viewer_final->addPointCloud<pcl::PointXYZ>(icp_result, output_color, "output cloud");
	viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
		1, "output cloud");
	while (!viewer_final->wasStopped())
	{
		viewer_final->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

    return (0);
}

4.实验结果

标签:src,include,tgt,SAC,fpfh,PointCloud,pcl,IA,ICP
From: https://blog.csdn.net/m0_71596228/article/details/137171129

相关文章

  • RANSAC(提取FPFH特征)+ICP配准
            RANSAC(RandomSampleConsensus)和ICP(IterativeClosestPoint)是点云配准中常用的两个算法,可以使用RANSAC进行粗配准结合ICP进行精配准。1.FPFH特征FPFH特征:定义:FPFH是一种点云特征描述子,用于表示点云中每个点的局部特征。计算过程:对于每个点,计算其法......
  • ICPC2023 陕西邀请赛 题解
    G-PermutationQuestion找到一个排列\(p\),使得\(\prod_{i=1}^nlcm(p_i,p_{(imodn)+1})\)最大Solution考虑到\(x\)和\(x-1\)必然是互质的所以顺序排列即可Code#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;cin>>n;for(inti......
  • NVIDIA公司在实体机器人上的第一步尝试 —— Nova Cater AMR —— 九号机器人与英伟达
    相关:https://www.leiphone.com/category/robot/Hgy9i8azqGncESIB.htmlNovaCaterAMR是一款仓储运货机器人,可以应用在仓储物流上,也可以应用在酒店运送菜品上;该机器人使用和NVIDIA公司联合开发的自动驾驶系统,这也是NVIDIA公司在实体机器人上的首次尝试。九号公司是一家中国公......
  • debian12 linux root能用lightdm登陆xfce桌面,普通用户不能用lightdm登陆xfce桌面,闪
    Fn+Ctrl+F3,进入tty,发现登陆普通用户后再使用startxfce4可以直接进桌面下面参照https://forums.opensuse.org/t/normal-user-can-not-login/50756http://linux.it.net.cn/m/view.php?aid=6499有多种办法原因可能是用在自己账户下命令行sudostartx导致~/.Xauthority文件......
  • NVIDIA一直宣传的DPU是个啥东西,啥用处? —— NVIDIA BlueField-3 DPU
    地址:https://www.bilibili.com/video/BV1ys4y1z7nS/?spm_id_from=333.788.recommend_more_video.3&vd_source=f1d0f27367a99104c397918f0cf362b7无意间看到了一个比较靠谱的解释:(来自地址:https://www.bilibili.com/video/BV1ys4y1z7nS/)......
  • uniapp弹窗方式
    文字弹窗uni.showToast({ title:'文字弹窗', icon:'none', duration:2000 })图标文字弹框uni.showToast({ title:'成功提示弹窗', icon:'success', duration:2000 })取消确认弹框uni.showModal......
  • P1821 [USACO07FEB] Cow Party S
    [P1821USACO07FEB]CowPartyS-洛谷|计算机科学教育新生态(luogu.com.cn)每次都求一遍从uuu到r......
  • 大海捞针 Skia(C++) 第 4.1 期(特别篇):将绘制结果输出到窗口
    前言由于本人(我)没有系统学习过图形学,无法提供准确的术语表达,如果哪位大佬看到我的一些错误,还请友善指出!第四期之后,我一直纠结于应该讲些什么。图形学的东西我真的学的不多,未来也不是很想走这个方向。但是我仍然希望通过我的一些绵薄之力为一些苦苦寻找关于Skia资料的兄弟们提供......
  • @PathVariable注解
      @PathVariable 是SpringMVC中的一个注解,用于将URL中的模板变量绑定到方法的参数上。在SpringMVC中,通常会使用RESTful风格的URL来处理请求,URL中可能包含一些占位符,例如/users/{id},其中{id}就是一个占位符,用来表示一个参数,如进行逻辑删时,在请求头直接添加......
  • Debian 12 配置其国内软件源-实测有用
    这个链接配置适合Debian11https://www.shanhubei.com/archives/2627.html Debian12请使用:debhttps://mirrors.tuna.tsinghua.edu.cn/debian/bookwormmaincontribnon-freenon-free-firmwaredeb-srchttps://mirrors.tuna.tsinghua.edu.cn/debian/bookwormmaincon......