PclSharp1.12.0--BoundaryEstimation(基于法线的边界提取)

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

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

2、源码

注:测试代码均使用PclSharp1.12.0库

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

去噪之前的边界估计 :

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

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西~风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值