新闻中心

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

2025-11-24
浏览次数:
返回列表

使用 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) 点上。

PictoGraphic PictoGraphic

AI驱动的矢量插图库和插图生成平台

PictoGraphic 133 查看详情 PictoGraphic

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  # 上海网站内容seo  # 网站营销策划推广费用  # 市场营销推广哪家比较好  # 成都抖音seo关键词排名公司  # 吴中怎样做seo推广  # 网站建设及推广培训  # 品牌推广策划方案seo  # 赣县网站建设公司  # 并将  # python  # 是在  # 最小值  # 我们可以  # 数据结构  # 是一个  # 浮点数  # 多个  # 多维  # 工具  # app 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 生成rdflib自定义SPARQL函数:参数匹配与实践指南  微信群消息显示延迟如何解决 微信群消息刷新优化方法  漫画星球免费下拉式入口 漫画星球免费漫画在线阅读网站  荣耀Play7T运行卡顿解决_荣耀Play7T性能优化  优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题  J*aScript中管理异步API调用:确保操作顺序与数据一致性  React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性  Lar*el如何正确地在控制器和模型之间分配逻辑_Lar*el代码职责分离与架构建议  Lar*el头像管理:图片缩放与旧文件删除的最佳实践  处理动态列数据:J*a ArrayList的正确初始化与字符累加教程  必由学官方平台入口 必由学在线课堂登录地址  微信网页版官方快速登录入口 微信网页版网页版账号直达  写好的html代码怎么运行出来_运行写好的html代码方法【教程】  俄罗斯方块最新版入口 俄罗斯方块在线玩官网入口  QQ邮箱登录首页官网地址2026 QQ邮箱官方网页入口  快手极速版在线观看 官方网页版登录地址  PHP高效扁平化嵌套数组:使用array_merge与数组解包操作符  Mac怎么锁定备忘录_Mac备忘录加密设置教程  Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】  GemBox Document HTML转PDF垂直文本渲染问题及解决方案  《噬血代码2》新预告片发布 展示游戏剧情  Linux如何排查内存不足OOME问题_LinuxOOM分析教程  composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?  手机CPU怎么影响游戏体验_手机CPU对游戏性能的影响分析  LINUX怎么设置定时任务_LINUX crontab配置教程  如何使 Jest 模拟函数默认抛出错误以提高测试效率  神庙逃亡小游戏在线玩 神庙逃亡小游戏入口  葱吃多了会怎样 葱吃多了会伤胃吗  Angular中单选按钮的正确使用与常见陷阱解析  腾讯QQ邮箱登录入口_QQ邮箱官方网站使用地址  在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析  C++如何打印当前代码行号与文件名_C++预定义宏FILE与LINE的使用  蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台  钉钉视频会议声音异常如何处理 钉钉会议音频修复技巧  windows10怎么查看硬盘序列号_windows10硬盘id查询命令  Android Studio计算器C键逻辑错误排查与修复:条件判断优化指南  CSS图片焦点样式实现教程:理解与应用tabindex属性  Flexbox布局实践:实现粘性导航栏与底部固定页脚  MongoDB Aggregation:在嵌套对象数组中精确匹配ObjectId  知乎APP怎么管理已购盐选内容_知乎APP盐选内容购买记录与查看方法  在Go语言中利用后缀数组处理多字符串:实现高效文本匹配与自动补全  React Router v6 教程:构建认证保护的私有路由与重定向策略  漫蛙2在线漫画入口 漫蛙正版漫画网页版直达  解决Flask中Quill编辑器内容提交失败及TypeError的指南  J*a递归快速排序中静态变量导致数据累积的陷阱与解决方案  Golang切片为何属于引用类型_Golang slice底层结构与引用语义说明  c++中为什么推荐使用using替代typedef_c++现代化类型别名  QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台  Composer如何处理Git子模块(submodule)依赖_Composer与Git Submodule的对比与选择  c++20的std::jthread是什么_c++可中断线程与RAII式管理 

搜索