1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| # 实现voxel滤波,并加载数据集中的文件进行验证
import argparse import open3d as o3d import os import numpy as np from pyntcloud import PyntCloud
# 功能:对点云进行voxel滤波 # 输入: # point_cloud:输入点云 # leaf_size: voxel尺寸 def voxel_filter(points, leaf_size, method='centroid'): # 降采样后的点云容器 filtered_points = None # 当前使用的点云数据 working_points = points.copy(deep=True) # 过滤器 classifier = get_voxel_frid_classifier(working_points, leaf_size) # 调用方法得到体素编号 working_points['voxel_grid_id'] = working_points.apply(lambda row: classifier(row['x'], row['y'], row['z']), axis=1) # 选用滤波方法-->中心或随机 if method == 'centroid': # 将带有体素编号的点根据‘voxel_grid_id’分组,最后求平均得到后在转换为numpy形式 filtered_points = working_points.groupby(['voxel_grid_id']).mean().to_numpy() elif method == 'random': # 在带有体素编号的点中随机取一个点(sample(1)),在转换为numpy形式 filtered_points = working_points.groupby(['voxel_grid_id']).apply(lambda x: x[['x', 'y', 'z']].sample(1)).to_numpy() # 将降采样后的点return return filtered_points
# 进行体素编号的计算 def get_voxel_frid_classifier(points, leaf_size): (p_min, p_max) = (points.min(), points.max()) (D_x, D_y, D_z) = ( np.ceil((p_max['x'] - p_min['x']) / leaf_size).astype(np.int32), np.ceil((p_max['y'] - p_min['y']) / leaf_size).astype(np.int32), np.ceil((p_max['z'] - p_min['z']) / leaf_size).astype(np.int32) )
def classifier(x, y, z): (i_x, i_y, i_z) = ( np.ceil((x - p_min['x']) / leaf_size).astype(np.int32), np.ceil((y - p_min['y']) / leaf_size).astype(np.int32), np.ceil((z - p_min['z']) / leaf_size).astype(np.int32)) idx = i_x + D_x * i_y + D_y * D_x * i_z return idx
return classifier
def main(file_name): # # 从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_pynt = PyntCloud.from_file(file_name)
# 转成open3d能识别的格式 point_cloud_o3d = point_cloud_pynt.to_instance("open3d", mesh=False) # o3d.visualization.draw_geometries([point_cloud_o3d]) # 显示原始点云
# 调用voxel滤波函数,实现滤波 filtered_cloud = voxel_filter(point_cloud_pynt.points, 10.0,method='random') point_cloud_o3d.points = o3d.utility.Vector3dVector(filtered_cloud) # 显示滤波后的点云 o3d.visualization.draw_geometries([point_cloud_o3d])
def get_arguments(): """ Get command-line arguments """ # init parser: parser = argparse.ArgumentParser("Downsample given point cloud using voxel grid.")
# add required and optional groups: required = parser.add_argument_group('Required')
# add required: required.add_argument( "-i", dest="input", help="Input path of point cloud in ply format.", required=True )
# parse arguments: return parser.parse_args()
if __name__ == '__main__': arguments=get_arguments() main(arguments.input)
|