• pcl--基于区域增长的点云分割


    在本教程中,我们将学习如何使用pcl::RegionGrowing 类实现的区域增长算法。算法的目的是合并在平滑度足够接近的点。因此,该算法的输出是一组簇,其中每个簇是一组点,这些点被认为是同一光滑表面的一部分。该算法的工作是基于点法线之间角度的比较。

    理论:

    首先,它按曲率值对点进行排序。之所以需要这样做,是因为该区域从具有最小曲率值的点开始增长。这样做的原因是,具有最小曲率的点位于平坦的区域(从最平坦的区域开始增长可以减少区段的总数)。

    所以我们得到了排序后的云。直到点云中没有未标记的点为止,该算法提取曲率值最小的点并开始区域增长。此过程如下所示:

    拾取的点将添加到称为“种子”的集中

    对于每个种子点,该算法都会找到其相邻点。

    测试每个相邻点的法线与当前种子点法线之间的角度。如果角度小于阈值,则将当前点添加到当前区域。

    之后,对每个相邻点进行曲率值测试。如果曲率小于阈值,则该点将添加到种子。

    当前种子将从种子集中移除。

    如果种子集变为空,这意味着算法已经扩大了区域,并且从一开始就重复该过程。

    源码:

    创建 region_growing_segmentation.cpp 文件

    1. 1#include <iostream>
    2. 2#include <vector>
    3. 3#include <pcl/point_types.h>
    4. 4#include <pcl/io/pcd_io.h>
    5. 5#include <pcl/search/search.h>
    6. 6#include <pcl/search/kdtree.h>
    7. 7#include <pcl/features/normal_3d.h>
    8. 8#include <pcl/visualization/cloud_viewer.h>
    9. 9#include <pcl/filters/filter_indices.h> // for pcl::removeNaNFromPointCloud
    10. 10#include <pcl/segmentation/region_growing.h>
    11. 11
    12. 12int
    13. 13main ()
    14. 14{
    15. 15 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    16. 16 if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("region_growing_tutorial.pcd", *cloud) == -1)
    17. 17 {
    18. 18 std::cout << "Cloud reading failed." << std::endl;
    19. 19 return (-1);
    20. 20 }
    21. 21
    22. 22 pcl::search::Search<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
    23. 23 pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
    24. 24 pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
    25. 25 normal_estimator.setSearchMethod (tree);
    26. 26 normal_estimator.setInputCloud (cloud);
    27. 27 normal_estimator.setKSearch (50);
    28. 28 normal_estimator.compute (*normals);
    29. 29
    30. 30 pcl::IndicesPtr indices (new std::vector <int>);
    31. 31 pcl::removeNaNFromPointCloud(*cloud, *indices);
    32. 32
    33. 33 pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
    34. 34 reg.setMinClusterSize (50);
    35. 35 reg.setMaxClusterSize (1000000);
    36. 36 reg.setSearchMethod (tree);
    37. 37 reg.setNumberOfNeighbours (30);
    38. 38 reg.setInputCloud (cloud);
    39. 39 reg.setIndices (indices);
    40. 40 reg.setInputNormals (normals);
    41. 41 reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
    42. 42 reg.setCurvatureThreshold (1.0);
    43. 43
    44. 44 std::vector <pcl::PointIndices> clusters;
    45. 45 reg.extract (clusters);
    46. 46
    47. 47 std::cout << "Number of clusters is equal to " << clusters.size () << std::endl;
    48. 48 std::cout << "First cluster has " << clusters[0].indices.size () << " points." << std::endl;
    49. 49 std::cout << "These are the indices of the points of the initial" <<
    50. 50 std::endl << "cloud that belong to the first cluster:" << std::endl;
    51. 51 std::size_t counter = 0;
    52. 52 while (counter < clusters[0].indices.size ())
    53. 53 {
    54. 54 std::cout << clusters[0].indices[counter] << ", ";
    55. 55 counter++;
    56. 56 if (counter % 10 == 0)
    57. 57 std::cout << std::endl;
    58. 58 }
    59. 59 std::cout << std::endl;
    60. 60
    61. 61 pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
    62. 62 pcl::visualization::CloudViewer viewer ("Cluster viewer");
    63. 63 viewer.showCloud(colored_cloud);
    64. 64 while (!viewer.wasStopped ())
    65. 65 {
    66. 66 }
    67. 67
    68. 68 return (0);
    69. 69}

    说明:

    1、相关的头文件

    1. 1#include <iostream>
    2. 2#include <vector>
    3. 3#include <pcl/point_types.h>
    4. 4#include <pcl/io/pcd_io.h>
    5. 5#include <pcl/search/search.h>
    6. 6#include <pcl/search/kdtree.h>
    7. 7#include <pcl/features/normal_3d.h>
    8. 8#include <pcl/visualization/cloud_viewer.h>
    9. 9#include <pcl/filters/filter_indices.h> // for pcl::removeNaNFromPointCloud
    10. 10#include <pcl/segmentation/region_growing.h>
    11. 11

    2、加载点云pcd文件

    1. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    2. if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("region_growing_tutorial.pcd", *cloud) == -1)
    3. {
    4. std::cout << "Cloud reading failed." << std::endl;
    5. return (-1);
    6. }

    3、计算点的法线

    1. pcl::search::Search<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
    2. pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
    3. pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
    4. normal_estimator.setSearchMethod (tree);
    5. normal_estimator.setInputCloud (cloud);
    6. normal_estimator.setKSearch (50);
    7. normal_estimator.compute (*normals);

    4、去除一些无效点

    1. pcl::IndicesPtr indices (new std::vector <int>);
    2. pcl::removeNaNFromPointCloud(*cloud, *indices);

    5、实例化pcl::RegionGrowing。它是一个模板类,有两个参数:

    PointT—要使用的点的类型(在给定的示例中为pcl::PointXYZ)

    NormalT—要使用的法线类型(在给定的示例中为pcl::Normal)

    然后设置最小和最大集群大小。这意味着分割完成后,所有点小于最小值(或大于最大值)的簇都将被丢弃。最小值和最大值的默认值分别为1和“尽可能多”。

    1. pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
    2. reg.setMinClusterSize (50);//最小集群大小
    3. reg.setMaxClusterSize (1000000);//最大集群大小
    4. reg.setSearchMethod (tree);//使用kdtree最近邻搜索
    5. reg.setNumberOfNeighbours (30);//设置邻居的数量
    6. reg.setInputCloud (cloud);//传入点云
    7. reg.setIndices (indices);//传入点索引
    8. reg.setInputNormals (normals);//传入法线
    9. reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);//平滑度阈值
    10. reg.setCurvatureThreshold (1.0);//曲率阈值
    11. std::vector <pcl::PointIndices> clusters;
    12. reg.extract (clusters);

    6、输出一些信息

    1. std::cout << "Number of clusters is equal to " << clusters.size () << std::endl;
    2. std::cout << "First cluster has " << clusters[0].indices.size () << " points." << std::endl;
    3. std::cout << "These are the indices of the points of the initial" <<
    4. std::endl << "cloud that belong to the first cluster:" << std::endl;
    5. std::size_t counter = 0;
    6. while (counter < clusters[0].indices.size ())
    7. {
    8. std::cout << clusters[0].indices[counter] << ", ";
    9. counter++;
    10. if (counter % 10 == 0)
    11. std::cout << std::endl;
    12. }
    13. std::cout << std::endl;

    7、RegionGrowing类提供了一个方法,该方法返回彩色云,其中每个集群都有自己的颜色。因此,在这部分代码中,pcl::visualization::CloudViewer被实例化,用于查看分割结果-相同颜色的云。

    1. pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
    2. pcl::visualization::CloudViewer viewer ("Cluster viewer");
    3. viewer.showCloud(colored_cloud);
    4. while (!viewer.wasStopped ())
    5. {
    6. }
    7. return (0);
    8. }

    编译和运行

    1、将以下行添加到CmakeList.txt文件:

    1. 1cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
    2. 2
    3. 3project(region_growing_segmentation)
    4. 4
    5. 5find_package(PCL 1.5 REQUIRED)
    6. 6
    7. 7include_directories(${PCL_INCLUDE_DIRS})
    8. 8link_directories(${PCL_LIBRARY_DIRS})
    9. 9add_definitions(${PCL_DEFINITIONS})
    10. 10
    11. 11add_executable (region_growing_segmentation region_growing_segmentation.cpp)
    12. 12target_link_libraries (region_growing_segmentation ${PCL_LIBRARIES})

    2、运行

    $ ./region_growing_segmentation

    3、输出

     

  • 相关阅读:
    PyTorch之MLP
    SpringBoot 整合 websocket (二)—— 部署Nginx\Tomcat
    【深度学习】实验6答案:图像自然语言描述生成(让计算机“看图说话”)
    “把握拐点,洞悉投资者情绪与比特币价格的未来之路!“
    【JavaScript】参考手册-Array对象的3个属性和25个方法
    【运维自动化-配置平台】如何使用云资源同步功能(腾讯云为例)
    独立站怎样建站?平台怎么选?一文速览
    Uniapp导出的iOS应用上架详解
    【Mysql】增删改查(基础版)
    iHRM 人力资源管理系统_第9章_文件上传与PDF报表入门_第一节_文件上传
  • 原文地址:https://blog.csdn.net/m0_50046535/article/details/125509860