• Ubuntu 20.04.06 PCL C++学习记录(二十六)


    @[TOC]PCL中点云配准模块的学习

    学习背景

    参考书籍:《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,,PCL版本为1.10.0,CMake版本为3.16,可用点云下载地址

    学习内容

    在代码中使用ICP迭代最近点算法,程序随机生成一个点与作为源点云,并将其沿x轴平移后作为目标点云,然后利用ICP估计源到目标的刚体变换橘子,中间对所有信息都打印出来。在 ICP 配准过程中,算法会迭代地寻找源点云和目标点云之间的最佳变换矩阵,使得两个点云之间的距离最小化。

    源代码及所用函数

    源代码

    //迭代最近点算法
    #include//标准输入输出头文件
    #include//PCD输入输出头文件
    #include//点类型定义头文件
    #include//ICP(迭代最近点)配准算法头文件。
    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>);
        //*******************填充点云第一种写法**************************//
        // // 随机填充点云
        // cloud_in->width    = 5;               //设置点云宽度
        // cloud_in->height   = 1;               //设置点云为无序点
        // cloud_in->is_dense = false;
        // cloud_in->points.resize (cloud_in->width * cloud_in->height);
        // for (size_t i = 0; i < cloud_in->points.size(); i++)
        // {
        //     cloud_in->points[i].x = 1024.0f*rand()/(RAND_MAX +1.0f);
        //     cloud_in->points[i].y = 1024.0f*rand()/(RAND_MAX +1.0f);
        //     cloud_in->points[i].z = 1024.0f*rand()/(RAND_MAX +1.0f);
        // }
        //*********************填充点云第二种方法**********************//
        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->points.size () << "个点,其坐标为:" << std::endl;
        //*******************打印点云第一种方法************************//
        // for (size_t i = 0; i < cloud_in->points.size (); ++i)
        // {
        //     std::cout << "    " << cloud_in->points[i].x << " " << cloud_in->points[i].y << " " << cloud_in->points[i].z << std::endl;
        // }
        //******************打印点云的第二种方法***********************//
        for (auto& point : *cloud_in)
        {
            std::cout << point << std::endl;    
        }
        
        //****************************************实现一个简单的点云刚体变换,以构造目标点云******************************//
        *cloud_out = *cloud_in; 
        std::cout << "点云大小:" << cloud_out->size() << std::endl;
        for (auto& point : *cloud_out)
        {
            point.x += 0.7f;
        }
        std::cout << "转移了 " << cloud_in->size () << "个点" << std::endl;
        for(auto& point : *cloud_out)
        {
            std::cout << point << std::endl;
        }
        pcl::IterativeClosestPoint<pcl::PointXYZ,pcl::PointXYZ> icp;//创建IterativeClosestPoint的对象
        icp.setInputSource(cloud_in); //cloud_in设置为点云的源点
        icp.setInputTarget(cloud_out);//cloud_out设置为与cloud_in对应的匹配目标
        pcl::PointCloud<pcl::PointXYZ> Final;//存储经过配准变换点云后的点云
        icp.align(Final);//打印配准相关输入信息
        std::cout << "已收敛" << icp.hasConverged() << "总共" << icp.getFitnessScore() << std::endl;
        std::cout << icp.getFinalTransformation() << std::endl;
    
        return 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.16 FATAL_ERROR)#指定CMake的最低版本要求为3.16
    project(project)#设置项目名称
    find_package(PCL 1.10 REQUIRED)#查找PCL库,要求版本为1.10或更高。
    include_directories(${PCL_INCLUDE_DIRS})#将PCL库的头文件目录添加到包含路径中
    link_directories(${PCL_LIBRARY_DIRS})#将PCL库的库文件目录添加到链接器搜索路径中。
    add_definitions(${PCL_DEFINITIONS})#添加PCL库的编译器定义
    add_executable (iterative_closest_point iterative_closest_point.cpp)
    target_link_libraries (iterative_closest_point ${PCL_LIBRARIES})#将PCL库链接到可执行文件目标。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果

    在这里插入图片描述红色是随机生成点云,绿色是ICP配准后的点云
    在这里插入图片描述

    函数

    • icp.hasConverged() 是 PCL 库中 IterativeClosestPoint 类的一个成员函数,用于检查 ICP 配准算法是否收敛。hasConverged() 函数返回一个布尔值,表示 ICP 算法是否达到了收敛条件。当 ICP 算法满足收敛条件时,hasConverged() 函数将返回 true,表示配准过程已经完成,得到了最佳的变换矩阵。

    • icp.getFitnessScore()是ICP(迭代最近点)算法中的一个函数,用于计算当前变换矩阵的适应度得分(Fitness Score)用来评估当前变换矩阵的性能。具体来说,getFitnessScore()通常会计算以下指标:
      对应点之间的欧氏距离之和或均值。距离越小,说明对齐效果越好。
      内点(Inlier)的数量或比例。内点指的是在一定误差范围内匹配的点对。内点越多,说明对齐效果越好。
      误差的标准差。误差越集中,说明对齐更加一致。

      关于返回值的大小通常有两种常见的情况:
      得分越小越好:如果getFitnessScore()返回的是误差或距离的度量,如对应点之间的欧氏距离之和或均值,则得分越小表示对齐效果越好。在这种情况下,ICP算法的目标是最小化getFitnessScore()的返回值。
      得分越大越好:如果getFitnessScore()返回的是内点的数量、比例或其他表示对齐质量的指标,则得分越大表示对齐效果越好。在这种情况下,ICP算法的目标是最大化getFitnessScore()的返回值。
      在大多数实现中,这个分数通常是平均平方误差,所以较低的分数意味着两个点云之间的对应点的距离较近,表明配准的质量较高。

    补充内容

  • 相关阅读:
    C++错题本
    【附源码】计算机毕业设计SSM数据结构知识点渐进学习网站
    python+appium+pytest自动化测试-参数化设置
    网络安全(黑客)自学
    python疫苗预约系统毕业设计开题报告
    【无标题】
    Java工具类:HttpUtil项目实战
    中文分词的词典中的词性标记
    【一起读源码】1. Java 中元组 Tuple
    DNS解析为什么不生效?DNS解析不生效原因分析
  • 原文地址:https://blog.csdn.net/weixin_44178555/article/details/137923309