4. 深度相机点云预处理
任务目标
对深度相机(如RealSense、Kinect等)获取的原始点云执行三步预处理:直通滤波(裁剪感兴趣区域)、体素降采样(稀疏化)、统计离群点去除(平滑去噪)。输出为可直接用于后续配准或识别的干净点云。
环境依赖
Python 3.8+,安装Open3D(推荐0.17+):
pip install open3d numpy
关键完整代码
import open3d as o3d
import numpy as np
def preprocess_pointcloud(input_path, output_path=None):
"""
对深度相机点云执行:直通滤波 → 体素降采样 → 统计离群点去除
Args:
input_path: 输入点云文件路径(.ply/.pcd)
output_path: 输出路径,None则返回处理结果不保存
Returns:
o3d.geometry.PointCloud: 预处理后的点云
"""
# 1. 读取原始点云
pcd = o3d.io.read_point_cloud(input_path)
if pcd.is_empty():
raise ValueError(f"点云为空或读取失败: {input_path}")
print(f"原始点云点数: {len(pcd.points)}")
# 2. 直通滤波:裁剪工作空间(单位:米,按需调整)
bbox = o3d.geometry.AxisAlignedBoundingBox(
min_bound=np.array([-0.5, -0.5, 0.0]), # x,y,z最小值
max_bound=np.array([0.5, 0.5, 0.8]) # x,y,z最大值
)
pcd_cropped = pcd.crop(bbox)
print(f"直通滤波后点数: {len(pcd_cropped.points)}")
# 3. 体素降采样:体素边长5mm(稀疏化并均匀化密度)
voxel_size = 0.005
pcd_down = pcd_cropped.voxel_down_sample(voxel_size)
print(f"降采样后点数: {len(pcd_down.points)}")
# 4. 统计离群点去除:邻域点数20,标准差阈值1.0
pcd_clean, ind = pcd_down.remove_statistical_outlier(
nb_neighbors=20, std_ratio=1.0
)
print(f"去离群点后点数: {len(pcd_clean.points)}")
# 5. 保存或返回
if output_path:
o3d.io.write_point_cloud(output_path, pcd_clean)
print(f"已保存至: {output_path}")
return pcd_clean
if __name__ == "__main__":
# 使用示例:替换为实际深度相机导出的点云文件
result = preprocess_pointcloud("raw_scene.ply", "clean_scene.ply")
# 可视化验证(取消注释以查看)
# o3d.visualization.draw_geometries([result])
运行与验证
- 准备输入:将深度相机(RealSense D435等)采集的帧保存为
raw_scene.ply,或使用Open3D自带的示例点云测试:
python -c "import open3d as o3d; o3d.data.DemoCropPointCloud().point_cloud_path"
- 执行预处理:将上述代码保存为
preprocess.py,运行:
python preprocess.py
- 通过条件:
- 控制台输出四个点数依次递减(原始→裁剪→降采样→去噪),且最终点数不为0;
- 生成clean_scene.ply文件,用o3d.visualization.draw_geometries打开后,点云边界清晰、无明显漂浮噪声点、密度均匀;
- 若原始点云含超出工作空间的点(如天花板、地面远处),直通滤波后这些点应被移除。
参数调整说明
| 参数 | 位置 | 推荐范围 | 调整依据 |
|---|---|---|---|
| bbox边界 | 直通滤波 | 根据机器人工作空间设定 | 过大保留无关点,过小裁掉目标物体 |
| voxel_size | 降采样 | 0.003~0.01m | 值越大点越稀疏,需保留足够几何特征 |
| nb_neighbors | 去离群点 | 10~50 | 邻域点数越多,对密度变化越不敏感 |
| std_ratio | 去离群点 | 0.5~2.0 | 越小去除越多,过大则保留噪声 |
常见问题
- 输入点云单位:RealSense默认单位米,若数据单位是毫米,需先将坐标除以1000再滤波;
- 点数过少:若降采样后点数不足1000,说明体素尺寸过大或原始点云太稀疏,应减小voxel_size;
- 离群点未去除干净:降低std_ratio至0.5,或增大nb_neighbors至30;
- 实时性要求:若需在线处理,建议将voxel_size调至0.008以上,并限制bbox范围以降低计算量。