当前位置: 首页 > news >正文

Open3D 对点云进行去噪(下采样、欧式聚类分割)01

Open3D使用 下采样(Voxel Downsample)欧式聚类分割(Cluster DBSCAN) 优化点云的去噪效果,尤其是在面对大量噪声或孤立簇时非常有效。

  1. Voxel 下采样:降低点云密度,加速后续处理。
  2. DBSCAN 聚类分割:识别并移除孤立的小点簇(即噪声簇)。

在这里插入图片描述

✅ 方法一:Voxel 下采样(Voxel Downsample)

📌 原理说明:

通过将空间划分为体素(voxel),每个体素内只保留一个代表点(如中心点或平均点),从而达到降采样和初步去噪的目的。

# 设置 voxel_size,根据你的点云密度调整(单位与点云一致,例如米或毫米)
voxel_size = 0.05  # 例如:5厘米# 执行 Voxel 下采样
downsampled_pcd = filtered_pcd.voxel_down_sample(voxel_size=voxel_size)print(f"原始点数量: {len(filtered_pcd.points)}")
print(f"下采样后点数量: {len(downsampled_pcd.points)}")

✅ 方法二:欧式聚类分割(Cluster DBSCAN)

📌 原理说明:

DBSCAN 是一种基于密度的聚类算法,能识别出密集区域的点簇,并将稀疏的、孤立的小簇标记为噪声。

# 使用欧式聚类 DBSCAN 分割
with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:labels = np.array(downsampled_pcd.cluster_dbscan(eps=0.3, min_points=10, print_progress=True))# eps: 搜索邻域半径(单位与点云一致)
# min_points: 成为一个簇所需的最小点数# 显示聚类结果
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  # 噪声点涂成黑色
downsampled_pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])# 可视化聚类结果
o3d.visualization.draw_geometries([downsampled_pcd])

✅ 方法三:结合使用 —— 移除孤立小簇(更彻底去噪)

如果你的目标是去除所有不属于大簇的点(即噪声),可以按如下方式操作:

# 将簇标签转换为整型数组
unique_labels, counts = np.unique(labels, return_counts=True)# 设置最小簇大小阈值(例如:50个点)
min_cluster_size = 50# 获取满足条件的簇标签
valid_clusters = unique_labels[counts >= min_cluster_size]# 构建 mask:仅保留属于“大簇”的点
mask = np.isin(labels, valid_clusters)# 应用 mask 到点云
cleaned_points = np.asarray(downsampled_pcd.points)[mask]
cleaned_colors = np.asarray(downsampled_pcd.colors)[mask] if downsampled_pcd.has_colors() else None# 创建新的干净点云
final_cleaned_pcd = o3d.geometry.PointCloud()
final_cleaned_pcd.points = o3d.utility.Vector3dVector(cleaned_points)
if cleaned_colors is not None:final_cleaned_pcd.colors = o3d.utility.Vector3dVector(cleaned_colors)# 可视化最终结果
o3d.visualization.draw_geometries([final_cleaned_pcd])

🧠 总结流程建议:

步骤目的
voxel_down_sample()减少点数量,提高效率,初步去噪
cluster_dbscan()识别点簇,区分主要结构与孤立噪声
mask + filter移除小簇噪声,保留主要结构

📦 完整函数封装示例(可直接调用)

def remove_noise_with_clustering(pcd, voxel_size=0.05, eps=0.3, min_points=10, min_cluster_size=50):# Step 1: 下采样downsampled_pcd = pcd.voxel_down_sample(voxel_size=voxel_size)# Step 2: DBSCAN 聚类labels = np.array(downsampled_pcd.cluster_dbscan(eps=eps, min_points=min_points, print_progress=False))# Step 3: 过滤小簇unique_labels, counts = np.unique(labels, return_counts=True)valid_clusters = unique_labels[counts >= min_cluster_size]mask = np.isin(labels, valid_clusters)# Step 4: 提取干净点云cleaned_points = np.asarray(downsampled_pcd.points)[mask]cleaned_colors = np.asarray(downsampled_pcd.colors)[mask] if downsampled_pcd.has_colors() else Nonecleaned_pcd = o3d.geometry.PointCloud()cleaned_pcd.points = o3d.utility.Vector3dVector(cleaned_points)if cleaned_colors is not None:cleaned_pcd.colors = o3d.utility.Vector3dVector(cleaned_colors)return cleaned_pcd

