激光感知(五):点云聚类算法之DBSCAN

目录

  • 一、DBSCAN介绍
  • 二、算法流程
  • 三、算法改进
  • 四、KD-Tree
      • 1. 构造
      • 2. leaf_size
      • 3. 如何进行半径搜索

一、DBSCAN介绍

在点云数据分析中,我们经常需要对点云数据进行分割,提取感兴趣的部分。聚类是点云分割中的一类方法(其他方法有模型拟合、区域增长、基于图的方法、深度学习方法等)。DBSCAN 是一种基于密度的聚类算法,具有抗噪声、无需指定类别种数、可以在空间数据中发现任意形状的聚类等优点,适用于点云聚类

二、算法流程

DBSCAN 算法核心是找到密度相连对象的最大集合,算法流程如下图伪代码所示:
激光感知(五):点云聚类算法之DBSCAN_第1张图片

首先对点云进行逐点遍历,如果该点非核心点,则认为是噪声点并忽视(噪声点可能在后续被核心点归入聚类中),若为核心点则新建聚类,并将所有邻域点加入聚类。对于邻域点中的核心点,还要递归地把其邻域点加入聚类。依此类推直到无点可加入该聚类,并开始考虑新的点,建立新的聚类。
激光感知(五):点云聚类算法之DBSCAN_第2张图片

三、算法改进

DBSCAN 虽然具有抗噪声、无需指定类别种数、可以在空间数据中发现任意形状的聚类等优点,但也存在计算复杂度高,计算时间过长的问题,直接使用并不能满足自动驾驶场景的应用条件,需要对算法复杂度进行改进 。

这里算法的复杂度取决于邻域点查找(即RangeQuery)的复杂度。最直观的方法是使用线性扫描查找,但是这样算法整体时间复杂度为O(n^2),这里给出两种改进方法:

  • 一种改进的方法是通过预先计算距离矩阵后进行邻域查找。其复杂度为 O ( n 2 / 2 ) + O ( n ∗ k ) ,其中 k 为平均邻域点数。但是这种改进的缺点是需要额外 O ( n 2 ) 或 O ( n ∗ k ) 的空间。
  • 另一种更大的改进是使用索引方法查询邻域点,如使用Kdtree。其复杂度为 O ( n ∗ l o g ( n ) + k ∗ l o g ( n ) ∗ n ),其中加号前一项为建树时间复杂度,后一项为邻域查找复杂度。

使用Kdtree结构进行聚类是一种比较适合激光点云这样数据量大的样本的方式,能较大的减少计算复杂度。

四、KD-Tree

kd-tree(k-dimensional树的简称),是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。主要应用于多维空间关键数据的搜索,比如范围搜索和最近邻搜索。

1. 构造

构建KD树步骤如下(假设样本具有n个特征):

1) 分别计算n个特征的方差,选择方差最大的一个特征(假设为特征a);或者循环使用N个维度来分割空间。

2) 对特征a,计算其中位数值median,以该值作为样本的划分点(根节点)。

3) 针对样本集中的其他数据,根据特征a进行划分,所有小于median的样本划分到左子树中,所有大于median的样本划分到右子树中。

4) 分别对左右子树递归进行以上步骤,直到左右子树的样本数量不超过leaf_size指定的数量为止。
激光感知(五):点云聚类算法之DBSCAN_第3张图片

2. leaf_size

影响kd_tree / ball_tree的构建。

1) 当leaf_size值很小的时候,kd_tree / ball_tree的深度就会很大,因此,构建时间(或查找时间)就会较长。

2) 当leaf_size值很大的时候,kd_tree / ball_tree的深度就会较小,构建时间(或查找时间)就会较短。

3) 特殊的,如果样本集中含有M个样本,而leaf_size的值为M,此时,kd_tree / ball_tree只会含有一个节点,此时,就相当于是brute算法。

3. 如何进行半径搜索

1) 找到当前样本所在叶子节点,搜索叶子节点内的点;
2) 以样本点为核心,指定距离为半径,画一个超球体;
3) 从堆栈中依次弹出节点,检测超球体与节点分割线是否相交,相交表明另外一侧(另一棵子树)可能存在半径内的点
4) 对另外一颗子树进行遍历搜索,重复上述操作得到半径内的点,这样只搜索邻域,计算量少
激光感知(五):点云聚类算法之DBSCAN_第4张图片

你可能感兴趣的:(从零开始入门自动驾驶感知算法)