Skip to content

点云离群点去除

在使用扫描设备采集数据时,所得点云往往含有需要去除的噪声和伪影(artifacts)。本教程介绍 Open3D 的离群点去除(outlier removal)功能。

加载一个点云,并使用 voxel_downsample 进行降采样。

print("Load a ply point cloud, print it, and render it")
sample_pcd_data = o3d.data.PCDPointCloud()
pcd = o3d.io.read_point_cloud(sample_pcd_data.path)
o3d.visualization.draw_geometries([pcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
print("Downsample the point cloud with a voxel of 0.02")
voxel_down_pcd = pcd.voxel_down_sample(voxel_size=0.02)
o3d.visualization.draw_geometries([voxel_down_pcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])

tutorial_geometry_pointcloud_outlier_removal_3_1.png tutorial_geometry_pointcloud_outlier_removal_3_3.png

输出:

Load a ply point cloud, print it, and render it
Downsample the point cloud with a voxel of 0.02

此外,也可以使用 uniform_down_sample,通过每隔 n 个点采集一个点的方式对点云进行降采样。

print("Every 5th points are selected")
uni_down_pcd = pcd.uniform_down_sample(every_k_points=5)
o3d.visualization.draw_geometries([uni_down_pcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])

tutorial_geometry_pointcloud_outlier_removal_5_1.png

输出:

Every 5th points are selected

下面的辅助函数使用 select_by_index,它接收一个二值掩码,仅输出被选中的点。被选中的点和未被选中的点会被分别可视化。

def display_inlier_outlier(cloud, ind):
inlier_cloud = cloud.select_by_index(ind)
outlier_cloud = cloud.select_by_index(ind, invert=True)
print("Showing outliers (red) and inliers (gray): ")
outlier_cloud.paint_uniform_color([1, 0, 0])
inlier_cloud.paint_uniform_color([0.8, 0.8, 0.8])
o3d.visualization.draw_geometries([inlier_cloud, outlier_cloud],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])

remove_statistical_outlier(统计离群点去除)会移除那些与自身邻居的距离相对于整个点云平均水平而言更远的点。它接收两个输入参数:

  • nb_neighbors,指定在计算给定点的平均距离时考虑多少个邻居。
  • std_ratio,允许根据整个点云平均距离的标准差来设定阈值水平。该数值越低,滤波就越激进。
print("Statistical oulier removal")
cl, ind = voxel_down_pcd.remove_statistical_outlier(nb_neighbors=20,
std_ratio=2.0)
display_inlier_outlier(voxel_down_pcd, ind)

tutorial_geometry_pointcloud_outlier_removal_9_1.png

输出:

Statistical oulier removal
Showing outliers (red) and inliers (gray):

remove_radius_outlier(半径离群点去除)会移除那些在以其为中心、给定半径的球体内邻居数量过少的点。可以通过两个参数来针对你的数据调整该滤波器:

  • nb_points,用于选取球体内应包含的最少点数。
  • radius,用于定义统计邻居时所使用球体的半径。
print("Radius oulier removal")
cl, ind = voxel_down_pcd.remove_radius_outlier(nb_points=16, radius=0.05)
display_inlier_outlier(voxel_down_pcd, ind)

tutorial_geometry_pointcloud_outlier_removal_11_1.png

输出:

Radius oulier removal
Showing outliers (red) and inliers (gray):