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

碧海醫心
发布: 2025-11-24 14:10:13
原创
182人浏览过

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.ravel(), y_coords.ravel(), z_coords.ravel()]).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调用中,从而实现更高效、更简洁的采样。

AI TransPDF
AI TransPDF

高效准确地将PDF文档翻译成多种语言的AI智能PDF文档翻译工具

AI TransPDF 231
查看详情 AI TransPDF

核心思想是:将盒子的标签作为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网格中盒子内部点的高效采样教程的详细内容,更多请关注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号