当前位置:   article > 正文

常用的点云预处理算法_点云处理算法

点云处理算法

点云预处理是处理点云数据时的重要部分,其目的是提高点云数据的质量和处理效率。通过去除离群点、减少点云密度和增强特征,可以消除噪声、减少计算量、提高算法的准确性和鲁棒性,从而为后续的点云处理和分析步骤(如配准、分割和重建)提供更高质量的数据基础。

以下是常用的点云预处理算法介绍,内容包括离群点过滤、点云下采样、坐标上采样和特征上采样的数学原理以及Open3D实现代码。

离群点过滤

无效值剔除

无效值剔除是指移除点云中的值或无穷大的值。

数学原理: 假设点云数据集为,其中每个点。无效值剔除的规则可以表示为:

Open3D实现

  1. import open3as o3d
  2. def remove_invalid_points(pcd):
  3.     pcd = pcd.select_by_index(
  4.         np.where(np.isfinite(np.asarray(pcd.points)).all(axis=1))[0]
  5.     )
  6.     return pcd
  7. # 示例
  8. pcd = o3d.io.read_point_cloud("example.ply")
  9. pcd = remove_invalid_points(pcd)
  10. o3d.visualization.draw_geometries([pcd])
统计方法剔除

统计方法剔除利用每个点的邻域统计信息来识别并移除离群点。

数学原理: 计算每个点到其个最近邻点的平均距离,并将该点的平均距离与全局平均距离进行比较。如果某点的平均距离超出某一阈值,则认为该点为离群点。

Open3D实现

  1. def statistical_outlier_removal(pcd, nb_neighbors=20, std_ratio=2.0):
  2.     cl, ind = pcd.remove_statistical_outlier(nb_neighbors=nb_neighbors, std_ratio=std_ratio)
  3.     pcd = pcd.select_by_index(ind)
  4.     return pcd
  5. # 示例
  6. pcd = o3d.io.read_point_cloud("example.ply")
  7. pcd = statistical_outlier_removal(pcd)
  8. o3d.visualization.draw_geometries([pcd])
半径滤波方法剔除

半径滤波方法根据每个点在指定半径内的邻居数量来剔除离群点。

数学原理: 设定一个半径和最小点数阈值。对于每个点,如果其在半径内的邻居数量少于,则认为该点为离群点。

Open3D实现

  1. def radius_outlier_removal(pcd, radius=0.05, min_points=5):
  2.     cl, ind = pcd.remove_radius_outlier(nb_points=min_points, radius=radius)
  3.     pcd = pcd.select_by_index(ind)
  4.     return pcd
  5. # 示例
  6. pcd = o3d.io.read_point_cloud("example.ply")
  7. pcd = radius_outlier_removal(pcd)
  8. o3d.visualization.draw_geometries([pcd])

离群点剔除代码示例:

  1. import open3as o3d
  2. from copy import deepcopy
  3. import numpy as np
  4.  
  5.  
  6. if __name__ == '__main__':
  7.     file_path = 'rabbit.pcd'
  8.     pcd = o3d.io.read_point_cloud(file_path)
  9.     pcd = pcd.uniform_down_sample(50)#每50个点采样一次
  10.     pcd.paint_uniform_color([0.50.50.5])#指定显示为灰色
  11.     print(pcd)
  12.  
  13.     #剔除无效值
  14.     pcd1 = deepcopy(pcd)
  15.     pcd1.paint_uniform_color([001])#指定显示为蓝色
  16.     pcd1.translate((2000)) #整体进行x轴方向平移
  17.     pcd1 = pcd1.remove_non_finite_points(TrueTrue)#剔除无效值
  18.     print(pcd1)
  19.  
  20.     #统计方法剔除
  21.     pcd2 = deepcopy(pcd)
  22.     pcd2.paint_uniform_color([010])#指定显示为蓝色
  23.     pcd2.translate((-2000)) #整体进行x轴方向平移
  24.     res = pcd2.remove_statistical_outlier(200.5)#统计方法剔除
  25.     pcd2 = res[0]#返回点云,和点云索引
  26.     print(pcd2)
  27.  
  28.     #半径方法剔除
  29.     pcd3 = deepcopy(pcd)
  30.     pcd3.paint_uniform_color([100])#指定显示为蓝色
  31.     pcd3.translate((0200)) #整体进行y轴方向平移
  32.     res = pcd3.remove_radius_outlier(nb_points=20, radius=2)#半径方法剔除
  33.     pcd3 = res[0]#返回点云,和点云索引
  34.     print(pcd3)
  35.  
  36.     # # 点云显示
  37.     o3d.visualization.draw_geometries([pcd, pcd1, pcd2, pcd3], #点云列表
  38.                                       window_name="离群点剔除",
  39.                                       point_show_normal=False,
  40.                                       width=800,  # 窗口宽度
  41.                                       height=600)  # 窗口高度

