新闻中心

3D网格中盒子内部点的高效采样教程

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

3D网格中盒子内部点的高效采样教程

本教程详细阐述了如何在3d网格中对给定盒子进行高效的内部点采样。通过利用numpy库的`np.mgrid`函数,我们将展示一种简洁且向量化的方法,以指定步长生成包含(x, y, z)坐标及对应标签的采样点集合。这种方法显著简化了代码并提升了处理多个3d盒子的效率,适用于需要大规模空间数据采样的场景。

在处理3D空间数据时,我们经常需要对特定区域(例如由一组坐标定义的盒子)进行均匀采样。这在计算机图形学、物理模拟、机器学习特征提取等领域尤为常见。本文将深入探讨如何使用Python的NumPy库,特别是np.mgrid函数,高效地从3D盒子内部提取具有指定步长的采样点,并为每个点关联其所属盒子的标签。

1. 问题背景与数据结构

假设我们有一个包含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米),在每个盒子的内部以该步长均匀地采样点,并为每个采样点附上盒子的标签。最终输出应是一个包含所有采样点及其对应标签的集合。

2. 传统采样方法的局限性

一种常见的直观方法是:

  1. 计算每个盒子的x, y, z维度的最小值和最大值。
  2. 根据step_size计算每个维度上需要采样的点数。
  3. 使用np.mgrid配合复数步长(例如num_points * 1j)来生成包含端点的坐标网格。
  4. 将生成的坐标展平并堆叠,然后为每个点重复盒子的标签。
  5. 对所有盒子重复上述过程,并将结果收集到列表中。

其大致代码结构如下:

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.r*el(), y_coords.r*el(), z_coords.r*el()]).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的复数步长用法需要我们预先计算点数,这增加了复杂性。

3. 基于np.mgrid的优化采样方法

NumPy的np.mgrid函数提供了一种更简洁的切片语法start:stop:step,可以直接指定步长来生成等间隔的数值序列。通过巧妙地利用这一特性,我们可以将坐标生成和标签关联集成到单个np.mgrid调用中,从而实现更高效、更简洁的采样。

PictoGraphic PictoGraphic

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

PictoGraphic 133 查看详情 PictoGraphic

核心思想是:将盒子的标签作为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

代码解析:

  1. np.min(box[:, :3], axis=0) 和 np.max(box[:, :3], axis=0):这行代码从盒子的所有顶点中提取x, y, z坐标,并计算每个维度上的最小值和最大值,从而定义了盒子的边界。
  2. np.mgrid[min_x:max_x:step_size, ... , label:label + 1]:
    • min_x:max_x:step_size:为X轴生成从min_x开始,以step_size为步长,直到但不包括max_x的等间隔序列。Y轴和Z轴同理。
    • label:label + 1:为第四个维度(标签)生成一个从label开始,以1为步长,直到但不包括label + 1的序列。这意味着它只会生成一个值,即label本身。
    • np.mgrid会返回一个多维数组,其维度顺序是[x_dim, y_dim, z_dim, label_dim]。
  3. .reshape(4, -1).T:
    • reshape(4, -1):将生成的网格展平为一个2D数组,其中第一维是4(对应x, y, z, label),第二维是所有采样点的总数。
    • .T:进行转置操作,将数组形状从(4, N)变为(N, 4),使得每一行代表一个采样点(x, y, z, label),这更符合通常的数据表示习惯。

这种方法极大地简化了代码,并充分利用了NumPy的向量化能力,对于大规模数据处理具有显著的性能优势。

4. 完整示例与应用

现在,我们将上述优化方法应用于处理多个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.]

5. 注意事项与最佳实践

  1. np.mgrid的步长行为: start:stop:step 语法生成的序列不包含 stop 值。这意味着如果你的盒子边界正好是max_x,那么max_x本身不会被采样到。如果需要包含max_x,可以考虑将max_x稍微增大一个极小值(例如max_x + epsilon),或者使用np.linspace来精确控制点数并包含端点。但在大多数均匀采样场景中,不包含终点是可接受的。
  2. 浮点数精度: 由于step_size是浮点数,浮点运算可能导致精度问题。在某些情况下,这可能会导致边界点采样行为的微小差异。
  3. 标签一致性: 本教程假设每个盒子的所有顶点都具有相同的标签。在实际应用中,请确保你的数据结构符合这一假设,或者相应地调整标签提取逻辑。
  4. 内存消耗: 对于非常大或非常小的step_size,

