2. 点云降采样
任务目标
对输入点云执行体素栅格降采样(Voxel Grid Downsampling),通过设置合适的体素边长,在显著减少点云数量的同时保持物体主要几何形状特征,并输出降采样前后的点数对比。
环境与依赖
本案例基于 Python 3.8+ 与 Open3D 0.17+ 实现。安装命令:
pip install open3d numpy
关键完整代码
import open3d as o3d
import numpy as np
def voxel_downsample_demo(pcd_path, voxel_size=0.02):
"""
对输入点云执行体素栅格降采样。
参数:
pcd_path: 点云文件路径(支持 .pcd/.ply/.xyz 等格式)
voxel_size: 体素边长(米),需根据点云尺度调整
返回:
(原始点数, 降采样后点数, 降采样点云)
"""
# 读取原始点云
pcd = o3d.io.read_point_cloud(pcd_path)
if pcd.is_empty():
raise ValueError("点云为空,请检查文件路径或格式")
original_points = np.asarray(pcd.points)
original_num = len(original_points)
# 体素栅格降采样
downsampled_pcd = pcd.voxel_down_sample(voxel_size=voxel_size)
downsampled_num = len(np.asarray(downsampled_pcd.points))
# 打印统计信息
print(f"原始点数: {original_num}")
print(f"降采样后点数: {downsampled_num}")
print(f"点数减少比例: {(1 - downsampled_num / original_num) * 100:.2f}%")
return original_num, downsampled_num, downsampled_pcd
if __name__ == "__main__":
# 使用内置示例点云(斯坦福兔子)验证流程
bunny = o3d.data.BunnyMesh()
mesh = o3d.io.read_triangle_mesh(bunny.path)
pcd = mesh.sample_points_uniformly(number_of_points=5000)
# 保存为临时文件以复用主函数(实际使用时直接传入文件路径)
temp_path = "temp_bunny.pcd"
o3d.io.write_point_cloud(temp_path, pcd)
# 设置体素边长:兔子模型尺度约0.1~0.2m,取0.005可保留形状细节
orig_n, down_n, down_pcd = voxel_downsample_demo(temp_path, voxel_size=0.005)
# 可视化对比(左:原始,右:降采样)
pcd_orig = o3d.io.read_point_cloud(temp_path)
pcd_orig.paint_uniform_color([0.8, 0.2, 0.2]) # 红色
down_pcd.paint_uniform_color([0.2, 0.6, 0.2]) # 绿色
o3d.visualization.draw_geometries([pcd_orig, down_pcd])
import os
os.remove(temp_path) # 清理临时文件
运行与验证
运行方式:将上述代码保存为 voxel_downsample.py,直接执行:
python voxel_downsample.py
程序会自动下载斯坦福兔子网格并均匀采样5000点作为输入,随后执行体素降采样并弹出可视化窗口。
验证判定标准:
- 点数变化:控制台输出中,降采样后点数应明显小于5000(体素边长0.005时通常降至约2000~3000点),且减少比例在合理范围(约40%~60%)。
- 形状保持:可视化窗口中,红色原始点云与绿色降采样点云叠加显示时,兔子轮廓、耳朵、四肢等几何特征应清晰可辨,无明显空洞或变形。
- 参数敏感性:将
voxel_size改为0.01重新运行,点数应进一步减少(约500~1000点),但形状仍可辨认;改为0.001时点数几乎不变——这验证了体素大小对密度控制的有效性。
体素大小选择建议
| 点云尺度 | 建议体素边长 | 效果 |
|---|---|---|
| 小物体(如零件,0.1m级) | 0.001~0.005 | 保留精细特征 |
| 中等场景(如桌面物体,1m级) | 0.005~0.02 | 平衡密度与形状 |
| 大场景(如室内扫描,10m级) | 0.02~0.1 | 去除冗余点 |
实际使用时,先估算点云包围盒对角线长度的1%~5%作为初始体素值,再根据点数减少比例与目视效果微调。
常见问题
- 降采样后出现空洞:体素设置过大,导致薄壁结构被完全滤除。应减小体素边长。
- 点数几乎不变:体素远小于点间距,未产生合并效果。应增大体素值。
- 文件读取失败:确认点云文件存在且格式受支持;若为二进制PLY,需确保Open3D版本兼容。