图片

点云下采样

点云下采样的主要目的是减少点云数据的规模,从而降低计算复杂度和存储需求。在实际应用中,点云数据通常包含大量的点,这会占用大量的存储空间并增加处理时间。通过下采样,可以去除冗余点,只保留关键点,既能加速后续处理(如配准、分类、分割等),又能减少内存使用。此外,下采样还能提高算法的鲁棒性,减少噪声影响,使得处理结果更加稳定和可靠。

体素下采样

体素下采样通过将点云划分为固定大小的三维网格,并用每个网格中的点的质心来代表该网格中的所有点。

数学原理: 设定体素网格的大小为,将点云划分为体素网格,每个体素中的点用其质心替代。

其中,为体素的质心,为体素中的点数。

Open3D实现

  1. import open3as o3d
  2. from copy import deepcopy
  3.  
  4.  
  5. if __name__ == '__main__':
  6.     file_path = 'rabbit.pcd'
  7.     pcd = o3d.io.read_point_cloud(file_path)
  8.     pcd.paint_uniform_color([0.50.50.5])#指定显示为灰色
  9.     print(pcd)
  10.  
  11.     pcd1 = deepcopy(pcd)
  12.     pcd1.paint_uniform_color([001])#指定显示为蓝色
  13.     pcd1.translate((2000)) #整体进行x轴方向平移
  14.     pcd1 = pcd1.voxel_down_sample(voxel_size=1)
  15.     print(pcd1)
  16.  
  17.     pcd2 = deepcopy(pcd)
  18.     pcd2.paint_uniform_color([010])#指定显示为绿色
  19.     pcd2.translate((0200)) #整体进行y轴方向平移
  20.     res = pcd2.voxel_down_sample_and_trace(1, min_bound=pcd2.get_min_bound()-0.5, max_bound=pcd2.get_max_bound()+0.5, approximate_class=True)
  21.     pcd2 = res[0]
  22.     print(pcd2)
  23.  
  24.     
  25.     # 点云显示
  26.     o3d.visualization.draw_geometries([pcd, pcd1, pcd2], #点云列表
  27.                                       window_name="体素下采样",
  28.                                       point_show_normal=False,
  29.                                       width=800,  # 窗口宽度
  30.                                       height=600)  # 窗口高度

图片

随机下采样

随机下采样是从点云中随机选取一定比例的点,以减少点云的点数。

数学原理: 设点云数据集为,随机下采样从中选取个点。其中,是从中随机选取的索引。

