三维点云(点云体素降采样方法介绍)

2022-08-10,,

三维点云

点云体素降采样(Voxel Filter Downsampling)

1.方法

Centroid 均值采样
Random select 随机采样

2.伪代码流程

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() 

本文地址:https://blog.csdn.net/weixin_41281151/article/details/107125844

《三维点云(点云体素降采样方法介绍).doc》

下载本文的Word格式文档,以方便收藏与打印。