Voxel_DownSampling

该代码来自于AlexGeControl,如果侵犯到您的权益,我会删除文章
使用体素降采样点云数据

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)

感谢您的阅读。 🙏 关于转载请看这里