以上就是3D网格中盒子内部点的高效采样教程的详细内容,更多请关注其它相关文章!


# 计算机  # app  # 数据结构  # 多维  # 是一个  # 第一个  # 都是  # python  # 李佳琦营销推广  # 山东化工行业网站建设  # 南宁推广网站哪家好用点  # 蚌埠市网站优化  # 哈尔滨网站建设登录  # 沈阳浑南网站优化推广  # 阳泉seo公司甄选火星  # 南宁网站建设实训  # 珠海整站seo排名效果  # 同城核心关键词排名前十  # 我们可以  # 但在  # 不包含  # 多个  # 这一 


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


相关推荐: C++如何打印当前代码行号与文件名_C++预定义宏FILE与LINE的使用  AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看  怎么在浏览器上运行HTML文件_浏览器运行HTML文件技巧【技巧】  poki网页游戏推荐_poki免费游戏平台入口  Golang如何使用const iota_Go iota常量计数器讲解  qq游戏手机版下载安装_qq游戏移动端入口  AO3网页版最新入口合集 Archive of Our Own在线访问指南  Win10桌面图标出现小盾牌怎么办 Win10去除UAC图标教程【解决】  抖音网页版怎么|直播|_抖音网页版开播操作指南  一加Ace 6T支持全新明眸护眼:通过了最严苛的护眼小金标认证  想当下一个《2077》?《心之眼》Steam评价升至"多半好评"  小米汽车11月交付量突破40000台!雷军:将继续努力  Log4j Console Appender性能瓶颈与高并发优化策略  顺丰快递查询系统 官方正版查询入口  企业名称高精度匹配:N-gram方法在结构相似性分析中的应用  优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践  Win11怎么用U盘重装系统 Win11制作启动盘并重装系统完整教程【详解】  mc.js官网登录入口 mc.js官方登录入口最新版  HTML长属性值处理:表单action路径优化与代码规范应对  4399体育竞技小游戏_4399小游戏赛事入口  PHP 枚举:根据字符串获取枚举案例的策略与实现  天眼查企业查询官网入口 天眼查官方网页版查询  PostgreSQL海量数据高效导入策略:Python与Django实践指南  AO3官网镜像链接 Archive of Our Own同人文在线浏览  J*aScript数组对象转换:按指定键分组与值收集  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  单射、满射与双射的关系 一文理清所有逻辑  poki免费入口快捷访问 poki人气小游戏直接玩站点  MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具  Win11怎么隐藏桌面图标 Win11一键隐藏所有桌面元素及恢复显示  TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法  J*aScript实现单选按钮与关联输入框的联动禁用教程  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  HTML转PPT成品工具有哪些?HTML网页转PPT成品工具大全  漫蛙manwa官网登录界面_漫蛙漫画网页版主站入口  J*aScript中在Map循环中检测并处理空数组元素  Excel组合图表怎么做 Excel创建柱状图与折线组合图教程【图表】  包子漫画官方网站阅读入口-包子漫画在线漫画官网直达链接  如何在 Excel Online 和 Google 表格中更改日期格式  QQ邮箱网页版邮箱入口 QQ邮箱官方登录平台  PDO预处理语句中冒号的正确处理:区分SQL函数格式与命名占位符  百度网盘网页版入口 百度网盘网页版官方登录网址  Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】  12306选座怎么选到特殊座位_12306特殊座位选择注意事项  抖音怎么赚钱_抖音创作者变现方法与途径指南  cad如何更改注释性对象的比例_cad注释性比例调整方法  QQ邮箱网页版快速登录 QQ邮箱邮箱账号官方入口地址  魅族17怎样用浏览器译外语网页_iPhone魅族17浏览器译外语网页【即时翻译】  Go语言中JSON数据解码与字段访问指南  如何使用Node.js csv 包按条件移除含空字段的CSV记录 

搜索