• 【PCL自学:Segmentation3】基于PCL的点云分割:区域增长分割


    一、什么是区域增长分割

      在本文中,我们将学习如何使用pcl:: regiongrow类中实现的区域增长算法。所述算法的目的是将在平滑性约束方面足够接近的点分类。因此,该算法的输出是聚类的集合,其中每个聚类都是一组点,被认为是同一光滑曲面的一部分。该算法的工作是基于点法线之间角度的比较。

    二、区域增长分割原理剖析

      让我们来看看该算法是如何工作的。
      1.首先,它根据它们的曲率值对点进行分类。之所以要这样做是因为这个区域从曲率最小的点开始增长。这是因为曲率最小的点位于平坦的区域(从最平坦的区域增长可以减少分割总数)。
      2.选中的点被添加到名为seeds(增长种子集合)的集合中。
      3.对于每个种子点,算法找到它的邻近点。
        a.每个邻居都被计算它的法线和当前种子点的法线之间的角度。如果角度小于阈值,则将当前点添加到当前种子所在区域。
        b.然后对每个邻域进行曲率值测试。如果曲率小于阈值,则将此点添加到种子集合中作为新种子。
        c.从种子集合中删除当前的种子。
      4.如果种子集变成空的,这意味着算法扩大了区域,这个过程从头开始重复迭代,直到种子集合为空。

    三、区域增长分割示例代码

    #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 ()
    {
    // 读取点云pcd文件
      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);
      }
    
    // 建立搜索KD树
      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); // 搜索方法为kd树走索
      normal_estimator.setInputCloud (cloud);  // 填入点云
      normal_estimator.setKSearch (50);		   // 设置搜索范围
      normal_estimator.compute (*normals);	   // 将法相保存在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);		// 设置kd树搜索方法
      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);
    }
    
    • 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
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    运行效果如下:
    在这里插入图片描述


    【博主简介】
      斯坦福的兔子,男,天津大学工学硕士。毕业至今从事光学三维成像及点云处理相关工作。因工作中使用的三维处理库为公司内部库,不具有普遍适用性,遂自学开源PCL库及其相关数学知识以备使用。谨此将自学过程与君共享。
    博主才疏学浅,尚不具有指导能力,如有问题还请各位在评论处留言供大家共同讨论。’

  • 相关阅读:
    Monaco Editor教程(十六):缩略图minimap的配置详解
    面向开发者的Android
    持续集成部署-k8s-配置与存储-配置管理:SubPath
    论文阅读《Direct Sparse Odometry》2
    【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-汇总 ( Chapter17-ChapterB )
    BOMBLAB
    使用windows自带的磁盘测速工具对硬盘进行测速——从此无需额外下载第三方硬盘测速工具
    旅游计划定制小程序网页模板源码
    Linux安装Mariadb数据库
    SSM整合分页插件
  • 原文地址:https://blog.csdn.net/weixin_41966507/article/details/125422539