
本教程详细阐述了如何在3d网格中对给定盒子进行高效的内部点采样。通过利用numpy库的`np.mgrid`函数,我们将展示一种简洁且向量化的方法,以指定步长生成包含(x, y, z)坐标及对应标签的采样点集合。这种方法显著简化了代码并提升了处理多个3d盒子的效率,适用于需要大规模空间数据采样的场景。
在处理3D空间数据时,我们经常需要对特定区域(例如由一组坐标定义的盒子)进行均匀采样。这在计算机图形学、物理模拟、机器学习特征提取等领域尤为常见。本文将深入探讨如何使用Python的NumPy库,特别是np.mgrid函数,高效地从3D盒子内部提取具有指定步长的采样点,并为每个点关联其所属盒子的标签。
假设我们有一个包含n个3D盒子的数组,每个盒子由其8个顶点定义。每个顶点是一个4D坐标(x, y, z, l),其中(x, y, z)表示空间位置,l是一个整数标签(例如,表示物体类型)。
例如,一个盒子的数据结构可能如下所示:
boxes.shape = (n, 8, 4) # n个盒子,每个盒子8个顶点,每个顶点4个维度(x, y, z, label)
# 示例:第一个盒子的数据
boxes[0] = [
[0.0, 0.0, 0.0, 1],
[2.0, 0.0, 0.0, 1],
[2.0, 3.0, 0.0, 1],
[0.0, 3.0, 0.0, 1],
[0.0, 0.0, 1.0, 1],
[2.0, 0.0, 1.0, 1],
[2.0, 3.0, 1.0, 1],
[0.0, 3.0, 1.0, 1]
]我们的目标是,给定一个step_size(例如0.01米),在每个盒子的内部以该步长均匀地采样点,并为每个采样点附上盒子的标签。最终输出应是一个包含所有采样点及其对应标签的集合。
一种常见的直观方法是:
其大致代码结构如下:
import numpy as np # 假设 boxes 已定义 # mins = np.min(boxes[:, :, :3], axis=1) # 获取每个盒子的x,y,z最小值 # maxs = np.max(boxes[:, :, :3], axis=1) # 获取每个盒子的x,y,z最大值 # labels = boxes[:, 0, 3].astype(int) # 假设每个盒子的标签一致 # sampled_points_list = [] # sampled_labels_list = [] # step_size = 0.01 # for i in range(boxes.shape[0]): # # 计算每个维度上的点数 # num_points_x = int(np.floor((maxs[i, 0] - mins[i, 0]) / step_size)) # num_points_y = int(np.floor((maxs[i, 1] - mins[i, 1]) / step_size)) # num_points_z = int(np.floor((maxs[i, 2] - mins[i, 2]) / step_size)) # # 使用复数步长确保包含终点 # x_coords, y_coords, z_coords = np.mgrid[ # mins[i, 0]:maxs[i, 0]:(num_points_x + 1)*1j, # +1 to ensure endpoint is included if needed # mins[i, 1]:maxs[i, 1]:(num_points_y + 1)*1j, # mins[i, 2]:maxs[i, 2]:(num_points_z + 1)*1j # ] # points = np.vstack([x_coords.ravel(), y_coords.ravel(), z_coords.ravel()]).T # current_labels = np.repeat(labels[i], points.shape[0]) # sampled_points_list.append(points) # sampled_labels_list.append(current_labels) # # sampled_points = np.vstack(sampled_points_list) # # sampled_labels = np.concatenate(sampled_labels_list)
这种方法虽然可行,但在计算每个维度上的点数以及处理标签重复时,代码略显繁琐。更重要的是,np.mgrid的复数步长用法需要我们预先计算点数,这增加了复杂性。
NumPy的np.mgrid函数提供了一种更简洁的切片语法start:stop:step,可以直接指定步长来生成等间隔的数值序列。通过巧妙地利用这一特性,我们可以将坐标生成和标签关联集成到单个np.mgrid调用中,从而实现更高效、更简洁的采样。
核心思想是:将盒子的标签作为np.mgrid的第四个维度。由于标签对于盒子内部的所有采样点都是一致的,我们可以将其范围设置为label:label+1,这样np.mgrid将只在该维度生成一个值,即盒子的标签。
对于单个盒子box及其标签label,采样代码如下:
import numpy as np
# 假设 box 是一个形状为 (8, 4) 的NumPy数组,label 是该盒子的整数标签
# step_size 是采样步长
# 获取盒子的 x, y, z 坐标范围
min_x, min_y, min_z = np.min(box[:, :3], axis=0)
max_x, max_y, max_z = np.max(box[:, :3], axis=0)
# 使用 np.mgrid 直接生成包含标签的采样点
# 注意:np.mgrid 的 start:stop:step 语法不包含 stop 值
sampled_points_with_labels = np.mgrid[
min_x:max_x:step_size,
min_y:max_y:step_size,
min_z:max_z:step_size,
label:label + 1 # 标签维度,生成一个值
].reshape(4, -1).T代码解析:
这种方法极大地简化了代码,并充分利用了NumPy的向量化能力,对于大规模数据处理具有显著的性能优势。
现在,我们将上述优化方法应用于处理多个3D盒子。
import numpy as np
# 示例输入数据:包含两个盒子
boxes = np.array([
[ # 第一个盒子,标签为1
[0.0, 0.0, 0.0, 1], [2.0, 0.0, 0.0, 1], [2.0, 3.0, 0.0, 1], [0.0, 3.0, 0.0, 1],
[0.0, 0.0, 1.0, 1], [2.0, 0.0, 1.0, 1], [2.0, 3.0, 1.0, 1], [0.0, 3.0, 1.0, 1]
],
[ # 第二个盒子,标签为2
[10.0, 10.0, 10.0, 2], [11.0, 10.0, 10.0, 2], [11.0, 12.0, 10.0, 2], [10.0, 12.0, 10.0, 2],
[10.0, 10.0, 11.0, 2], [11.0, 10.0, 11.0, 2], [11.0, 12.0, 11.0, 2], [10.0, 12.0, 11.0, 2]
]
])
step_size = 0.5 # 采样步长
all_sampled_points = [] # 用于收集所有盒子的采样点
# 遍历每一个盒子
for i in range(boxes.shape[0]):
current_box_coords = boxes[i, :, :3] # 提取当前盒子的x,y,z坐标
# 假设盒子的标签在所有顶点中都是一致的,取第一个顶点的标签即可
current_box_label = int(boxes[i, 0, 3])
# 计算当前盒子的x,y,z坐标范围
min_x, min_y, min_z = np.min(current_box_coords, axis=0)
max_x, max_y, max_z = np.max(current_box_coords, axis=0)
# 使用优化方法生成采样点,包含标签作为第四维
sampled_box_points = np.mgrid[
min_x:max_x:step_size,
min_y:max_y:step_size,
min_z:max_z:step_size,
current_box_label:current_box_label + 1 # 标签维度
].reshape(4, -1).T
all_sampled_points.append(sampled_box_points)
# 合并所有盒子的采样点到一个NumPy数组中
final_sampled_data = np.vstack(all_sampled_points)
print("最终采样数据形状:", final_sampled_data.shape)
print("\n前5个采样点:\n", final_sampled_data[:5])
print("\n后5个采样点:\n", final_sampled_data[-5:])
# 验证采样点的标签
print("\n采样点中包含的标签:", np.unique(final_sampled_data[:, 3]))示例输出(部分):
最终采样数据形状: (108, 4) 前5个采样点: [[0. 0. 0. 1. ] [0. 0. 0.5 1. ] [0. 0. 1. 1. ] [0. 0.5 0. 1. ] [0. 0.5 0.5 1. ]] 后5个采样点: [[10.5 11.5 10.5 2. ] [10.5 11.5 11. 2. ] [10.5 12. 10. 2. ] [10.5 12. 10.5 2. ] [10.5 12. 11. 2. ]] 采样点中包含的标签: [1. 2.]
以上就是3D网格中盒子内部点的高效采样教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号