3. 点云去噪

任务目标

使用统计滤波(Statistical Outlier Removal)去除点云中的稀疏离群点噪声,调整邻域点数与标准差阈值参数,通过可视化对比和定量指标评估去噪质量。

环境依赖

Python 3.8+,安装 open3d 与 numpy:

pip install open3d numpy

实现代码

以下代码生成含噪声的合成点云(球面点+随机离群点),执行统计滤波,并输出去噪前后的点云文件与质量指标:

import open3d as o3d
import numpy as np

# 1. 生成合成点云:球面点 + 稀疏离群噪声
np.random.seed(42)
theta = np.random.uniform(0, np.pi, 2000)
phi = np.random.uniform(0, 2 * np.pi, 2000)
r = 1.0
sphere = np.stack([
    r * np.sin(theta) * np.cos(phi),
    r * np.sin(theta) * np.sin(phi),
    r * np.cos(theta)
], axis=1)

# 添加少量真实表面噪声(小幅偏移)
surface_noise = np.random.normal(0, 0.01, sphere.shape)
sphere += surface_noise

# 添加离群点(均匀分布在球外区域)
n_outliers = 100
outliers = np.random.uniform(-2, 2, (n_outliers, 3))

cloud_raw = np.vstack([sphere, outliers])
pcd_raw = o3d.geometry.PointCloud()
pcd_raw.points = o3d.utility.Vector3dVector(cloud_raw)

# 2. 统计滤波去噪
pcd_clean, ind = pcd_raw.remove_statistical_outlier(
    nb_neighbors=20,      # 邻域点数
    std_ratio=2.0         # 标准差倍数阈值
)

# 3. 保存结果
o3d.io.write_point_cloud("raw.pcd", pcd_raw)
o3d.io.write_point_cloud("clean.pcd", pcd_clean)

# 4. 定量评估
total = len(cloud_raw)
removed = total - len(pcd_clean)
print(f"原始点数: {total}")
print(f"去除点数: {removed}")
print(f"去除比例: {removed / total:.2%}")

# 已知真实标签(前2000为表面点,后100为离群点)
labels = np.array([1]*2000 + [0]*100)  # 1=内点, 0=离群点
pred = np.zeros(total, dtype=int)
pred[ind] = 1  # 保留的点标记为1

tp = np.sum((pred == 1) & (labels == 1))
fp = np.sum((pred == 1) & (labels == 0))
fn = np.sum((pred == 0) & (labels == 1))
precision = tp / (tp + fp) if (tp + fp) > 0 else 0
recall = tp / (tp + fn) if (tp + fn) > 0 else 0
f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0
print(f"精确率: {precision:.3f}")
print(f"召回率: {recall:.3f}")
print(f"F1分数: {f1:.3f}")

运行与可视化验证

  1. 运行脚本后,当前目录生成 raw.pcd 与 clean.pcd。
  2. 执行以下命令可视化对比去噪效果:
python -c "import open3d as o3d; p=o3d.io.read_point_cloud('raw.pcd'); o3d.visualization.draw_geometries([p])"
python -c "import open3d as o3d; p=o3d.io.read_point_cloud('clean.pcd'); o3d.visualization.draw_geometries([p])"

观察原始点云中球体外部存在明显离散点,去噪后这些点被移除,球面结构保持完整。

判定标准

  • 控制台输出的去除比例约为 4%~5%(100/2100),F1分数应高于 0.95,表明离群点被有效识别且表面点基本保留。
  • 可视化中 clean.pcd 的球体表面无明显空洞或变形,外部无残留离群点。

参数调整说明

增大 nb_neighbors 会使滤波更保守(去除更少点);减小 std_ratio 会提高敏感度(去除更多点)。实际应用中可对真实扫描点云先可视化,再根据噪声密度迭代调整这两个参数,以表面细节保留与噪声清除的平衡为准。