PclSharp--基于区域生长的分割

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、编译结果

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

PclSharp--基于区域生长的分割_第1张图片

你可能感兴趣的:(PCL,c#,算法)