• 【PCL自学:Segmentation4】基于Min-Cut点云分割


    一、基于Min-Cut的点云分割

      在本节中,我们将学习如何使用在pcl::MinCutSegmentation类中实现的基于min-cut的分割算法。该算法对给定的输入点云进行二值分割。根据对象的中心及其半径,算法将云分为两组:前景点和背景点(属于对象的点和不属于对象的点)。

    二、Min-Cut原理剖析

      该算法的思想需要图论知识,如下:
      1. 对于给定的点云算法,它构造了一个图,其中包含云中的每一个点作为一组顶点,以及另外两个称为源和汇聚的顶点。图中每个与该点对应的顶点都与源连接,与边连接汇聚。除此之外,每个顶点(源和汇除外)都有连接对应点与其最近邻居的边。
      2. 算法为每条边分配权重。有三种不同类型的权重。让我们来研究一下
    ① 首先,它给点云之间的边赋予权重。这个权重被称为平滑成本,由公式计算

               s m o o t h C o s t = e − ( d i s t σ ) 2 smoothCost=e^{-(\frac{dist}{ \sigma })^2} smoothCost=e(σdist)2

      这里的dist是点与点之间的距离。距离越远的点,边缘被切割的概率越大。

    ②下一步,算法设置数据开销。它由前景惩罚和背景惩罚组成。第一个是那些连接点云和源顶点的边的权值,这些边具有用户定义的常量值。第二个分配给连接点与汇聚顶点的边,并由公式计算

             b a c k g r o u n d P e n a l t y = ( d i s t a n c e T o C e n t e r r a d i u s ) backgroundPenalty=(\frac{distanceToCenter}{radius}) backgroundPenalty=(radiusdistanceToCenter)

      这里的distanceToCenter是物体在水平面上与期望中心的距离

           d i s t a n c e T o C e n t e r = ( x − c e n t e r X ) 2 + ( y − c e n t e r Y ) 2 distanceToCenter=\sqrt{(x-centerX)^2+(y-centerY)^2} distanceToCenter=(xcenterX)2+(ycenterY)2
      公式中出现的半径是算法的输入参数,大致可以认为是物体中心以外没有属于前景的点的范围(物体的水平半径)。
      3. 在所有的准备工作完成后,寻找最小切口。在此基础上,对云进行前景点和背景点的划分。
    具体原理可以参考这篇论文来理解。 “Min-Cut Based Segmentation of Point Clouds”.

    需要说明的是:这个方法其实效果并没有论文中描述的好,而且参数比较过。适合学习思想,并不适合直接使用。

    三、示例代码

    #include <iostream>
    #include <vector>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    #include <pcl/visualization/cloud_viewer.h>
    #include <pcl/filters/filter_indices.h> // for pcl::removeNaNFromPointCloud
    #include <pcl/segmentation/min_cut_segmentation.h>
    
    int main ()
    {
    // 加载pcd文件中的点云
      pcl::PointCloud <pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZ>);
      if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("min_cut_segmentation_tutorial.pcd", *cloud) == -1 )
      {
        std::cout << "Cloud reading failed." << std::endl;
        return (-1);
      }
    // 选择有效的点进行分割
      pcl::IndicesPtr indices (new std::vector <int>);
      pcl::removeNaNFromPointCloud(*cloud, *indices);
    // pcl::MinCutSegmentation模板类只有一个参数PointT,该参数表示将使用哪种类型的点。
      pcl::MinCutSegmentation<pcl::PointXYZ> seg;
      seg.setInputCloud (cloud);
      seg.setIndices (indices);
    // 为算法提供点云中必须分割d的点和索引
      pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new pcl::PointCloud<pcl::PointXYZ> ());
      pcl::PointXYZ point;
      point.x = 68.97;
      point.y = -18.55;
      point.z = 0.57;
      foreground_points->points.push_back(point);
      seg.setForegroundPoints (foreground_points);
    // 如前所述,算法要求已知为物体中心的点。
      seg.setSigma (0.25);
      seg.setRadius (3.0433856);
      seg.setNumberOfNeighbours (14);
      seg.setSourceWeight (0.8);
    
    // 将分割后的点分类
      std::vector <pcl::PointIndices> clusters;
      seg.extract (clusters);
    
      std::cout << "Maximum flow is " << seg.getMaxFlow () << std::endl;
    
    // 显示点云
      pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = seg.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

    分割效果如下:
    在这里插入图片描述
    前辈的这篇文章对该算法做了尝试,结果显示该算法效果并不好。


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

  • 相关阅读:
    JAVASE语法零基础——static成员和代码块
    YUM源的几种常见方式
    [ C++ ] 继承
    Python21天学习挑战赛Day(15-16)·lxml库与Xpath提取网页数据
    C++数据结构X篇_15_求二叉树叶子数与高度(递归方法)
    OPUS 中DTX的作用
    Redis快速入门----------客户端使用
    Re14:读论文 ILLSI Interpretable Low-Resource Legal Decision Making
    【Linux基础】Linux的基本指令使用(超详细解析,小白必看系列)
    年底无情被裁,我面试大厂的这几个月…
  • 原文地址:https://blog.csdn.net/weixin_41966507/article/details/125423669