自学内容网 自学内容网

点云采样方法

一、代码

Python

import open3d as o3d
import numpy as np
import random
import math


# 方法一:体素格下采样
def voxel_cell_downsampling(point, voxel=10):
    point = point.voxel_down_sample(voxel)
    return point


# 方法二:随机下采样
def random_downsampling(point, size=20):
    # 获取点云中点的数量
    num_points = np.asarray(point.points).shape[0]
    # 随机选取一半的点进行下采样
    indices = np.random.choice(num_points, size=num_points // size, replace=False)
    point = point.select_by_index(indices)
    return point


# 方法三:最远点下采样
def farthest_point_downsampling(point, v=1000, batch=1):
    points = np.asarray(point.points)
    dump = np.zeros((v, 3))
    ran_points = math.floor(len(points) / batch)
    ran_dump = math.floor(v / batch)
    distance = np.ones((ran_points,)) * 1e10
    for j in range(batch):
        further = random.randint(0, ran_points - 1)
        pointsN = points[(j * ran_points):((j + 1) * ran_points), :]
        dump1 = dump[j * ran_dump:(j + 1) * ran_dump, :]
        for i in range(ran_dump):
            dump1[i] = pointsN[further]
            keypoint = pointsN[further, :]
            dis = np.sqrt(np.sum((pointsN - keypoint) ** 2, axis=1))
            mask = dis < distance
            distance[mask] = dis[mask]
            further = np.argmax(distance)
        dump[j * ran_dump:(j + 1) * ran_dump, :] = dump1
    new_pointcloud = o3d.geometry.PointCloud()
    new_pointcloud.points = o3d.utility.Vector3dVector(dump)
    return new_pointcloud


def view_show(point1, point2):
    # 关键点绿色
    point1.paint_uniform_color([0, 1, 0])
    # 点云红色
    point2.paint_uniform_color([1, 0, 0])
    # 可视化
    vis = o3d.visualization.Visualizer()
    vis.create_window(window_name="GICP", width=1200, height=1200)

    # 设置背景颜色
    vis.get_render_option().background_color = [0, 0, 0]  # 白色背景

    # 添加点云到Visualizer
    vis.add_geometry(point1)
    vis.add_geometry(point2)

    # 运行可视化循环
    vis.run()
    vis.destroy_window()


if __name__ == "__main__":
    # 读取点云
    scene = o3d.io.read_point_cloud("data/pig_view1.pcd")
    target = o3d.io.read_point_cloud("data/pig_view2.pcd")

    # scene = voxel_cell_downsampling(scene)
    # target = voxel_cell_downsampling(target)

    # scene = random_downsampling(scene)
    # target = random_downsampling(target)

    scene = farthest_point_downsampling(scene)
    target = farthest_point_downsampling(target)

    # 可视化关键点和原点云
    view_show(scene, target)

关键代码解析:

# 方法一:体素格下采样
def voxel_cell_downsampling(point, voxel=10):
    point = point.voxel_down_sample(voxel)
    return point


# 方法二:随机下采样
def random_downsampling(point, size=20):
    # 获取点云中点的数量
    num_points = np.asarray(point.points).shape[0]
    # 随机选取一半的点进行下采样
    indices = np.random.choice(num_points, size=num_points // size, replace=False)
    point = point.select_by_index(indices)
    return point

1. 体素格下采样

  • 方法原理: 将点云划分为体素格(Voxel Grid),然后在每个体素格中保留一个代表性的点,其他点被丢弃。

  • 参数设置:

    • point:输入的点云数据。
    • voxel:体素格的大小,用于控制下采样后点云的密度。体素格越小,下采样后的点云越稀疏。
  • 影响:

    • voxel 参数的大小会直接影响下采样后点云的密度。较小的 voxel 值会导致更多的点被保留,点云密度更高;较大的 voxel 值会导致更多的点被丢弃,点云密度更低。

2. 随机下采样

  • 方法原理: 随机选择一定数量的点作为采样点,其他点被丢弃。

  • 参数设置:

    • point:输入的点云数据。
    • size:采样点的数量,用于控制下采样后点云的密度。选择更大的 size 将保留更多的点,点云密度更高;选择更小的 size 将丢弃更多的点,点云密度更低。
  • 影响:

    • size 参数的大小会直接影响下采样后点云的密度。较大的 size 值会导致更多的点被保留,点云密度更高;较小的 size 值会导致更多的点被丢弃,点云密度更低。

参数设置建议:

  • 对于体素格下采样,可以通过调整 voxel 的大小来控制点云的密度,根据需要选择合适的值。
  • 对于随机下采样,可以通过调整 size 的大小来控制点云的密度,根据需要选择合适的值。

def farthest_point_downsampling(point, v=1000, batch=1):
    points = np.asarray(point.points)
    dump = np.zeros((v, 3))
    ran_points = math.floor(len(points) / batch)
    ran_dump = math.floor(v / batch)
    distance = np.ones((ran_points,)) * 1e10
    for j in range(batch):
        further = random.randint(0, ran_points - 1)
        pointsN = points[(j * ran_points):((j + 1) * ran_points), :]
        dump1 = dump[j * ran_dump:(j + 1) * ran_dump, :]
        for i in range(ran_dump):
            dump1[i] = pointsN[further]
            keypoint = pointsN[further, :]
            dis = np.sqrt(np.sum((pointsN - keypoint) ** 2, axis=1))
            mask = dis < distance
            distance[mask] = dis[mask]
            further = np.argmax(distance)
        dump[j * ran_dump:(j + 1) * ran_dump, :] = dump1
    new_pointcloud = o3d.geometry.PointCloud()
    new_pointcloud.points = o3d.utility.Vector3dVector(dump)
    return new_pointcloud

这本来是最远点采样,感觉速度有点慢,所以把点云分成几组进行最远点采样,最后合起来,效果肯定没有整体来的好,batch=1就是正常的最远点采样 

  1. 将输入的点云数据转换为 NumPy 数组。
  2. 创建一个零填充的数组 dump,用于存储下采样后的点云数据。
  3. 计算每个批次的点数 ran_points,以及每个批次下采样后的点数 ran_dump
  4. 初始化一个距离数组 distance,用于存储每个点到已选择点的最小距离。
  5. 对每个批次进行迭代:
    • 随机选择一个起始点作为初始中心点 further
    • 获取当前批次的点云数据 pointsN
    • 初始化一个数组 dump1,用于存储当前批次下采样后的点云数据。
    • 对每个点进行迭代:
      • 将当前中心点添加到 dump1 中。
      • 计算每个点到当前中心点的距离。
      • 更新距离数组 distance,保留每个点到已选择点的最小距离。
      • 选择下一个中心点,其为距离数组中距离最远的点。
    • 将当前批次下采样后的点云数据 dump1 存储到整体下采样结果数组 dump 中。
  6. 将下采样后的点云数据转换为 Open3D 点云对象并返回。

参数说明:

  • point:输入的点云数据。
  • v:期望的下采样后点云的总点数。默认为 1000。
  • batch:用于控制迭代的批次数量。默认为 1。

参数设置建议:

  • v 参数控制下采样后点云的总点数,可以根据需要调整。
  • batch 参数影响了算法的迭代次数,更大的值可能会增加计算时间,但可能会提高下采样的效果,尤其是当输入点云较大时。

结果:

采样前

 体素格下采样

随机下采样

 

最远点采样

 

调整了batch=5后

 


原文地址:https://blog.csdn.net/qq_58060770/article/details/136404836

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!