3. 点云分割与聚类:基于欧几偶里得聚类的目标分割、DBSCAN算法在点云中的应用
点云分割与聚类,说白了就是把一堆乱七八糟的点,按照物体分堆。你想想看,激光雷达扫回来几万个点,里面可能有车、有行人、有树、有路灯。如果不把它们分开,后续的跟踪就没法做。
我个人习惯把聚类看作是感知系统的「第一道筛子」。筛得好不好,直接决定了后面目标识别的上限。今天我们就聊聊两种最常用的方法:欧几里得聚类和DBSCAN。
3.1 欧几里得聚类:最直观的分割方式
欧几里得聚类,名字听着挺唬人,其实原理特别简单。就是算两个点之间的直线距离,如果距离小于某个阈值,就认为它们属于同一个物体。
我在项目中第一次用这个方法时,觉得它太「笨」了。但后来发现,对于稀疏的远距离点云,它反而比那些花哨的算法更稳定。嗯,这里要注意一个关键点:阈值的选择。
核心思想:在三维空间中,同一个物体表面的点,彼此之间的距离通常很近。不同物体之间,存在明显的空隙。
算法流程其实就三步:
- 选一个种子点:从点云中随便挑一个没处理过的点
- 找邻居:用KD-Tree快速搜索半径 r 内的所有点
- 生长:把这些邻居点加入当前簇,再以它们为种子继续找
重复以上步骤,直到所有点都被标记。说白了就是个「滚雪球」的过程。
我的经验:阈值 r 怎么设?我一般先看激光雷达的水平角分辨率。比如32线雷达,10Hz频率下,100米处相邻两线的间距大概在0.3米左右。所以 r 设在0.5-1.0米比较合理。太小了会把一辆车切成好几块,太大了会把车和旁边的树粘在一起。
代码实现其实不复杂,PCL库里有现成的:
// PCL 欧几里得聚类示例
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance(0.5); // 距离阈值 0.5米
ec.setMinClusterSize(100); // 最少100个点才算一个目标
ec.setMaxClusterSize(25000); // 最多25000个点
ec.setSearchMethod(tree); // KD-Tree加速
ec.setInputCloud(cloud);
ec.extract(cluster_indices); // 输出聚类结果
你看,核心参数就三个:距离阈值、最小点数、最大点数。最小点数这个参数,我吃过亏。有一次把路边的几个噪点也聚类成一个目标,结果跟踪模块一直报假警。后来我设了最小点数100,这种误检就少了很多。
3.2 DBSCAN:能处理噪声的密度聚类
欧几里得聚类有个硬伤:它假设所有区域的点云密度是一样的。但实际场景中,近处的点密密麻麻,远处的点稀稀拉拉。用同一个阈值,近处容易过分割,远处容易欠分割。
DBSCAN 就是来解决这个问题的。它不看绝对距离,而是看密度。一个点周围如果足够「热闹」,它就是核心点;如果周围冷冷清清,它就是噪声。
DBSCAN 的三个关键概念:
- 核心点:在半径 eps 内至少有 minPts 个点
- 边界点:在核心点的邻域内,但自身不满足核心点条件
- 噪声点:既不是核心点也不是边界点
算法怎么工作的?我简单说说:
- 先找一个核心点,把它邻域内的所有点都拉进来
- 对这些新拉进来的点,如果它们也是核心点,继续扩张
- 直到没有新的核心点可以加入,一个簇就形成了
- 剩下的点,要么是边界点(归入最近的簇),要么是噪声(直接扔掉)
我曾经在一个项目中,用欧几里得聚类处理高速公路场景。结果远处的车因为点太稀疏,被当成了噪声。换成 DBSCAN 后,把 eps 设大一些,远处的车也能被正确聚类。这就是密度聚类的优势——它不要求全局密度一致。
避坑指南:DBSCAN 的参数 eps 和 minPts 是联动的。我建议先固定 minPts=10,然后根据点云密度调整 eps。如果场景中既有近处密集点又有远处稀疏点,可以考虑用自适应 eps,或者分区域设置不同参数。
PCL 里也有 DBSCAN 的实现,不过需要自己封装一下:
// 伪代码:DBSCAN 核心逻辑
for each point p in cloud:
if p is visited: continue
neighbors = regionQuery(p, eps) // 找邻域点
if neighbors.size() < minPts:
mark p as noise
else:
expandCluster(p, neighbors) // 扩张簇
3.3 两种方法怎么选?
说实话,没有绝对的好坏。我个人的经验是:
| 场景 | 推荐方法 | 理由 |
|---|---|---|
| 近距离城市道路(0-50米) | 欧几里得聚类 | 点云密集,阈值好调,速度快 |
| 高速公路(50-150米) | DBSCAN | 密度变化大,DBSCAN 更鲁棒 |
| 有大量噪声的场景 | DBSCAN | 天然支持噪声过滤 |
| 实时性要求极高 | 欧几里得聚类 | 计算量小,容易并行化 |
你想想看,如果场景简单、点云均匀,欧几里得聚类又快又好。但如果场景复杂、噪声多,DBSCAN 的密度思想就派上用场了。
我的一个小技巧:在实际工程中,我经常把两种方法结合起来用。先用 DBSCAN 做粗聚类,把明显的噪声去掉。再用欧几里得聚类做细分割,把粘连的目标分开。这样既保证了鲁棒性,又控制了计算量。
好了,关于点云分割与聚类,今天就聊这么多。这两种方法都是基础中的基础,但用好它们,需要你对场景有深刻的理解。多调参、多试错,慢慢就有感觉了。
本章要点回顾:
- 欧几里得聚类:基于距离阈值,简单高效,适合均匀密度场景
- DBSCAN:基于密度连通,能处理噪声和密度变化
- 参数调优是关键:阈值、最小点数、eps 需要根据场景反复调试
- 实际工程中可组合使用,取长补短