使用NumPy高效地在3D网格中填充点

霞舞
发布: 2025-11-26 14:39:15
原创
477人浏览过

使用numpy高效地在3d网格中填充点

本文详细介绍了如何使用NumPy库高效地在三维(3D)网格中的多个边界框内采样点。通过利用`np.mgrid`函数,我们可以简洁地生成指定步长内的坐标点,并为每个点分配相应的标签。教程涵盖了数据结构解析、核心采样逻辑以及处理多边界框的方法,并提供了完整的示例代码和关键注意事项,帮助读者优化3D空间点采样任务。

1. 引言与问题定义

在处理三维空间数据时,我们经常需要在一个或多个定义好的边界框(bounding box)内部以特定步长采样离散点。例如,给定一组由8个角点定义的3D盒子,每个角点包含(x, y, z, label)四维坐标信息,我们的目标是生成每个盒子内部所有满足step_size间隔的(x, y, z)坐标点,并为这些点分配对应的标签。

1.1 输入数据结构

假设我们有一个NumPy数组boxes,它包含了n个3D边界框的信息。每个边界框由其8个角点定义,每个角点是一个4D向量(x, y, z, label)。因此,boxes的形状通常为(num_boxes, 8, 4)。其中:

  • num_boxes:边界框的数量。
  • 8:每个边界框由8个角点定义。
  • 4:每个角点包含(x, y, z, label)四维信息。

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

boxes[0] = 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]
])
登录后复制

这里,label(例如示例中的1)对于同一个边界框的所有8个角点是保持一致的。

2. 使用 np.mgrid 进行高效采样

NumPy的np.mgrid函数是生成多维坐标网格的强大工具,它允许我们以类似于Python切片的方式定义每个维度的起始、结束和步长。这使得它非常适合用于在3D空间中进行规则采样。

 v18.5.30投票评选网站管理系统
v18.5.30投票评选网站管理系统

宁志投票评选网站管理系统一套专为活动投票专题建站首选的信息网站管理系统,风格宽频页面十分大方,宁志网站管理系统是国内知名建站软件,它由技术人员开发好了的一种现成建站软件,主要为全国各地方自助建站提供方便。 特点:安全、稳定、美观、实用、易操作。NZCMS开发结构采用ASP+ACCESS/MSSQL开发,运行高效的运行性能以及良好的可维护性,在近几年来吸引了众多国内机关单位的使用与推动:由于有众多支

 v18.5.30投票评选网站管理系统 119
查看详情  v18.5.30投票评选网站管理系统

2.1 核心采样逻辑(单个边界框)

对于单个边界框,采样过程可以分解为以下步骤:

  1. 确定边界范围: 从边界框的8个角点中,找出每个维度(x, y, z)的最小值和最大值。
  2. 定义采样步长: 指定我们希望采样点的间隔step_size。
  3. 生成坐标网格: 使用np.mgrid生成x, y, z坐标以及标签的网格。
  4. 重塑数据: 将生成的网格重塑为(num_sampled_points, 4)的格式,其中每行代表一个采样点(x, y, z, label)。
import numpy as np

def sample_points_in_single_box(box_coords, box_label, step_size):
    """
    在单个3D边界框内以指定步长采样点。

    参数:
        box_coords (np.ndarray): 形状为(8, 3)的数组,表示边界框的8个(x,y,z)角点。
        box_label (int/float): 边界框的标签。
        step_size (float): 采样点的间隔距离。

    返回:
        np.ndarray: 形状为(N, 4)的数组,每行包含一个采样点的(x, y, z, label)。
    """
    # 提取每个维度的最小值和最大值
    min_x, min_y, min_z = np.min(box_coords, axis=0)
    max_x, max_y, max_z = np.max(box_coords, axis=0)

    # 使用np.mgrid生成坐标网格
    # 注意:mgrid的步长参数是独占的,即不包含max值。
    # 对于标签维度,我们只取box_label本身。
    # label:label+1 确保mgrid只生成一个值,即box_label
    sampled_grid = np.mgrid[
        min_x : max_x : step_size,
        min_y : max_y : step_size,
        min_z : max_z : step_size,
        box_label : box_label + 1 # 确保标签维度只包含一个值
    ]

    # 将多维网格重塑为 (4, N) 然后转置为 (N, 4)
    # 其中 N 是采样点的总数
    sampled_points = sampled_grid.reshape(4, -1).T
    return sampled_points

# 示例数据
# 假设一个简单的单位立方体,标签为7
example_box_raw = np.array([
    [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.]
])
example_box_coords = example_box_raw[:, :3] # 提取XYZ坐标
example_box_label = int(example_box_raw[0, 3]) # 提取标签

step_size = 0.6
sampled_data = sample_points_in_single_box(example_box_coords, example_box_label, step_size)
print("单个边界框采样结果:")
print(sampled_data)
登录后复制

输出示例:

单个边界框采样结果:
[[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. ]]
登录后复制

