1、区域生长分割算法:

区域生长分割算法的输出是一个聚类集合,每个聚类集合被认为是同一光滑表面的一部分。该算法思想:首先依据点的曲率值对点进行排序,之所以排序,是因为区域生长算法是从曲率最小的点开始生长的,这个点就是初始种子点,初始种子点所在的区域即为最平滑的区域,一般场景中平面区域较大,这样从最平滑的区域开始生长可减少分割区域的总数,提高效率。

    算法的流程:设置一空的种子点序列和空的聚类数组,选好初始种子点后,将其加入到种子点序列中,并搜索邻域点。对每一个邻域点,比较邻域点的法线与当前种子点的法线之间的夹角,小于平滑阈值的邻域点加入到当前区域。然后检查每一个邻域点的曲率值,小于曲率阈值的邻域点加入到种子点序列中。在进行种子点邻域判断后,删除当前种子点,利用新加入的种子点继续生长,重复进行以上生长过程,直到种子点序列被清空。一个区域生长完成,将其加入聚类数组。最后,利用曲率值从小到大排序,顺序选择输入点集的点作为种子点加入到种子点序列中,重复以上生长步骤,这样就通过区域生长实现了点云的分割。
 

2、代码:

using PclSharp;
 using PclSharp.Common;
 using PclSharp.Features;
 using PclSharp.Filters;
 using PclSharp.IO;
 using PclSharp.SampleConsensus;
 using PclSharp.Search;
 using PclSharp.Segmentation;
 using PclSharp.Std;
 using PclSharp.Struct;
 using System;
 using System.Numerics;namespace PclSharpTest
 {
     class Program
     {
         static void Main(string[] args)
         {
             Console.WriteLine($"C#--PclSharp算法库测试:");            bool Bool_cutting = false;

            //1、读取点云数据
           

var src_cloud = new PointCloudOfXYZ();
             using (var reader = new PCDReader())
                 reader.Read(AppDomain.CurrentDomain.BaseDirectory + $"//pcd//cow.pcd", src_cloud);
             //Console.WriteLine($"src_cloud has {src_cloud.Count} data points");

            //2、点云进行法线估计
           

var normals = new PointCloudOfNormal();//法线点云
             var tree = new KdTreeOfXYZ();
             using (var ne = new NormalEstimationOfPointXYZAndNormal())//法线估计对象
             {
                 
                 ne.SetSearchMethod(tree);//设置搜索方式
                 ne.SetInputCloud(src_cloud);//设置输入点云
                 ne.KSearch = 50; //设置k近邻点的个数
                 ne.Compute(normals);//执行法线估计
             }

            //3、直通滤波
       

var indices = new VectorOfInt();//声明一个索引
             if (Bool_cutting)
             {
                 using (var pass = new PclSharp.Filters.PassThroughOfXYZ())
                 {
                     pass.SetInputCloud(src_cloud);
                     pass.SetIndices(indices);
                     pass.FilterFieldName = "z";//指定进行过滤的字段
                     pass.FilterLimits = (0, 10f);//设置在过滤字段上的范围
                     pass.filter(indices);
                 }            }

            //4、区域生长的分割
     

var reg = new RegionGrowingOfPointXYZAndNormal();//创建区域生长的分割对象 
             reg.MinClusterSize = 50;//设置聚类所需要的最小点数
             reg.MaxClusterSize = 1000000;//设置一个聚类的最大点数
             reg.SetSearchMethod(tree);//设置搜索方式
             reg.NumberOfNeighbours = 30;//设置近邻点的个数
             reg.SetInputCloud(src_cloud);//设置输入点云
             if (Bool_cutting) reg.SetIndices(indices);//通过输入参数设置,确定是否输入点云的索引
             reg.SetInputNormals(normals);//输入点云的法向量
             reg.SmoothnessThreshold = (float)(30.0/ 180.0 * Math.PI);//设置平滑阈值
             reg.CurvatureThreshold = 0.05f;//设置曲率阈值            var clusters = new VectorOfPointIndices();//用动态数组保存聚类的结果
             reg.Extract(clusters);
             PointCloudOfXYZRGB colored_cloud = reg.ColoredCloud;            using (var viewer = new PclSharp.Vis.CloudViewer(" cloudviewer window"))
             {
                 viewer.ShowCloud(colored_cloud);
                 while (!viewer.WasStopped);            }
            Console.ReadKey();
         }    }
 }

3、编译结果

分割后的图像存在部分红色点,说明这部分点的数量小于或大于用户设定的阈值。基于区域生长的分割算法,通过修改相关输入参数,可以获得更好的分割效果:

区域生长算法分割图像python代码 基于区域生长的分割_区域生长