使用 NumPy 在 3D 边界框内高效采样点并关联标签

DDD
发布: 2025-11-24 12:26:48
原创
843人浏览过

使用 NumPy 在 3D 边界框内高效采样点并关联标签

本教程详细介绍了如何利用 numpy 的 `np.mgrid` 函数,在给定的 3d 边界框内以指定步长高效地采样一系列空间点,并为每个采样点自动关联其所属边界框的标签。通过直接在 `np.mgrid` 中构造标签维度,避免了额外的数据处理步骤,从而简化了代码并提升了效率。

理解 3D 边界框数据结构

在处理 3D 空间数据时,我们经常会遇到以边界框形式表示的对象。每个边界框通常由其最小和最大坐标定义,并且可能带有一个或多个属性,例如标签。本教程中,我们假设每个边界框由 8 个 4D 坐标点描述,格式为 (x, y, z, l),其中 (x, y, z) 是空间坐标,l 是一个整数标签。一个 boxes 数组可能包含 n 个这样的边界框,其形状可能为 (n, 8, 4)。

例如,一个边界框的数据结构可能如下所示:

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]
]
登录后复制

这里,每个点的第四个维度(索引为 3)代表其所属边界框的标签。

目标:在边界框内进行点采样

我们的目标是在每个给定的 3D 边界框内部,以一个固定的 step_size(例如 0.01 米)生成一系列均匀分布的 (x, y, z) 坐标点,并将每个采样点与其所属边界框的标签 l 关联起来。最终输出应是一个包含所有采样点及其对应标签的列表或数组。

核心工具:np.mgrid 函数

NumPy 库提供了 np.mgrid 函数,它是一个非常强大的工具,用于在指定范围内生成多维网格坐标。它的语法类似于 Python 的切片操作,格式为 start:stop:step。

  • start 和 stop 定义了维度的起始和结束值。
  • step 可以是浮点数或复数:
    • 当 step 是浮点数时(例如 0.01),它表示步长。在这种情况下,生成的序列将从 start 开始,以 step 为间隔递增,直到但不包括 stop。
    • 当 step 是复数时(例如 10j),它表示在 start 和 stop 之间(包含 start 和 stop)生成 N 个点。例如,start:stop:N*1j 将生成 N 个均匀间隔的点。

在本教程中,我们将主要利用浮点数 step_size 的用法,并结合巧妙的维度构造来实现标签的自动关联。

高效采样与标签关联的实现

为了高效地在 3D 边界框内采样点并关联标签,我们可以将 np.mgrid 的功能扩展到第四个维度,专门用于存储标签信息。

1. 确定边界框的范围和标签

对于一个给定的边界框 box(形状为 (8, 4)),我们需要提取其 x, y, z 坐标的最小值和最大值,以及其标签。由于所有 8 个点的标签都是相同的,我们可以从任意一个点获取标签。

import numpy as np

# 假设这是一个单独的边界框数据
box = 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]
])
step_size = 0.6 # 采样步长

# 提取x, y, z维度的最小值和最大值
min_x, max_x = np.min(box[:, 0]), np.max(box[:, 0])
min_y, max_y = np.min(box[:, 1]), np.max(box[:, 1])
min_z, max_z = np.min(box[:, 2]), np.max(box[:, 2])

# 提取边界框的标签
label = int(box[0, 3]) # 假设所有点的标签相同
登录后复制

2. 使用 np.mgrid 生成点和标签

现在,我们将 np.mgrid 应用于四个维度:x, y, z 和 label。

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 # 关键:生成一个只包含标签值的维度
]
登录后复制

这里 label:label + 1 是一个巧妙的用法。它会生成一个从 label 开始,步长为 1,到 label + 1 结束(不包含 label + 1)的序列。这意味着这个维度将只包含 label 这一个值,从而将标签广播到所有生成的 (x, y, z) 点上。

AI帮个忙
AI帮个忙

多功能AI小工具,帮你快速生成周报、日报、邮、简历等

AI帮个忙 116
查看详情 AI帮个忙

3. 重塑数据

np.mgrid 的输出是一个多维数组,其每个维度对应于输入切片。我们需要将其重塑为 (N, 4) 的二维数组,其中 N 是采样点的总数,每行代表一个 (x, y, z, label) 点。

points_final = points_with_labels.reshape(4, -1).T
登录后复制

reshape(4, -1) 会将数组重塑为 4 行,列数自动计算。.T 进行转置操作,将形状变为 (-1, 4),即 N 行 4 列,这正是我们期望的 (x, y, z, label) 格式。

示例代码:单个边界框的采样