✅ 使用示例:

import open3d as o3d
import numpy as npdef remove_noise_with_clustering(pcd, voxel_size=0.05, eps=0.3, min_points=10, min_cluster_size=50):# Step 1: 下采样downsampled_pcd = pcd.voxel_down_sample(voxel_size=voxel_size)# Step 2: DBSCAN 聚类labels = np.array(downsampled_pcd.cluster_dbscan(eps=eps, min_points=min_points, print_progress=False))# Step 3: 过滤小簇unique_labels, counts = np.unique(labels, return_counts=True)valid_clusters = unique_labels[counts >= min_cluster_size]mask = np.isin(labels, valid_clusters)# Step 4: 提取干净点云cleaned_points = np.asarray(downsampled_pcd.points)[mask]cleaned_colors = np.asarray(downsampled_pcd.colors)[mask] if downsampled_pcd.has_colors() else Nonecleaned_pcd = o3d.geometry.PointCloud()cleaned_pcd.points = o3d.utility.Vector3dVector(cleaned_points)if cleaned_colors is not None:cleaned_pcd.colors = o3d.utility.Vector3dVector(cleaned_colors)return cleaned_pcdif __name__ == "__main__":# 加载点云file_path = "demo.ply"pcd = o3d.io.read_point_cloud(file_path)# 将点云数据转化为numpy数组points = np.asarray(pcd.points)colors = np.asarray(pcd.colors)  # 获取颜色数据# 筛选Z轴小于设定阈值的点及其对应的颜色mask = (points[:, 2] > 500) & (points[:, 2] < 3000)filtered_points = points[mask]filtered_colors = colors[mask]# 交换X轴和Y轴的数据filtered_points[:, [0, 1]] = filtered_points[:, [1, 0]]# 创建新的点云对象并赋值筛选后的点和颜色filtered_pcd = o3d.geometry.PointCloud()filtered_pcd.points = o3d.utility.Vector3dVector(filtered_points)filtered_pcd.colors = o3d.utility.Vector3dVector(filtered_colors)cleaned_pcd = remove_noise_with_clustering(filtered_pcd, voxel_size=0.05*1000, eps=0.3*1000, min_points=10, min_cluster_size=50)o3d.visualization.draw_geometries([filtered_pcd],width=800, height=500)o3d.visualization.draw_geometries([cleaned_pcd],width=800, height=500)

原点云:
在这里插入图片描述
Voxel 下采样+欧式聚类分割(Cluster DBSCAN)
在这里插入图片描述

相关文章:

  • 基于算法竞赛的c++编程(25)指针简单介绍和简单应用
  • 【Vue】scoped+组件通信+props校验
  • DingDing机器人群消息推送
  • 二维FDTD算法仿真
  • JVM如何优化
  • Qt学习及使用_第1部分_认识Qt---Qt开发基本流程
  • AirPosture | 通过 AirPods 矫正坐姿
  • while/do while/for循环几个小细节
  • 免费数学几何作图web平台
  • React中子传父组件通信操作指南
  • JavaScript的ArrayBuffer与C++的malloc():两种内存管理方式的深度对比
  • Linux进程信号(一)
  • LLMs 系列实操科普(2)
  • Spring Boot面试题精选汇总
  • 如何做好一份技术文档?从规划到实践的完整指南
  • React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
  • ubuntu22.04 安装docker 和docker-compose
  • 安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
  • 在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
  • 【自动控制原理】分析和设计控制系统的性能(*^▽^*)
  • 芜湖经济开发区网站/新站如何快速收录
  • 网站seo插件/电商seo
  • 做网站前怎么写文档/网站页面优化方案
  • 网站建设人员/商丘关键词优化推广
  • 怎么查看网站域名/百度热搜榜排名今日第一
  • 网站建设方案多少钱/app软件开发