2. 点云体素下采样
任务目标
读取一份点云数据,通过体素滤波器(VoxelGrid)进行下采样,在保持物体整体形状特征的前提下显著降低点云密度,并输出下采样前后的点云数量及可视化对比结果。
环境依赖
需要安装 open3d 和 numpy。若本地无现成点云文件,可使用 Open3D 内置的示例数据(如 fragment.ply)或随机生成一份点云作为输入。
关键完整代码
import open3d as o3d
import numpy as np
# 1. 加载点云(若文件不存在则生成随机点云用于演示)
pcd_path = "fragment.ply"
try:
pcd = o3d.io.read_point_cloud(pcd_path)
if pcd.is_empty():
raise FileNotFoundError
except Exception:
# 生成一个包含曲面结构的随机点云(球面采样 + 噪声)
print("未找到点云文件,生成随机球面点云作为输入...")
theta = np.random.uniform(0, np.pi, 5000)
phi = np.random.uniform(0, 2 * np.pi, 5000)
r = 1.0
x = r * np.sin(theta) * np.cos(phi)
y = r * np.sin(theta) * np.sin(phi)
z = r * np.cos(theta)
points = np.column_stack((x, y, z))
points += np.random.normal(0, 0.02, points.shape) # 添加轻微噪声
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
print(f"原始点云点数: {len(pcd.points)}")
# 2. 体素下采样
voxel_size = 0.05 # 体素边长,可根据点云尺度调整
downsampled = pcd.voxel_down_sample(voxel_size)
print(f"下采样后点数: {len(downsampled.points)}")
# 3. 可视化对比(左:原始,右:下采样)
pcd.paint_uniform_color([0.8, 0.2, 0.2]) # 原始点云红色
downsampled.paint_uniform_color([0.1, 0.6, 0.9]) # 下采样蓝色
o3d.visualization.draw_geometries([pcd, downsampled],
window_name="Voxel Downsample",
width=1200, height=600)
运行与验证
- 将上述代码保存为
voxel_downsample.py,在终端执行python voxel_downsample.py。 - 程序会打印下采样前后的点数,并弹出可视化窗口,左右分别显示原始点云(红色)与下采样结果(蓝色)。
- 通过条件:下采样后点数明显少于原始点数(通常减少 50% 以上);可视化中物体轮廓与主要几何特征保持完整,没有出现大面积空洞或形状畸变。
体素大小调整建议
voxel_size 决定下采样强度:值越大,保留的点越少,细节丢失越多。若点云坐标范围在 0~1 之间,0.05 是较稳妥的起始值;若点云尺度更大(如范围 0~100),可尝试 voxel_size=1.0 或更大。实际使用时,建议先观察点云坐标范围,再设置约为最大尺寸的 1/100~1/50 作为体素边长。
上图示意了体素下采样的核心思想:将空间划分为固定大小的立方体网格(体素),每个体素内只保留一个代表点(通常为该体素内所有点的重心),从而用稀疏均匀的点云近似原始密集点云。