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点作为输入,随后执行体素降采样并弹出可视化窗口。

验证判定标准:

  1. 点数变化:控制台输出中,降采样后点数应明显小于5000(体素边长0.005时通常降至约2000~3000点),且减少比例在合理范围(约40%~60%)。
  2. 形状保持:可视化窗口中,红色原始点云与绿色降采样点云叠加显示时,兔子轮廓、耳朵、四肢等几何特征应清晰可辨,无明显空洞或变形。
  3. 参数敏感性:将 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版本兼容。