zoukankan      html  css  js  c++  java
  • 点云下采样2

    来源:https://blog.csdn.net/weixin_41281151/article/details/107125844

    点云体素降采样(Voxel Filter Downsampling)
    代码参考网址秦乐乐CSDN博客
    理论参考知乎博主:WALL-E

    1.方法
    Centroid 均值采样
    Random select 随机采样


    2.伪代码流程

    注解:

    第4步是计算没一个点的体素索引。
    3.代码编写
    step1 计算边界值

    #step1 计算边界点
    x_max, y_max, z_max = np.amax(point_cloud,axis=0) #计算 x,y,z三个维度的最值
    x_min, y_min, z_min = np.amin(point_cloud, axis=0)

    step2 确定体素的尺寸

    #step2 确定体素的尺寸
    size_r = leaf_size

    step3 计算每个 volex的维度,即在每个维度上的体素的个数。

    #step3 计算每个 volex的维度
    Dx = (x_max - x_min)/size_r +1
    Dy = (y_max - y_min)/size_r +1
    Dz = (z_max - z_min)/size_r +1

    step4 计算每个点在volex grid内每一个维度的值,即计算每个点属于哪个体素,亦即计算每个点的体素的索引。

    #step4 计算每个点在volex grid内每一个维度的值
    h = list()
    for i in range(len(point_cloud)):
    Dx = (x_max - x_min)/size_r
    Dy = (y_max - y_min)/size_r
    Dz = (z_max - z_min)/size_r
    h.append(hx + hy*Dx + hz*Dx*Dy)

    step5 对h值进行排序

    h = np.array(h)
    h_indice = np.argsort(h) #提取索引
    h_sorted = h[h_indice] #升序

    将h值相同的点放入到同一个grid中,并进行筛选,并区分random和centroid两种滤波方式

    count = 0 #用于维度的累计
    #将h值相同的点放入到同一个grid中,并进行筛选
    for i in range(len(h_sorted)-1): #0-19999个数据点
    if h_sorted[i] == h_sorted[i+1]: #当前的点与后面的相同,放在同一个volex grid中
    continue
    else:
    if(filter_mode == "centroid"): #均值滤波
    point_idx = h_indice[count: i+1]
    filtered_points.append(np.mean(point_cloud[point_idx],axis=0)) #取同一个grid的均值
    count = i
    elif(filter_mode == "random"): #随机滤波
    point_idx = h_indice[count: i+1]
    random_points = random.choice(point_cloud[point_idx])
    filtered_points.append(random_points)
    count = i

    调用

    # 调用voxel滤波函数,实现滤波
    filtered_cloud = voxel_filter(points, 0.05, "random") #centroid or random
    point_cloud_o3d_filter.points = o3d.utility.Vector3dVector(filtered_cloud)

    效果图

    原点云图在open3d中展示如下

    random随机降采样效果如下

    centroid随机降采样效果如下

    整体对比


    完整代码
    注意:数据集放在相应运行的目录下

    # 实现voxel滤波,并加载数据集中的文件进行验证
    
    import open3d as o3d
    import os
    import numpy as np
    from pyntcloud import PyntCloud
    import matplotlib.pyplot as plt
    import random
    from pandas import DataFrame
    
    # matplotlib显示点云函数
    def Point_Cloud_Show(points):
    fig = plt.figure(dpi=150)
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(points[:, 0], points[:, 1], points[:, 2], cmap='spectral', s=2, linewidths=0, alpha=1, marker=".")
    plt.title('Point Cloud')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    plt.show()
    
    # 二维点云显示函数
    def Point_Show(pca_point_cloud):
    x = []
    y = []
    pca_point_cloud = np.asarray(pca_point_cloud)
    for i in range(10000):
    x.append(pca_point_cloud[i][0])
    y.append(pca_point_cloud[i][1])
    plt.scatter(x, y)
    plt.show()
    
     
    
    # 功能:对点云进行voxel滤波
    # 输入:
    # point_cloud:输入点云
    # leaf_size: voxel尺寸
    def voxel_filter(point_cloud, leaf_size,filter_mode):
    filtered_points = []
    # 作业3
    # 屏蔽开始
    #step1 计算边界点
    x_max, y_max, z_max = np.amax(point_cloud,axis=0) #计算 x,y,z三个维度的最值
    x_min, y_min, z_min = np.amin(point_cloud, axis=0)
    #step2 确定体素的尺寸
    size_r = leaf_size
    #step3 计算每个 volex的维度
    Dx = (x_max - x_min)/size_r
    Dy = (y_max - y_min)/size_r
    Dz = (z_max - z_min)/size_r
    #step4 计算每个点在volex grid内每一个维度的值
    h = list()
    for i in range(len(point_cloud)):
    hx = np.floor((point_cloud[i][0] - x_min)/size_r)
    hy = np.floor((point_cloud[i][1] - y_min)/size_r)
    hz = np.floor((point_cloud[i][2] - z_min)/size_r)
    h.append(hx + hy*Dx + hz*Dx*Dy)
    #step5 对h值进行排序
    h = np.array(h)
    h_indice = np.argsort(h) #提取索引
    h_sorted = h[h_indice] #升序
    count = 0 #用于维度的累计
    #将h值相同的点放入到同一个grid中,并进行筛选
    for i in range(len(h_sorted)-1): #0-19999个数据点
    if h_sorted[i] == h_sorted[i+1]: #当前的点与后面的相同,放在同一个volex grid中
    continue
    else:
    if(filter_mode == "centroid"): #均值滤波
    point_idx = h_indice[count: i+1]
    filtered_points.append(np.mean(point_cloud[point_idx],axis=0)) #取同一个grid的均值
    count = i
    elif(filter_mode == "random"): #随机滤波
    point_idx = h_indice[count: i+1]
    random_points = random.choice(point_cloud[point_idx])
    filtered_points.append(random_points)
    count = i
    
    # 屏蔽结束
    
    # 把点云格式改成array,并对外返回
    filtered_points = np.array(filtered_points, dtype=np.float64)
    return filtered_points
    
    def main():
    # # 从ModelNet数据集文件夹中自动索引路径,加载点云
    # cat_index = 10 # 物体编号,范围是0-39,即对应数据集中40个物体
    # root_dir = '/Users/renqian/cloud_lesson/ModelNet40/ply_data_points' # 数据集路径
    # cat = os.listdir(root_dir)
    # filename = os.path.join(root_dir, cat[cat_index],'train', cat[cat_index]+'_0001.ply') # 默认使用第一个点云
    # point_cloud_pynt = PyntCloud.from_file(file_name)
    
    # 加载自己的点云文件
    point_cloud_raw = np.genfromtxt(r"person_0001.txt", delimiter=",")
    point_cloud_raw = DataFrame(point_cloud_raw[:,0:3]) # 为 xyz的 N*3矩阵
    point_cloud_raw.columns = ['x', 'y', 'z'] # 给选取到的数据 附上标题
    point_cloud_pynt = PyntCloud(point_cloud_raw) # 将points的数据 存到结构体中
    
    point_cloud_o3d_orign = point_cloud_pynt.to_instance("open3d", mesh=False) # to_instance实例化
    point_cloud_o3d_filter = o3d.geometry.PointCloud() #实例化
    
    # o3d.visualization.draw_geometries([point_cloud_o3d]) # 显示原始点云
    
    points = np.array(point_cloud_o3d_orign.points)
    
    # 调用voxel滤波函数,实现滤波
    filtered_cloud = voxel_filter(points, 0.05, "centroid") #centroid or random
    point_cloud_o3d_filter.points = o3d.utility.Vector3dVector(filtered_cloud)
    # 显示滤波前后的点云
    o3d.visualization.draw_geometries([point_cloud_o3d_orign])
    o3d.visualization.draw_geometries([point_cloud_o3d_filter])
    if __name__ == '__main__':
    main()
  • 相关阅读:
    《《《Postman 的官网下转
    《《《Springboot 配置 application.yml 连接MySQL数据库
    《《《MyBatis-Plus完成可用项目(通过测试可以连接数据库并返回数据(可以当作开发模板使用))
    《《《spring boot配置文件application.yml出现的异常信息:(java.lang.IllegalStateException: Failed to load property source from location 'classpath:/application.yml')
    《《《转载 Intellij IDEA 导入Maven项目
    start.spring.io访问不了,导致springboot项目创建不起来(Initialization failed for 'https://start.spring.io' Please check URL, network and proxy settings. Error mes...)
    《《《MyBatis-Plus入门 视频学习笔记
    在pom.xml中查看引入关系图
    《《《如何建立局域网共享文件夹(怎样通过IP地址共享文件夹(同一个局域网下))
    JS跨域问题及其解决办法
  • 原文地址:https://www.cnblogs.com/yibeimingyue/p/15592108.html
Copyright © 2011-2022 走看看