新闻中心
使用 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
AI驱动的矢量插图库和插图生成平台
133
查看详情
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])注意事项
-
端点包含性: 使用 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 方式。
浮点数精度: 在涉及浮点数计算时,尤其是在比较边界或计算步长时,可能会遇到浮点数精度问题。在实际应用中,如果对边界的精确性有极高要求,需要谨慎处理。
性能考量: 对于少量边界框,上述循环方法效率足够。但如果 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式管理


2025-11-24
浏览次数:次
返回列表
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. ]]