让我们结合上述步骤,为一个示例边界框生成采样点。

import numpy as np
from itertools import product, repeat

# 示例边界框数据
# 这是一个从 (0,0,0) 到 (1,1,1) 的立方体,标签为 7
label = 7
box = np.hstack([np.array(list(product(*repeat(range(2), 3)))), np.ones((8,1)) * label])
print("原始边界框数据:\n", box)

step_size = 0.6 # 采样步长

# 提取x, y, z维度的最小值和最大值
min_x, max_x = np.min(box[:, 0]), np.max(box[:, 0])
min_y, max_y = np.min(box[:, 1]), np.max(box[:, 1])
min_z, max_z = np.min(box[:, 2]), np.max(box[:, 2])

# 使用 np.mgrid 生成点和标签
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
]

# 重塑数据为 (N, 4) 格式
sampled_points = points_with_labels.reshape(4, -1).T

print("\n采样步长:", step_size)
print("生成的采样点及其标签:\n", sampled_points)
登录后复制

输出示例:

原始边界框数据:
 [[0. 0. 0. 7.]
 [0. 0. 1. 7.]
 [0. 1. 0. 7.]
 [0. 1. 1. 7.]
 [1. 0. 0. 7.]
 [1. 0. 1. 7.]
 [1. 1. 0. 7.]
 [1. 1. 1. 7.]]

采样步长: 0.6
生成的采样点及其标签:
 [[0.  0.  0.  7. ]
 [0.  0.  0.6 7. ]
 [0.  0.6 0.  7. ]
 [0.  0.6 0.6 7. ]
 [0.6 0.  0.  7. ]
 [0.6 0.  0.6 7. ]
 [0.6 0.6 0.  7. ]
 [0.6 0.6 0.6 7. ]]
登录后复制

处理多个边界框

当需要处理多个边界框时,我们可以遍历 boxes 数组,对每个边界框应用上述逻辑,并将结果收集起来。

import numpy as np

# 模拟多个边界框数据
# boxes.shape = (num_boxes, 8, 4)
boxes = 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]
    ],
    [
        [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 = boxes[i]

    # 提取x, y, z维度的最小值和最大值
    min_x, max_x = np.min(current_box[:, 0]), np.max(current_box[:, 0])
    min_y, max_y = np.min(current_box[:, 1]), np.max(current_box[:, 1])
    min_z, max_z = np.min(current_box[:, 2]), np.max(current_box[:, 2])

    # 提取边界框的标签
    label = int(current_box[0, 3])

    # 使用 np.mgrid 生成点和标签
    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
    ]

    # 重塑数据为 (N, 4) 格式
    sampled_points_for_box = points_with_labels.reshape(4, -1).T
    all_sampled_points.append(sampled_points_for_box)

# 将所有边界框的采样点合并为一个 NumPy 数组
final_sampled_data = np.vstack(all_sampled_points)

print("所有边界框的采样点及其标签的前10行:\n", final_sampled_data[:10])
print("\n所有边界框的采样点总数:", final_sampled_data.shape[0])
登录后复制

注意事项

  1. 端点包含性: 使用 np.mgrid 配合浮点数 step_size 时,生成的序列默认不包含 stop 值。这意味着 max_x, max_y, max_z 这些边界值本身可能不会被采样到,除非它们恰好是 start + k * step_size 的精确结果。如果需要严格包含端点,可以考虑以下方法:

    • 将 stop 值略微增大一个很小的量(例如 max_x + epsilon)。
    • 使用复数步长语法 N*1j,它会包含 start 和 stop,但需要预先计算每个维度所需的点数。例如 np.mgrid[min_x:max_x:(num_points_x)*1j]。
    • 结合 np.linspace 和 np.meshgrid。 选择哪种方法取决于对端点包含性的具体要求。本教程中的方法遵循了答案给出的简洁 step_size 方式。
  2. 浮点数精度: 在涉及浮点数计算时,尤其是在比较边界或计算步长时,可能会遇到浮点数精度问题。在实际应用中,如果对边界的精确性有极高要求,需要谨慎处理。

  3. 性能考量: 对于少量边界框,上述循环方法效率足够。但如果 boxes 数组非常大,且每个边界框的采样点数量也很多,循环可能不是最高效的方式。在这种极端情况下,可以考虑更高级的矢量化技术或并行计算,但这会使代码复杂性显著增加。对于大多数常见的 3D 场景,当前方法已提供良好的性能和可读性。

总结

通过巧妙地利用 NumPy np.mgrid 函数的切片语法,

以上就是使用 NumPy 在 3D 边界框内高效采样点并关联标签的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号