Advertisement

PCL区域生长分割

阅读量:

文章目录

        • 一、算法原理
      • 1、输入
      • 2、初始化
      • 3、算法
    • 二、代码部分

    • 三、代码解释

    • 参考文献

本次我们将深入研究 pcl::RegionGrowing 类内所包含的区域生长算法。
该算法的主要目标是将那些在平滑度方面足够接近的点合并,并有助于提高后续处理的效果。
The algorithm’s output is a collection of clusters, where each cluster represents a group of points that collectively represent a smooth surface.
The algorithm’s foundation lies in the calculation of angles between normals.

在这里插入图片描述
一、算法原理

我们来了解该算法的工作原理:首先介绍核心步骤及其逻辑关系。第一步是按照曲率值将点进行排序:随后按照特定规则逐步构建区域形状。这种做法的原因在于区域从曲率最小的点开始扩张:其中最为理想的情况是从较为平坦的区域开始增长能够有效地减少所需的线段数量。

我们获得了排序后的云数据集;具体来说,这个过程包括以下步骤:当所有点都被标记完毕时,算法首先识别曲率值最小的未标记点,随后启动区域扩展的过程,直到所有相邻区域都被覆盖为止

  • 将选定的点加入到种子集合中
    • 在算法运行过程中, 每一个选定的种子点都会被识别出其对应的邻居数据
      • 在计算每个邻居区域的方向时, 系统会比较该区域方向与当前参考数据方向之间的夹角
        • 如果计算得到的角度值低于设定阈值, 则标记该数据为可扩展候选
      • 接着, 在评估各个邻居区域的几何特性时, 系统会对每个区域的平均曲率进行计算
        • 如果某个区域的平均曲率低于预设的标准, 则该数据会被纳入候选种群
    • 最后, 在完成上述所有计算后, 系统会自动提取出当前最符合条件的数据样本作为新的迭代起点
在这里插入图片描述

若种子集为空,则表示算法已对该区域进行了扩展,并将从头开始重新执行该过程。您可在下方找到此算法的伪代码描述。

1、输入
在这里插入图片描述
2、初始化
在这里插入图片描述
3、算法
在这里插入图片描述
二、代码部分

请按照以下步骤,在选择一个您熟悉的专业开发环境(IDE)中生成一个名为region_grinding_segmentation.cpp的源代码文件,并将以下代码片段粘贴到该文件中:

复制代码
    #include <iostream>
    #include <vector>
    #include <pcl/point_types.h>
    #include <pcl/io/pcd_io.h>
    #include <pcl/search/search.h>
    #include <pcl/search/kdtree.h>
    #include <pcl/features/normal_3d.h>
    #include <pcl/visualization/cloud_viewer.h>
    #include <pcl/filters/filter_indices.h> // for pcl::removeNaNFromPointCloud
    #include <pcl/segmentation/region_growing.h>
    
    int
    main ()
    {
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
      if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("region_growing_tutorial.pcd", *cloud) == -1)
      {
    std::cout << "Cloud reading failed." << std::endl;
    return (-1);
      }
    
      pcl::search::Search<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
      pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
      pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
      normal_estimator.setSearchMethod (tree);
      normal_estimator.setInputCloud (cloud);
      normal_estimator.setKSearch (50);
      normal_estimator.compute (*normals);
    
      pcl::IndicesPtr indices (new std::vector <int>);
      pcl::removeNaNFromPointCloud(*cloud, *indices);
    
      pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
      reg.setMinClusterSize (50);
      reg.setMaxClusterSize (1000000);
      reg.setSearchMethod (tree);
      reg.setNumberOfNeighbours (30);
      reg.setInputCloud (cloud);
      reg.setIndices (indices);
      reg.setInputNormals (normals);
      reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
      reg.setCurvatureThreshold (1.0);
    
      std::vector <pcl::PointIndices> clusters;
      reg.extract (clusters);
    
      std::cout << "Number of clusters is equal to " << clusters.size () << std::endl;
      std::cout << "First cluster has " << clusters[0].indices.size () << " points." << std::endl;
      std::cout << "These are the indices of the points of the initial" <<
    std::endl << "cloud that belong to the first cluster:" << std::endl;
      std::size_t counter = 0;
      while (counter < clusters[0].indices.size ())
      {
    std::cout << clusters[0].indices[counter] << ", ";
    counter++;
    if (counter % 10 == 0)
      std::cout << std::endl;
      }
      std::cout << std::endl;
    
      pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
      pcl::visualization::CloudViewer viewer ("Cluster viewer");
      viewer.showCloud(colored_cloud);
      while (!viewer.wasStopped ())
      {
      }
    
      return (0);
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
三、代码解释

整体调用关系如下:

在这里插入图片描述

该算法在内部结构中涉及K最近邻搜索这一技术,在此处主要负责提供搜索方法并设置邻域数量。随后,它依次接收被分割的点云、点索引和法线信息。

复制代码
    pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
    reg.setMinClusterSize (50);
    reg.setMaxClusterSize (1000000);
    reg.setSearchMethod (tree);
    reg.setNumberOfNeighbours (30);
    reg.setInputCloud (cloud);
    //reg.setIndices (indices);
    reg.setInputNormals (normals);
    
    
      
      
      
      
      
      
      
      
    
    代码解读

这两行属于算法初始化的关键环节,在处理几何约束方面起着重要作用

复制代码
    reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
    reg.setCurvatureThreshold (1.0);
    
    
      
      
    
    代码解读
参考文献

1

1

2

2

全部评论 (0)

还没有任何评论哟~