• PclSharp--BoundaryEstimation(基于法线的边界提取)


    1、边界提取采用PCL库中的方法,基于法线估计来实现的边界检测与提取:由点云估计出法线,再由法线和点云数据估计出边界。

    有多个参数需要用户根据自己的数据进行调整,其中影响主要是估计法线的半径设置ne.RadiusSearch,设置为分辨率的10倍时,效果较好,主要是对于法线估计。邻域半径选择太小了,噪声较大,估计的法线就容易出错,而搜索邻域半径设置的太大估计速度就比较慢。boundEst.RadiusSearch ,也设置10倍,太小则内部的很多点就都当成边界点了。最后一个参数是边界判断时的角度阈值,默认值为PI/2,此处设置为PI/4,用户也可以根据需要进行更改。

    2、源码

    using PclSharp;
    using PclSharp.Features;
    using PclSharp.Helpers;
    using PclSharp.IO;
    using PclSharp.Search;
    using PclSharp.Struct;
    using PclSharp.Surface;
    using System;


    namespace PclSharpTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine($"C#--PclSharp算法库测试:");

                //读取点云数据
                var cloud = new PointCloudOfXYZ();
                using (var reader = new PCDReader())
                    reader.Read(AppDomain.CurrentDomain.BaseDirectory + $"//pcd//table_scene_lms400.pcd", cloud);
                //体素滤波
                using (var sor = new PclSharp.Filters.VoxelGridOfXYZ())
                {
                    sor.SetInputCloud(cloud);
                    sor.LeafSize = new PointXYZ { X = 0.01f, Y = 0.01f, Z = 0.01f };//体素点的大小
                    sor.filter(cloud);
                }
                //剔除离群点
                using (var sor = new PclSharp.Filters.StatisticalOutlierRemovalOfXYZ())
                {
                    sor.SetInputCloud(cloud);
                    sor.MeanK = 100; //设置在进行统计时考虑查询点临近点数
                    sor.StdDevMulThresh = 1.0; //设置判断是否为离群点的阀值
                    sor.filter(cloud);//输出滤波后点云
                }


                //保存边界估计结果
                var boundaries = new PointCloudOfBoundary();
                //定义一个进行边界特征估计的对象
                var boundEst = new BoundaryEstimationOfPointXYZAndNormal();
                // 计算法向量
                var normals = new PointCloudOfNormal();//法线点云
                using (var ne = new NormalEstimationOfPointXYZAndNormal())//法线估计对象
                using (var tree = new KdTreeOfXYZ()) //创建用于最近邻搜索的KD-Tree
                {
                    //法线估计
                    //ne.SetSearchMethod(tree);
                    ne.SetInputCloud(cloud);
                    ne.RadiusSearch = 0.1;//设置法线估计的半径,需要根据自己点云情况调整这个参数
                    ne.Compute(normals);//计算法线,结果存储在normals中
                }

                boundEst.SetInputCloud(cloud);//设置输入的点云
                boundEst.SetInputNormals(normals); //设置边界估计的法线,因为边界估计依赖于法线
                boundEst.RadiusSearch = 0.1; //设置边界估计所需要的半径
                boundEst.AngleThreshold = Math.PI / 4; //边界估计时的角度阈值
                boundEst.SetSearchMethod(new KdTreeOfXYZ()); //设置搜索方式KdTree
                boundEst.Compute(boundaries); //将边界估计结果保存在boundaries

                var cloud_boundary = new PointCloudOfXYZ();//边界点
                //存储估计为边界的点云数据,将边界结果保存为PointXYZ类型
                for (int i = 0; i < cloud.Count; i++)
                {
                    if (boundaries.Points[i].boundary_point > 0)
                    {
                        cloud_boundary.Add(cloud.Points[i]);
                    }
                }
                Console.WriteLine($"输出边界点的个数:{cloud_boundary.Points.Count}");

                using (var visualizer = new PclSharp.Vis.Visualizer("a window"))
                {
                    //创建两个观察视点
                    int v1 = 1;
                    int v2 = 2;
                    visualizer.CreateViewPort(0.0, 0.0, 0.5, 1.0, v1);
                    visualizer.CreateViewPort(0.5, 0.0, 1.0, 1.0, v2);

                    visualizer.SetBackgroundColor_ViewPort(0f, 0f, 0f, v1);
                    visualizer.SetBackgroundColor_ViewPort(0.05f, 0f, 0f, v2);

                    visualizer.AddPointCloud(cloud, "v1", v1);
                    visualizer.AddPointCloud(cloud_boundary, "v2",v2);

                    visualizer.SetPointCloudColor(0.5, 1, 1, "v1");//原始点云附色
                    visualizer.SetPointCloudColor(0, 1, 0, "v2");//原始点云附色
                    while (!visualizer.WasStopped)
                        visualizer.SpinOnce(100);
                }

                Console.ReadKey();
            }

        }
    }

    3、编译结果

    去噪之前的边界估计 :

    统计滤波去噪之后的边界估计:

     

     

  • 相关阅读:
    【深度学习实战(41)】保姆级教程:Anaconda + Pycharm 安装
    go install 出现 cannot use path@version syntax in GOPATH mode 的解决办法
    QToolButton几个小知识点总结
    如何选购过孔滑环
    SRS srs-bench
    擎创技术流 | 深入浅出运维可观测工具(三):eBPF如何兼容多架构模式性能管理
    复盘Linux期末考试【已凉凉】
    【数学建模】matlab向量(数组)
    ExecutorService、Callable、Future实现有返回结果的多线程原理解析
    java基于springboot校园餐厅订餐管理系统
  • 原文地址:https://blog.csdn.net/swmyaopeng/article/details/126702278