尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

激光雷达点云分割——地面分离、聚类分析和物体提取

激光雷达点云分割——地面分离、聚类分析和物体提取 上篇把点云滤波的四种方法讲透了——体素降采样、统计滤波、直通滤波、半径滤波以及参数怎么选、实时性能怎么优化。滤波之后拿到干净的点云下一步就是把点云里的不同物体分开这就是点云分割。面试时候被问你怎么从点云里识别出障碍物很多候选人直接跳到用深度学习做语义分割。但实际项目中传统的几何分割方法用得更多因为它们速度快、可解释性强、不需要大量标注数据。今天讲三种最经典的分割方法RANSAC地面分离、欧式聚类、区域生长。搞懂这三种大部分机器人项目的分割需求都能覆盖。地面分离RANSAC平面拟合移动机器人的点云里地面通常占了40%-60%的点。把地面去掉剩下的就是障碍物和感兴趣的目标。地面在大多数场景下可以近似为一个平面。RANSACRandom Sample Consensus是拟合平面最鲁棒的方法。RANSAC的思路很直觉随机选3个点确定一个平面看有多少点落在这个平面附近内点。重复N次选内点最多的那个平面。import open3d as o3d pcd o3d.io.read_point_cloud(scan.pcd) # RANSAC平面拟合 plane_model, inliers pcd.segment_plane( distance_threshold0.1, # 点到平面距离小于0.1m算内点 ransac_n3, # 每次随机选3个点 num_iterations100 # 迭代100次 ) # 提取地面和障碍物 ground pcd.select_by_index(inliers) obstacles pcd.select_by_index(inliers, invertTrue) print(f地面点数: {len(ground.points)}) print(f障碍物点数: {len(obstacles.points)}) print(f平面方程: {plane_model})plane_model返回的是平面方程的四个系数[a, b, c, d]对应ax by cz d 0。正常情况下cz的系数应该接近1因为地面大致是水平的。如果c很小说明拟合出来的平面几乎是竖直的大概率是拟合失败了。这里值得展开讲讲RANSAC的原理。RANSAC的核心是随机采样一致性验证。每次随机选3个点算一个平面然后统计有多少点落在这个平面附近内点。重复N次取内点最多的那次作为最终结果。为什么需要多次迭代因为你不知道哪3个点能确定一个好平面。如果随机选到的3个点恰好都在一个噪声簇上拟合出来的平面就是错的。迭代次数越多至少有一次选到3个好点的概率就越大。迭代次数怎么定有个理论公式N log(1-p) / log(1-w³)其中p是期望成功概率通常0.99w是内点比例。实际中一般设100次——计算量小100次迭代总共几毫秒且内点比例可能比估计的低。面试时候如果被问RANSAC和最小二乘拟合平面有什么区别回答要点最小二乘用所有点来拟合对离群点非常敏感一个远处噪声点就能把平面拉歪。RANSAC用随机采样内点投票对离群点天然鲁棒。所以点云分割几乎都用RANSAC而不是最小二乘。distance_threshold的选择很关键。室内地面比较平整0.05-0.1米就够了。室外地面有坡度、有起伏要放宽到0.15-0.3米。但也不能太宽松否则会把低矮障碍物的点也算进地面里。RANSAC有个前提假设地面是一个完整的平面。如果你的场景里有楼梯、斜坡、台阶地面不是单一平面RANSAC就只能拟合出其中一个面。这种情况下需要多平面分割或者用其他方法后面会提。PCL里的写法#include pcl/segmentation/sac_segmentation.h pcl::SACSegmentationpcl::PointXYZ seg; seg.setOptimizeCoefficients(true); seg.setModelType(pcl::SACMODEL_PLANE); seg.setMethodType(pcl::SAC_RANSAC); seg.setDistanceThreshold(0.1); seg.setInputCloud(cloud); seg.segment(*inliers, *coefficients);欧式聚类最常用的点云聚类方法去掉地面之后剩下的点云需要按物体分开。欧式聚类Euclidean Cluster Extraction是最直接的方法把距离足够近的点归为同一簇。# Open3D欧式聚类 clustering pcd.cluster_dbscan(eps0.15, min_points20) labels np.array(clustering) # 按标签提取每个簇 for i in set(labels): if i -1: # 噪声点 continue cluster pcd.select_by_index(np.where(labels i)[0]) print(f簇{i}: {len(cluster.points)}个点)eps是两个点被认为属于同一簇的最大距离min_points是一个簇至少包含的点数。室内场景eps一般设0.1-0.2米室外可以放宽到0.3-0.5米。欧式聚类的优点是简单高效缺点也很明显只看距离不看几何特征。两个距离很近但法线方向完全不同的面会被合并成一个簇。比如墙角的两面墙距离很近但属于不同平面。区域生长结合法线信息的分割区域生长解决了欧式聚类只看距离的问题。它的思路是从种子点出发把法线方向相近、空间相邻的点归为同一区域。# PCL区域生长 pcl::RegionGrowingRGBpcl::PointXYZRGB reg; reg.setMinClusterSize(50); reg.setMaxClusterSize(100000); reg.setSearchMethod(tree); reg.setNumberOfNeighbours(30); reg.setInputCloud(cloud); // 设置法线阈值弧度 reg.setSmoothnessThreshold(3.0 / 180.0 * M_PI); reg.setColorThreshold(10.0); reg.extract(*clusters);区域生长同时考虑了法线方向和颜色或曲率的相似性。和欧式聚类相比它能区分距离近但朝向不同的表面比如区分墙面和地面。但计算量更大因为需要先估计每个点的法线。在机器人项目中我的经验是先用RANSAC去地面再用欧式聚类做粗分割对需要精细分割的物体再用区域生长。面试中怎么聊面试官问点云分割按这个顺序回答先说RANSAC去地面原理、参数、局限再说欧式聚类原理、参数、和区域生长的对比最后结合项目说你的分割流程和效果。如果面试官问欧式聚类有什么缺点你可以说只看距离不看几何特征近距离的不同物体会被合并。改进方案是区域生长结合法线信息或者用深度学习方法做语义分割。如果面试官问实时性怎么保证你可以说RANSAC迭代次数可以限制100次通常足够欧式聚类用KD树加速整个分割流程在降采样后的点云上跑5万点以内可以在20毫秒内完成。实际项目中建议先用离线数据调好参数再上在线系统验证避免在实时系统上反复试参数浪费时间。下一篇讲相机成像原理。从点云到图像传感器的世界不只是激光雷达视觉传感器同样重要。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第149篇 激光雷达点云滤波——体素降采样、统计滤波和直通滤波 下一篇预告第151篇 相机成像原理——小孔模型、镜头畸变和成像几何有任何问题欢迎评论区留言我会尽量回复。
返回列表