2.2 处理多个边界框

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

import numpy as np

def sample_points_in_multiple_boxes(boxes_data, step_size):
    """
    在多个3D边界框内以指定步长采样点。

    参数:
        boxes_data (np.ndarray): 形状为(num_boxes, 8, 4)的数组,
                                 每个元素包含一个边界框的8个(x,y,z,label)角点。
        step_size (float): 采样点的间隔距离。

    返回:
        tuple: (sampled_points_xyz, sampled_labels)
               sampled_points_xyz (np.ndarray): 形状为(N, 3)的数组,所有采样点的(x,y,z)坐标。
               sampled_labels (np.ndarray): 形状为(N,)的数组,所有采样点的标签。
    """
    all_sampled_points = []
    all_sampled_labels = []

    # 遍历每个边界框
    for i in range(boxes_data.shape[0]):
        current_box_raw = boxes_data[i]

        # 提取当前边界框的XYZ坐标和标签
        current_box_coords = current_box_raw[:, :3]
        # 假设每个盒子的标签在其第一个角点的第四个维度
        current_box_label = int(current_box_raw[0, 3])

        # 提取每个维度的最小值和最大值
        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)

        # 使用np.mgrid生成坐标网格
        sampled_grid = 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
        ]

        # 重塑数据并分离XYZ和标签
        points_with_labels = sampled_grid.reshape(4, -1).T

        all_sampled_points.append(points_with_labels[:, :3])
        all_sampled_labels.append(points_with_labels[:, 3])

    # 将所有结果合并成一个NumPy数组
    final_points_xyz = np.vstack(all_sampled_points) if all_sampled_points else np.array([])
    final_labels = np.concatenate(all_sampled_labels).astype(int) if all_sampled_labels else np.array([])

    return final_points_xyz, final_labels

# 模拟多个边界框数据
# 盒子1:(0,0,0)到(2,3,1),标签为1
box1 = 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]
])
# 盒子2:(5,5,5)到(6,7,6),标签为2
box2 = np.array([
    [5.0, 5.0, 5.0, 2], [6.0, 5.0, 5.0, 2], [6.0, 7.0, 5.0, 2], [5.0, 7.0, 5.0, 2],
    [5.0, 5.0, 6.0, 2], [6.0, 5.0, 6.0, 2], [6.0, 7.0, 6.0, 2], [5.0, 7.0, 6.0, 2]
])

# 将多个盒子堆叠成输入格式 (num_boxes, 8, 4)
multiple_boxes_data = np.array([box1, box2])
step_size_multi = 0.5

sampled_points_xyz, sampled_labels = sample_points_in_multiple_boxes(multiple_boxes_data, step_size_multi)

print("\n多个边界框采样结果 (XYZ坐标):")
print(sampled_points_xyz)
print("\n多个边界框采样结果 (标签):")
print(sampled_labels)
print(f"\n总共采样点数量: {len(sampled_points_xyz)}")
登录后复制

3. 注意事项与优化

3.1 np.mgrid的步长行为

  • 独占性: np.mgrid使用浮点步长时,其行为类似于Python的range()函数,即终止值是不包含的。例如,0:1:0.6会生成[0., 0.6]。如果需要确保包含最大值(例如,当最大值正好是步长的倍数时),可能需要微调max_x + epsilon或使用np.linspace。
  • 复数步长: np.mgrid也支持复数步长(例如start:stop:N*1j),这表示生成N个点,且包含stop值,行为类似于np.linspace。如果严格要求包含边界,可以计算出所需点数并使用此方式。例如,num_points_x = int(np.floor((max_x - min_x) / step_size)) + 1,然后使用min_x:max_x:num_points_x*1j。然而,对于大多数3D采样场景,直接使用浮点步长通常足够。

3.2 性能考虑

  • 循环与向量化: 尽管np.mgrid本身是高效的NumPy操作,但对于处理n个盒子,我们仍然需要一个Python循环。对于每个盒子,np.mgrid会生成一个完整的网格。如果num_boxes非常大,或者step_size非常小导致每个盒子生成大量点,则整体计算量会很大。
  • 内存使用: 采样点数量可能非常庞大,尤其是当step_size很小且盒子体积很大时。确保系统有足够的内存来存储all_sampled_points和all_sampled_labels列表,以及最终的合并数组。

3.3 数据一致性

  • 标签提取: 在示例中,我们假设每个边界框的标签是其第一个角点(boxes_data[i, 0, 3])的第四个维度。请根据实际数据结构调整标签的提取方式,确保每个盒子只有一个一致的标签。

4. 总结

本文提供了一种使用NumPy np.mgrid函数在3D边界框内高效采样点的方法。通过清晰地定义输入数据结构、利用np.mgrid的强大功能来生成坐标网格,并结合循环处理多个边界框,我们可以构建一个健壮且易于理解的点采样解决方案。在实际应用中,应根据具体需求权衡step_size的选择以及对内存和性能的考量。

以上就是使用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号