【小白深度教程 1.28】手把手教你使用 Open3D(11)地面分割+点云聚类来实现目标分割(Python 代码)

【小白深度教程 1.28】手把手教你使用 Open3D(11)地面分割+点云聚类来实现目标分割(Python 代码)

在这篇文章中,我们将学习如何使用 Open3D 对自动驾驶中获取的激光雷达数据(点云),进行地面分割+点云聚类来实现目标分割。

在这个教程中,我们将学习如何对点云数据进行处理,首先分割地面,然后通过设置高度阈值去除地面点,最终对非地面部分进行聚类分析。我们将使用Open3D库来完成这个任务。

可视化效果:

分割结果:

在这里插入图片描述

Python 源码:

import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt

def load_bin_file(file_path):
    """ Load a .bin point cloud file. """
    # Load the point cloud data assuming each point is [x, y, z] format
    point_cloud = np.fromfile(file_path, dtype=np.float32).reshape(-1, 4)[:, :3]  # Assuming (x, y, z, intensity)
    return point_cloud

# 加载点云数据
file_path = '0000000000.bin'  # Replace with your .bin file path
points = load_bin_file(file_path)

# Create an Open3D point cloud object
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)

# 可视化原始点云
o3d.visualization.draw_geometries([pcd], window_name="Original Point Cloud")

# 去噪,移除离群点
pcd = pcd.voxel_down_sample(voxel_size=0.05)  # 使用体素网格下采样点云
pcd, ind = pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=2.0)  # 移除离群点

# 估计法向量
pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))
pcd.orient_normals_consistent_tangent_plane(100)

# 使用 RANSAC 分割地面
plane_model, inliers = pcd.segment_plane(distance_threshold=0.05, ransac_n=3, num_iterations=1000)
[a, b, c, d] = plane_model
print(f"地面平面模型: {plane_model}")

# 提取地面点和非地面点云
ground_pcd = pcd.select_by_index(inliers)
non_ground_pcd = pcd.select_by_index(inliers, invert=True)

# 获取地面点的高度范围
ground_points = np.asarray(ground_pcd.points)
ground_height = np.mean(ground_points[:, 2])  # 获取地面点的平均高度
height_threshold = ground_height + 0.2  # 设置高度阈值(可根据需要调整)

# 使用高度阈值分割非地面点
all_points = np.asarray(non_ground_pcd.points)
filtered_indices = np.where(all_points[:, 2] > height_threshold)[0]
filtered_pcd = non_ground_pcd.select_by_index(filtered_indices)

# 可视化过滤后的非地面点云
o3d.visualization.draw_geometries([filtered_pcd], window_name="Filtered Non-Ground Points")

# 对过滤后的点云使用 DBSCAN 进行聚类
labels = np.array(filtered_pcd.cluster_dbscan(eps=0.3, min_points=10, print_progress=True))

# 获取聚类的数量
max_label = labels.max()
print(f"非地面点云中的聚类数量: {max_label + 1}")

# 为每个聚类分配不同的颜色
colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
colors[labels < 0] = 0  # 对于噪声点,设为黑色
filtered_pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])

# 可视化聚类结果
o3d.visualization.draw_geometries([filtered_pcd], window_name="DBSCAN Clustering Result")

总结与调整建议

参数调整:RANSAC分割的 distance_threshold 和 DBSCAN的 eps 参数是关键,需要根据实际数据进行调试。

高度阈值设定: height_threshold 可以根据具体需求调整,以确保有效分离地面和非地面区域。

聚类分析:DBSCAN的 min_points 参数决定了对小规模物体的识别敏感性,可根据需要进行调节。