Open3D实现

  1. import open3as o3d
  2. from copy import deepcopy
  3. import numpy as np
  4.  
  5.  
  6. if __name__ == '__main__':
  7.     file_path = 'rabbit.pcd'
  8.     pcd = o3d.io.read_point_cloud(file_path)
  9.     pcd.paint_uniform_color([0.50.50.5])#指定显示为灰色
  10.     print(pcd)
  11.  
  12.     pcd1 = deepcopy(pcd)
  13.     pcd1.paint_uniform_color([001])#指定显示为蓝色
  14.     pcd1.translate((2000)) #整体进行x轴方向平移
  15.     pcd1 = pcd1.uniform_down_sample(100)#每100个点采样一次
  16.     print(pcd1)
  17.  
  18.     pcd2 = deepcopy(pcd)
  19.     pcd2.paint_uniform_color([010])#指定显示为绿色
  20.     pcd2.translate((0200)) #整体进行y轴方向平移
  21.     pcd2 = pcd2.random_down_sample(0.1)#采1/10的点云
  22.     print(pcd2)
  23.  
  24.     #自定义随机采样
  25.     pcd3 = deepcopy(pcd)
  26.     pcd3.translate((-2000)) #整体进行x轴方向平移
  27.     points = np.array(pcd3.points)
  28.     n = np.random.choice(len(points), 500replace=False) #s随机采500个数据,这种随机方式也可以自己定义
  29.     pcd3.points = o3d.utility.Vector3dVector(points[n])
  30.     pcd3.paint_uniform_color([100])#指定显示为红色
  31.     print(pcd3)
  32.     
  33.     # # 点云显示
  34.     o3d.visualization.draw_geometries([pcd, pcd1, pcd2, pcd3], #点云列表
  35.                         

图片

均匀下采样

均匀下采样是等间距选择点云中的点。

数学原理: 设点云数据集为,均匀下采样每隔个点选择一个点。

Open3D实现

  1. def uniform_downsample(pcd, every_k_points=10):
  2.     pcd = pcd.uniform_down_sample(every_k_points)
  3.     return pcd
  4. # 示例
  5. pcd = o3d.io.read_point_cloud("example.ply")
  6. pcd = uniform_downsample(pcd)
  7. o3d.visualization.draw_geometries([pcd])
最远点采样

最远点采样是一种迭代方法,每次选择距离当前已选点集最远的点。

数学原理: 初始化点集为随机选择的一个点,每次迭代选择距离当前已选点集最远的点:

Open3D实现

  1. import open3as o3d
  2. from copy import deepcopy
  3. import numpy as np
  4.  
  5. def farthest_point_sample(point, npoint):
  6.     """
  7.     Input:
  8.         xyz: pointcloud data, [N, D]
  9.         npoint: number of samples
  10.     Return:
  11.         centroids: sampled pointcloud index, [npoint, D]
  12.     """
  13.     N, D = point.shape
  14.     xyz = point[:,:3]
  15.     centroids = np.zeros((npoint,))
  16.     distance = np.ones((N,)) * 1e10
  17.     farthest = np.random.randint(0, N)
  18.     for i in range(npoint):
  19.         centroids[i] = farthest
  20.         centroid = xyz[farthest, :]
  21.         dist = np.sum((xyz - centroid) ** 2, -1)
  22.         mask = dist < distance
  23.         distance[mask] = dist[mask]
  24.         farthest = np.argmax(distance, -1)
  25.     point = point[centroids.astype(np.int32)]
  26.     return point
  27. if __name__ == '__main__':
  28.     file_path = 'rabbit.pcd'
  29.     pcd = o3d.io.read_point_cloud(file_path)
  30.     pcd.paint_uniform_color([0.50.50.5])#指定显示为灰色
  31.     print(pcd)
  32.  
  33.     pcd1 = deepcopy(pcd)
  34.     pcd1.translate((2000)) #整体进行x轴方向平移
  35.     points = np.array(pcd1.points)
  36.     points = farthest_point_sample(points, 500)
  37.     pcd1 = o3d.geometry.PointCloud()
  38.     pcd1.points = o3d.utility.Vector3dVector(points)
  39.     pcd1.paint_uniform_color([001])#指定显示为蓝色
  40.     print(pcd1)
  41.  
  42.     # # 点云显示
  43.     o3d.visualization.draw_geometries([pcd, pcd1], #点云列表
  44.                                       window_name="最远点采样",
  45.                                       point_show_normal=False,
  46.                                       width=800,  # 窗口宽度
  47.                                       height=600)  # 窗口高度
  48.  

图片

坐标上采样

点云上采样的目的是增加点云的密度,以提高其分辨率和细节表现。在许多应用中,特别是三维重建和表面细化时,原始点云的分辨率可能不足,导致重建结果不够精细或存在明显的缺陷。通过上采样,可以插值生成更多的点,使得点云更密集,从而更好地捕捉物体的几何细节,提升最终的三维模型质量。这对于需要高精度、高分辨率数据的任务(如精细的表面重建、细节检测等)尤为重要。

插值法

插值法是通过插值计算新增点的坐标。

数学原理: 常用的插值方法包括线性插值、双线性插值、三次样条插值等。以线性插值为例,两个点和之间新增点:

其中,为插值系数,取值范围为[0, 1]。

Open3D实现

  1. import open3as o3d
  2. from copy import deepcopy
  3. if __name__ == '__main__':
  4.     file_path = 'rabbit.pcd'
  5.     pcd = o3d.io.read_point_cloud(file_path)
  6.     pcd.paint_uniform_color([0.50.50.5])  # 指定显示为灰色
  7.     print(pcd)
  8.     pcd1 = deepcopy(pcd)
  9.     pcd1.paint_uniform_color([001])  # 指定显示为蓝色
  10.     pcd1.translate((2000))  # 整体进行x轴方向平移
  11.     pcd1 = pcd1.voxel_down_sample(voxel_size=1)
  12.     print(pcd1)
  13.     mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd1, alpha=2)
  14.     pcd2 = mesh.sample_points_poisson_disk(number_of_points=3000, init_factor=5)
  15.     pcd2.paint_uniform_color([010])  # 指定显示为绿色
  16.     pcd2.translate((-4000))  # 整体进行x轴方向平移
  17.     print(pcd2)
  18.     o3d.visualization.draw_geometries([pcd, pcd1, pcd2],  # 点云列表
  19.                                       window_name="点云上采样",
  20.                                       point_show_normal=False,
  21.                                       width=800,  # 窗口宽度
  22.                                       height=600)  # 窗口高度

