三维点云处理:6 降采样作业

降采样作业:

在这里插入图片描述

# 实现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 #用于维度的累计    
    np.seterr(divide='ignore',invalid='ignore') #忽略除法遇到无效值的问题
    #将h值相同的点放入到同一个grid中,并进行筛选
    for i  in range(len(h_sorted)-1):      #数据点
        if h_sorted[i] == h_sorted[i+1]:   #当前的点与后面的相同,放在同一个volex grid中
            continue
        else:
                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
    for i  in range(len(h_sorted)-1):      #数据点
        if h_sorted[i] == h_sorted[i+1]:   #当前的点与后面的相同,放在同一个volex grid中
            continue
        else:            
            filter_mode == "centroid"    #均值滤波
            point_idx = h_indice[count: i+1]
            filtered_points.append(np.mean(point_cloud[point_idx],axis=0))   #取同一个grid的均值
            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"car_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_1 = o3d.geometry.PointCloud()     #实例化    
    point_cloud_o3d_filter_2 = o3d.geometry.PointCloud()     #实例化

     

    points = np.array(point_cloud_o3d_orign.points)

    # 调用voxel滤波函数,实现滤波
    filtered_cloud_1 = voxel_filter(points, 0.05, "random")   #random
    point_cloud_o3d_filter_1.points = o3d.utility.Vector3dVector(filtered_cloud_1)
    filtered_cloud_2 = voxel_filter(points, 0.05, "centroid")   #centroid 
    point_cloud_o3d_filter_2.points = o3d.utility.Vector3dVector(filtered_cloud_2)
    # 显示滤波前后的点云
    o3d.visualization.draw_geometries([point_cloud_o3d_orign])# 显示原始点云
    o3d.visualization.draw_geometries([point_cloud_o3d_filter_1])
    o3d.visualization.draw_geometries([point_cloud_o3d_filter_2])
if __name__ == '__main__':
    main()


原图:
三维点云处理:6 降采样作业_第1张图片
random:
三维点云处理:6 降采样作业_第2张图片
centroid :
三维点云处理:6 降采样作业_第3张图片

你可能感兴趣的:(三维点云作业,python)