1、 PCL中Sample_consense库实现了随机采样一致性及其泛化估计算法,以及例如平面、柱面等各种常见几何模型,用不同的估计算法和不同的几何模型自由结合估算点云中隐含的具体几何模型的系数,实现对点云中所处的几何模型的分割。线、平面、柱面和球面等模型已经在PCL库中实现,平面模型经常被应用到常见的室内平面分割提取中,比如墙、地板、桌面,其他模型常被应用到根据几何结构检测识别和分割物体中。
RANSAC随机采样一致性算法简介:
RANSAC是一种随机参数估计算法。RANSAC从样本中随机抽选出一个样本子集,使用最小方差估计算法对这个子集计算模型参数,然后计算所有样本与该模型的偏差,再使用一个预先设定好的阈值与偏差比较,当偏差小于阈值时,该样本点属于模型内样本点(inliers),简称为局内点或内点,否则为模型外样本点(outliers),简称为局外点或外点,记录下当前的inliers的个数,然后重复这一过程。每一次重复,都记录当前最佳的模型参数,所谓最佳,即inliers的个数最多,次数对应的inliers个数为best_ninliers。每次迭代的末尾,都会根据期望的误差率、best_ninliers、总样本个数,当前迭代次数,计算一个迭代结束评判因子,据此决定是否迭代结束。迭代结束后,最佳模型参数就是最终的模型参数估计值。
RANSAC理论上可以剔除outliers的影响,并得到全局最优的参数估计。但是RANSAC有两个问题,首先在每次迭代中都要区分inliers和outliers,因此需要事先设定阈值,当模型具有明显的物理意义时,这个阈值还比较容易设定,但是若模型比较抽象时,这个阈值就不那么容易设定了,而且固定阈值不适用于样本动态变化的应用;第二个问题是,RANSAC的迭代次数是运行期决定的,不能阈值迭代的确切次数(当然迭代次数的范围是可以预测的)。除此之外,RANSAC只能从一个特定数据集中估计一个模型,当两个(或者更多个)模型存在时,RANSAC不能找到别的模型。
2、代码:
using PclSharp;
using PclSharp.Helpers;
using PclSharp.SampleConsensus;
using PclSharp.Std;
using PclSharp.Struct;
using System;
using System.Numerics;
namespace PclSharpTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"C#--PclSharp算法库测试:");
读取点云文件
//var inCloud = new PointCloudOfXYZ();
//using (var reader = new PCDReader())
// reader.Read(AppDomain.CurrentDomain.BaseDirectory + $"//pcd//table.pcd", inCloud);
var inCloud = new PointCloudOfXYZ();
var finalCloud = new PointCloudOfXYZ();
//生成数据
Random random = new Random();
for (int i = 0; i < 5000; i++)
{
float x = random.Next(-10,10)/10.0f;
float y = random.Next(-10, 10) / 10.0f;
float z;
if (i % 2 == 0)
{
z = random.Next(-10, 10) / 10.0f;//此处对应的点为局外点
}
else
{
z = -1 * (x + y) / 10.0f;
}
inCloud.Add(new Vector3(x, y, z));
}
inCloud.Width = 5000;//点云数目
inCloud.Height = 1;//设置无序点云
//存储局内点集合的点的索引的向量
VectorOfInt inliers =new VectorOfInt();
//平面模型的对象
SampleConsensusModelPlaneOfXYZ modelPlane = new SampleConsensusModelPlaneOfXYZ(inCloud);
RandomSampleConsensusOfXYZ ransac = new RandomSampleConsensusOfXYZ(modelPlane);
ransac.DistanceThreshold=0.01; //与平面距离小于0.01的点作为局内点
ransac.ComputeModel(); //执行随机参数估计
ransac.GetInliers(inliers);
//按照源点云中的索引复制点到新点云中
PclHelper.copyPointCloud(inCloud, inliers, finalCloud);
using (var visualizer = new PclSharp.Vis.Visualizer(" visual window"))
{
//创建两个观察视点
int v1 = 0;
int v2 = 1;
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(finalCloud, "v1", v1);
visualizer.AddPointCloud(inCloud, "v2", v2);
visualizer.SetPointCloudColor(1, 1, 0.5, "v1");//点云附色
visualizer.SetPointCloudColor(1, 0.5, 1, "v2");//点云附色
while (!visualizer.WasStopped)
visualizer.SpinOnce(100);
}
Console.ReadKey();
}
}
}
3、原始点云平面内点与立方体外点