三维点云(点云体素降采样方法介绍)
程序员文章站
2022-06-20 21:57:17
三维点云体素降采样(Voxel Filter Downsampling)代码参考网址秦乐乐CSDN博客理论参考知乎博主:WALL-E1.方法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_...
三维点云
点云体素降采样(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