1、在平面模型上构建凸(凹)多边形,首先从点云中提取平面模型,在通过该估计的平面模型系数从滤波后的点云投影一组点集形成点云,最后为投影后的点云计算其对应的二维凸(凹多边形)
2、源码
using PclSharp;
using PclSharp.Common;
using PclSharp.Filters;
using PclSharp.IO;
using PclSharp.SampleConsensus;
using PclSharp.Segmentation;
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_mug_stereo_textured.pcd", cloud);
// 1、构建直通滤波器,对点云进行滤波处理
PointCloudOfXYZ cloudFiltered = new PointCloudOfXYZ();//滤波后的点云
using (var pass = new PclSharp.Filters.PassThroughOfXYZ())
{
pass.SetInputCloud(cloud);
pass.FilterFieldName = "z";
pass.FilterLimits = (0, 1.1f);
pass.filter(cloudFiltered);
}
//2、创建分割对象并设置一些参数,使用SACMODEL_PLANE模型来分割点云,
//用来估计出该模型系数的方法是SAC_RANSAC(随机抽样一致性算法),
//当调用seg.segment(inliers, coefficents)时,分割就执行了,将所有的内点存储到inliers成员中、将屏幕估计的平面模型系数(ax + by + cz = d)存储到coefficient成员中:
var inliers = new PointIndices();
var coefficients = new ModelCoefficients();
using (var seg = new SACSegmentationOfXYZ())
{
seg.OptimizeCoefficients = true;//设置优化系数,该参数是可选设置
seg.ModelType = SACModel.Plane;//设置分割的是平面
seg.MethodType = SACMethod.RANSAC;//设置分割方法为随机一致性
seg.DistanceThreshold = 0.01;//设置距离阈值0.01
seg.SetInputCloud(cloudFiltered);//设置输入点云为过滤后的点云
//根据模型参数分割内点,存储分割结果到点集合inliers及存储平面模型的系数coefficients
seg.Segment(inliers, coefficients);
}
//3、将上面得到的滤波后的点集投影到平面模型上,并存储投影后的点云数据到cloud_projected对象。创建cloud_projected有两种方法,其中一种方法是直接提取之前得到的内点集合,不过这个例子里我们打算用之前得到的coefficients参数,建立平面模型后按照coefficients参数对该投影对象进行设置,然后将cloud_filtered投射到coefficients参数确定的平面模型上,就可以产生投影后的点云cloud_projected
var cloud_projected = new PointCloudOfXYZ();
using (var proj = new ProjectInliersOfXYZ())//创建点云投影滤波对象
{
proj.ModelType = SACModel.Plane; //设置投影模型为平面
proj.SetInputCloud(cloudFiltered); //设置输入点云为滤波后的点云
proj.SetModelCoefficients(coefficients); //根据参数估计设置投影平面
proj.filter(cloud_projected); //将滤波后的点云投影到平面模型
}
//4、执行ConcaveHull对象的创建和重建获取点云对应的凹多边形边界上的点
var cloud_hull = new PointCloudOfXYZ();
using (ConcaveHullOfXYZ concave_hull = new ConcaveHullOfXYZ())//创建多边形提取对象
{
concave_hull.SetInputCloud(cloud_projected);//设置输入点云为投影后的点云
//concave_hull.Dimension = 3; // 设置凹包维度
//设置alpha值,参数alpha限制voronoi图中多边形边长的长短(边长越短多边形越细分),alpha值是一个非零的正值,定义了voronoi图中多边形顶点到中心点的最大距离
concave_hull.Alpha = 0.1;//重建提取创建凹多边形
concave_hull.Reconstruct(cloud_hull);
}
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_hull, "v2", v2);
visualizer.SetPointCloudColor(1, 1, 0.5, "v1");//点云附色
visualizer.SetPointCloudColor(1, 0.5, 1, "v2");//点云附色
//visualizer.AddPolygonMesh1(mesh);
while (!visualizer.WasStopped)
visualizer.SpinOnce(100);
}
Console.ReadKey();
}
}
}
3、编译结果
1)原始点云可视化结果:
2)重建后点云可视化结果