基于RANSAC的激光点云分割

Lidar系列文章

传感器融合是将多个传感器采集的数据进行融合处理,以更好感知周围环境;这里首先介绍激光雷达的相关内容,包括激光雷达基本介绍(本节内容),激光点云数据处理方法(点云数据显示,点云分割,点云聚类,障碍物识别实例)等。

系列文章目录

1. 激光雷达基本介绍
2. 激光点云数据显示
3. 基于RANSAC的激光点云分割
4. 点云分割入门级实例学习
5. 激光点云目标物聚类
6. 基于PCL实现欧式聚类提取
7. 激光雷达障碍物识别


RANSAC随机抽样一致简介

RANSAC(RANdom SAmple Consensus)随机抽样一致,最早于1981年由Fischler和Bolles提出,基本思想是根据一组包含噪声、外点的各种缺陷的样本数据集中,估计出数据的数学模型参数,并同时得到有效样本数据。

RANSAC从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。每次迭代时选取一个数据子集(线:2个数据点,面:三个数据点)并对其进行拟合,计算剩余点到拟合后的模型(线/面)的距离,包含最多数量的“局内点”(距离模型一定范围内的点)或最小的噪声作为最佳模型。
RANSAC algorithm for line fitting with outliers
类似的RANSAC方法也包括先对数据集进行采样(如20%数据),对其进行拟合并计算偏差,偏差最小的为最佳模型。这种方法的优势是每次迭代中不用考虑所有点。

实例-使用RANSAC拟合直线

对于平面中的点,RANSAC方法拟合直线的主要步骤如下:

  1. 每次迭代中从数据集中随机采样2个点;
  2. 基于两个采样点拟合一条直线;
  3. 计算每个点到拟合直线的距离,容差内的点为内点。
  4. 每次迭代过程中跟踪拟合的直线,保留内点最多的拟合直线,即为最佳的模型。

下面将以RANSAC拟合2D点云中的直线进行介绍。下图是对数据集进行采样的子集。
Simple 2D Point Cloud Data
直线公式:
A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0
设其经过点1(x1, y1)和点2(x2, y2),则经过这两点的直线公式为:
( y 1 − y 2 ) x + ( x 2 − x 1 ) y + ( x 1 ∗ y 2 − x 2 ∗ y 1 ) = 0 (y1−y2)x+(x2−x1)y+(x1∗y2−x2∗y1)=0 (y1y2)x+(x2x1)y+(x1y2x2y1)=0
平面内点(x,y)到直线的距离d:
d = ∣ A x + B y + C ∣ / s q r t ( A 2 + B 2 ) d=∣Ax+By+C∣/sqrt(A^2 +B^2 ) d=Ax+By+C/sqrt(A2+B2)

std::unordered_set<int> Ransac(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, int maxIterations, float distanceTol)
{
   
	std::unordered_set<int> inliersResult;
	srand(time(NULL)); //srand() generate a random seed associate with current time.
	
	// TODO: Fill in this function
	// For max iterations 
	// Randomly sample subset and fit line
	// Measure distance between every point and fitted line
	// If distance is smaller than threshold count it as inlier
	// Return indicies of inliers from fitted line with most inliers

  // Time segmentation process
  auto startTime = std::chrono::steady_clock::now();

  while(maxIterations--)// For max iterations 
  {
   
    //Randomly pick two points;
    std::unordered_set<int> inliers;
    while(inliers.size()<2)
      inliers.insert(rand()%(cloud->points.size()));

    float x1, y1, x2, y2;
    auto itr = inliers.begin();
    x1 = cloud->points[*itr].x;
    y1 = cloud->points[*itr].y;
    itr++;
    x2 = cloud->points[*itr].x;
    y2 = cloud->points[*itr].y;
    //Line formula ax + by + c = 0
    float a = y1 - y2;
    float b = x2 - x1;
    float c = x1*y2 - x2*y1;

    // Measure distance between every point and fitted line
    // If distance is smaller than threshold count it as inlier
    for(int index=0; index < cloud->points.size(); index++)
    {
   
      //discard previous two points
      if(inliers.count(index)>0)
        continue;
      
      pcl::PointXYZ point = cloud->points[index];
      float x3 = point.x;
      float y3 
  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在C#中进行激光点云平面分割可以使用一些开源库,例如PointCloudLibrary(PCL)或者Unity3D的PointCloudRenderer插件。下面是一个使用PointCloudLibrary进行激光点云平面分割的示例代码: ```csharp using System; using System.Collections.Generic; using PCLStorage; using PCLStorage.Extensions; using PCLStorage.FileSystem; using pcl; using pcl.common; using pcl.io; using pcl.kdtree; using pcl.segmentation; namespace LaserPointCloudSegmentation { class Program { static void Main(string[] args) { // 读取点云数据 var cloud = new PointCloud<PointXYZ>(); using (var reader = new PCDReader()) { reader.Read("path_to_pcd_file", cloud); } // 创建分割对象 var seg = new SACSegmentation<PointXYZ>(); seg.SetOptimizeCoefficients(true); seg.ModelType = SACSegmentation<PointXYZ>.SACMODEL_PLANE; seg.MethodType = SACSegmentation<PointXYZ>.SAC_RANSAC; seg.MaxIterations = 100; seg.DistanceThreshold = 0.01; // 执行平面分割 var inliers = new PointIndices(); var coefficients = new ModelCoefficients(); seg.Segment(inliers, coefficients); // 提取分割结果 var cloud_segmented = new PointCloud<PointXYZ>(); var extract = new ExtractIndices<PointXYZ>(); extract.SetInputCloud(cloud); extract.SetIndices(inliers); extract.Filter(cloud_segmented); // 输出分割结果 Console.WriteLine($"Plane coefficients: {coefficients.Values[0]}, {coefficients.Values[1]}, {coefficients.Values[2]}, {coefficients.Values[3]}"); Console.WriteLine($"Segmented cloud size: {cloud_segmented.Size}"); // 保存分割结果 using (var writer = new PCDWriter()) { writer.Write("path_to_output_pcd_file", cloud_segmented); } } } } ``` 在上述代码中,你需要将 `path_to_pcd_file` 替换为你的点云文件的路径,将 `path_to_output_pcd_file` 替换为保存分割结果的路径。注意,你需要先安装并导入PointCloudLibrary(PCL)和相应的依赖项。 这只是一个简单示例,你可以根据自己的需求进行更复杂的激光点云平面分割算法实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值