【Lidar】Open3D点云DBSCAN聚类算法:基于密度的点云聚类(单木分割)附Python代码

发布时间 2023-12-18 16:17:19作者: RS迷途小书童

1 DBSCAN算法介绍

        DBSCAN聚类算法是一种基于密度的聚类算法,全称为“基于密度的带有噪声的空间聚类应用”,英文名称为Density-Based Spatial Clustering of Applications with Noise。

        DBSCAN聚类算法能够发现任意形状的类别,并且对噪音数据具有较强的鲁棒性。其基本思想是,如果一个点在给定的邻域内有足够多的相邻点,那么该点就是一个核心点;如果一个点在给定的邻域内没有足够多的相邻点,那么该点就是一个边界点;如果一个点既不是核心点也不是边界点,那么该点就是噪音点。

        DBSCAN聚类算法的优点在于,它只需要扫描一遍数据集即可完成聚类,不需迭代执行,因此具有较高的效率。此外,DBSCAN聚类算法可以发现任意形状的簇,而不仅仅是凸形簇。

        在实际应用中,DBSCAN聚类算法可以应用于许多领域,如图像处理、文本挖掘、生物信息学等。例如,在图像处理中,可以使用DBSCAN聚类算法对图像进行分割和识别;在文本挖掘中,可以使用DBSCAN聚类算法对文本进行主题分类和情感分析;在生物信息学中,可以使用DBSCAN聚类算法对基因序列进行聚类分析。总之,DBSCAN聚类算法是一种非常实用的聚类算法,可以应用于许多领域。

2 Python代码

        我这里使用的是Open3D库自带的DBSCAN算法,主要参数就两个:1、eps: 这是确定邻域的半径。它决定了在考虑一个点是否在某个点的邻域时,我们考虑的范围有多大。2、min_points: 这是构成一个簇所需要的最少点数。如果一个点的邻域中包含的点数少于这个值,那么这个点将被视为噪声点,不会加入任何簇。

# -*- coding: utf-8 -*-
"""
@Time : 2023/11/3 14:37
@Auth : RS迷途小书童
@File :Point Cloud Clustering.py
@IDE :PyCharm
@Purpose:点云聚类
"""
import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt


def DBSCAN():
    # 欧式聚类,注意eps和min_points的取值
    pcd_path = r"4 - Cloud.pcd"
    pcd = o3d.io.read_point_cloud(pcd_path)
    pcd = o3d.geometry.PointCloud(pcd)
    print(pcd)
    # pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
    with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:
        labels = np.array(pcd.cluster_dbscan(eps=0.045, min_points=20, print_progress=True))
        # eps: 这是确定邻域的半径。它决定了在考虑一个点是否在某个点的邻域时,我们考虑的范围有多大。
        # min_points: 这是构成一个簇所需要的最少点数。如果一个点的邻域中包含的点数少于这个值,那么这个点将被视为噪声点,不会加入任何簇。
    max_label = max(labels)  # 最大的类别值
    print(f"point cloud has {max_label + 1} clusters")
    colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
    colors[labels < 0] = 0  # 类别为0的,颜色设置为黑色
    pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])  # ndarray to vector3d
    o3d.visualization.draw([pcd], width=1920, height=1080)
    output_path = "clustered_point_cloud.pcd"
    o3d.io.write_point_cloud(output_path, pcd)


if __name__ == "__main__":
    DBSCAN()

3 效果展示

4 总结

        总的来说,DBSCAN算法还是不错的,它作为基于欧式距离为基础的密度聚类算法在表现上还可以。但是对于完善地林业单木分割还是有些困难,可能还需要加入其他算法来修正它的结果。其次在DBSCAN算法的参数方面需要好好臻选,如果搜索半径设置的过大程序就会执行很长一段时间!