欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-11-23 10:27:04
三维点云体素降采样(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

相关标签: 三维点云