
本教程详细介绍了如何利用NumPy库,特别是np.mgrid函数,高效地在多个3D边界框内部以指定步长采样离散点,并为每个采样点分配其所属边界框的标签。文章涵盖了数据结构、核心采样逻辑、多边界框处理方法,并提供了完整的代码示例及注意事项,旨在帮助读者优化3D空间点云或体素化数据的生成过程。
在计算机视觉、机器人学、3D建模等领域,我们经常需要对三维空间中的特定区域进行离散化采样。例如,给定一组3D边界框(Bounding Boxes),我们可能需要以一定的分辨率(即步长step_size)在每个框内部生成一系列均匀分布的点,并为这些点赋予其所属边界框的类别标签。这种操作对于生成训练数据、进行碰撞检测或体素化表示都至关重要。
本文将介绍一种基于NumPy库的优化方法,利用其强大的广播和网格生成功能,实现对多个3D边界框内点的快速采样。
假设我们有一组3D边界框,每个边界框由其8个顶点定义。每个顶点是一个4D坐标 (x, y, z, label),其中 (x, y, z) 是空间坐标,label 是一个整数标签,表示该边界框的类别。我们假设同一个边界框内的所有8个顶点都具有相同的标签。
我们的输入数据 boxes 可以表示为一个NumPy数组,其形状为 (num_boxes, 8, 4),其中 num_boxes 是边界框的数量,8 代表每个边界框有8个顶点,4 代表每个顶点包含 (x, y, z, label) 四个维度。
示例数据结构: 一个单独的边界框数据可能如下所示:
import numpy as np
# 示例:一个边界框的8个顶点及其标签
# 假设这是一个长方体,从(0,0,0)到(2,3,1)
box_example = np.array([
[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]
])
# 如果有多个边界框,它们将堆叠起来:
# boxes.shape = (num_boxes, 8, 4)我们的目标是:给定 boxes 数组和一个 step_size(采样步长),生成一个包含所有采样点的数组,每个点是 (x, y, z, label) 形式。
np.mgrid 是NumPy中一个非常强大的函数,用于创建多维网格坐标数组。它的切片语法 start:stop:step 可以直接指定起始值、结束值和步长,从而非常方便地生成均匀间隔的坐标。
对于单个边界框,采样点的核心步骤如下:
注意 np.mgrid 的步长行为: 当使用 start:stop:step_size 语法时,np.mgrid 的行为类似于 np.arange,即 stop 值是不包含在结果中的。这意味着如果边界框的最大坐标恰好是 start + k * step_size,那么该最大坐标将不会被包含在采样点中。如果需要严格包含最大边界,可能需要将 stop 值略微增加一个很小的量(例如 max_coord + epsilon),或者使用 num_points*1j 的语法(如 start:stop:num_points*1j),这会生成 num_points 个点,包含 start 和 stop。对于大多数应用,直接使用 step_size 且 stop 独占是可接受的。
单个边界框的采样代码示例:
import numpy as np
def sample_single_box(box_vertices, step_size):
"""
在单个3D边界框内采样点。
参数:
box_vertices (np.ndarray): 形状为(8, 4)的数组,表示边界框的8个顶点,
每个顶点包含(x, y, z, label)。
step_size (float): 采样步长。
返回:
np.ndarray: 形状为(N, 4)的数组,包含所有采样点及其标签(x, y, z, label)。
"""
# 提取X, Y, Z坐标的最小值和最大值
min_coords = np.min(box_vertices[:, :3], axis=0)
max_coords = np.max(box_vertices[:, :3], axis=0)
x_min, y_min, z_min = min_coords
x_max, y_max, z_max = max_coords
# 提取边界框的标签 (假设所有顶点标签相同)
box_label = int(box_vertices[0, 3])
# 使用np.mgrid生成网格点和标签
# 注意:mgrid的stop是独占的,如果需要包含max,可能需要微调max_coords
sampled_points_grid = np.mgrid[
x_min : x_max : step_size,
y_min : y_max : step_size,
z_min : z_max : step_size,
box_label : box_label + 1 # 为标签维度生成一个常量值
]
# 将网格数组重塑为 (N, 4) 的点列表
# reshape(4, -1) 将所有坐标和标签展平,然后转置
points = sampled_points_grid.reshape(4, -1).T
return points
# 示例用法
# 创建一个简单的立方体边界框,标签为7
example_box_vertices = np.array([
[0., 0., 0., 7.], [1., 0., 0., 7.], [0., 1., 0., 7.], [0., 1., 1., 7.],
[1., 0., 1., 7.], [1., 1., 0., 7.], [1., 1., 1., 7.], [0., 0., 1., 7.]
])
example_step_size = 0.6
sampled_points = sample_single_box(example_box_vertices, example_step_size)
print("单个边界框采样结果:")
print(sampled_points)
print(f"采样点总数: {sampled_points.shape[0]}")对于包含 num_boxes 个边界框的数组 boxes,我们可以遍历每个边界框,并应用上述的 sample_single_box 函数。最后,将所有边界框的采样结果合并成一个大的数组。
import numpy as np
def sample_multiple_boxes(all_boxes_data, step_size):
"""
在多个3D边界框内采样点。
参数:
all_boxes_data (np.ndarray): 形状为(num_boxes, 8, 4)的数组,
包含所有边界框的顶点数据。
step_size (float): 采样步长。
返回:
np.ndarray: 形状为(N_total, 4)的数组,包含所有边界框的采样点及其标签。
"""
all_sampled_points = []
# 遍历每个边界框
for i in range(all_boxes_data.shape[0]):
box_vertices = all_boxes_data[i]
# 提取X, Y, Z坐标的最小值和最大值
min_coords = np.min(box_vertices[:, :3], axis=0)
max_coords = np.max(box_vertices[:, :3], axis=0)
x_min, y_min, z_min = min_coords
x_max, y_max, z_max = max_coords
# 提取边界框的标签 (假设所有顶点标签相同)
box_label = int(box_vertices[0, 3])
# 使用np.mgrid生成网格点和标签
sampled_points_grid = np.mgrid[
x_min : x_max : step_size,
y_min : y_max : step_size,
z_min : z_max : step_size,
box_label : box_label + 1
]
# 将网格数组重塑为 (N, 4) 的点列表
points = sampled_points_grid.reshape(4, -1).T
all_sampled_points.append(points)
# 合并所有边界框的采样结果
if all_sampled_points:
return np.vstack(all_sampled_points)
else:
return np.empty((0, 4)) # 如果没有边界框,返回空数组
# 完整示例:创建多个边界框并进行采样
# 第一个边界框:[0,0,0]到[2,3,1],标签1
box1 = np.array([
[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]
])
# 第二个边界框:[5,5,5]到[6,7,8],标签2
box2 = np.array([
[5.0, 5.0, 5.0, 2], [6.0, 5.0, 5.0, 2], [6.0, 7.0, 5.0, 2], [5.0, 7.0, 5.0, 2],
[5.0, 5.0, 8.0, 2], [6.0, 5.0, 8.0, 2], [6.0, 7.0, 8.0, 2], [5.0, 7.0, 8.0, 2]
])
# 组合成一个包含多个边界框的数组
all_boxes = np.array([box1, box2])
sampling_step_size = 0.5
# 执行采样
final_sampled_points = sample_multiple_boxes(all_boxes, sampling_step_size)
print("\以上就是使用NumPy高效采样3D边界框内的点的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号