图片

特征上采样

最近邻插值

最近邻插值是通过选择最近邻的特征值作为新增点的特征值。

数学原理: 设已知点云的特征为,新增点的特征值通过最近邻点的特征值确定:,其中,为距离最近的点。

Open3D实现

  1. from sklearn.neighbors import NearestNeighbors
  2. def nearest_neighbor_interpolation(pcd, features, num_points):
  3.     points = np.asarray(pcd.points)
  4.     new_points = np.array([]).reshape(03)
  5.     new_features = np.array([]).reshape(0, features.shape[1])
  6.     for i in range(len(points) - 1):
  7.         for t in np.linspace(01, num_points):
  8.             new_point = points[i] + t * (points[i + 1] - points[i])
  9.             new_points = np.vstack((new_points, new_point))
  10.     nn = NearestNeighbors(n_neighbors=1).fit(points)
  11.     distances, indices = nn.kneighbors(new_points)
  12.     new_features = features[indices.flatten()]
  13.     pcd_interpolated = o3d.geometry.PointCloud()
  14.     pcd_interpolated.points = o3d.utility.Vector3dVector(new_points)
  15.     return pcd_interpolated, new_features
  16. # 示例
  17. pcd = o3d.io.read_point_cloud("example.ply")
  18. features = np.random.rand(len(pcd.points), 3)  # 假设特征是随机生成的
  19. pcd, new_features = nearest_neighbor_interpolation(pcd, features, num_points=10)
  20. o3d.visualization.draw_geometries([pcd])

以上内容总结自网络,如有帮助欢迎关注与转发,我们下次再见!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/928806
推荐阅读
相关标签
  

闽ICP备14008679号