使用NumPy高效采样3D边界框内的点

心靈之曲
发布: 2025-11-24 11:56:00
原创
741人浏览过

使用numpy高效采样3d边界框内的点

本教程详细介绍了如何利用NumPy库,特别是np.mgrid函数,高效地在多个3D边界框内部以指定步长采样离散点,并为每个采样点分配其所属边界框的标签。文章涵盖了数据结构、核心采样逻辑、多边界框处理方法,并提供了完整的代码示例及注意事项,旨在帮助读者优化3D空间点云或体素化数据的生成过程。

引言:3D空间点采样需求

计算机视觉、机器人学、3D建模等领域,我们经常需要对三维空间中的特定区域进行离散化采样。例如,给定一组3D边界框(Bounding Boxes),我们可能需要以一定的分辨率(即步长step_size)在每个框内部生成一系列均匀分布的点,并为这些点赋予其所属边界框的类别标签。这种操作对于生成训练数据、进行碰撞检测或体素化表示都至关重要。

本文将介绍一种基于NumPy库的优化方法,利用其强大的广播和网格生成功能,实现对多个3D边界框内点的快速采样。

数据结构与问题定义

假设我们有一组3D边界框,每个边界框由其8个顶点定义。每个顶点是一个4D坐标 (x, y, z, label),其中 (x, y, z) 是空间坐标,label 是一个整数标签,表示该边界框的类别。我们假设同一个边界框内的所有8个顶点都具有相同的标签。

我们的输入数据 boxes 可以表示为一个NumPy数组,其形状为 (num_boxes, 8, 4),其中 num_boxes 是边界框的数量,8 代表每个边界框有8个顶点,4 代表每个顶点包含 (x, y, z, label) 四个维度。

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

import numpy as np

# 示例:一个边界框的8个顶点及其标签
# 假设这是一个长方体,从(0,0,0)到(2,3,1)
box_example = 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]
])

# 如果有多个边界框,它们将堆叠起来:
# boxes.shape = (num_boxes, 8, 4)
登录后复制

我们的目标是:给定 boxes 数组和一个 step_size(采样步长),生成一个包含所有采样点的数组,每个点是 (x, y, z, label) 形式。

绘蛙AI修图
绘蛙AI修图

绘蛙平台AI修图工具,支持手脚修复、商品重绘、AI扩图、AI换色

绘蛙AI修图 279
查看详情 绘蛙AI修图

核心采样逻辑:利用 np.mgrid

np.mgrid 是NumPy中一个非常强大的函数,用于创建多维网格坐标数组。它的切片语法 start:stop:step 可以直接指定起始值、结束值和步长,从而非常方便地生成均匀间隔的坐标。

对于单个边界框,采样点的核心步骤如下:

  1. 确定边界框范围: 从8个顶点中找出X、Y、Z坐标的最小值和最大值。
  2. 提取标签: 获取该边界框的标签。
  3. 使用 np.mgrid 生成网格点:
    • x_min:x_max:step_size 定义X轴的采样范围和步长。
    • y_min:y_max:step_size 定义Y轴的采样范围和步长。
    • z_min:z_max:step_size 定义Z轴的采样范围和步长。
    • label:label+1 巧妙地为第四维度(标签)生成一个常量值,确保所有采样点都带有正确的标签。
  4. 重塑结果: np.mgrid 返回的是多个网格数组,我们需要将它们堆叠并重塑成 (N, 4) 的形式,其中 N 是采样点的总数,4 代表 (x, y, z, label)。

注意 np.mgrid 的步长行为: 当使用 start:stop:step_size 语法时,np.mgrid 的行为类似于 np.arange,即 stop 值是不包含在结果中的。这意味着如果边界框的最大坐标恰好是 start + k * step_size,那么该最大坐标将不会被包含在采样点中。如果需要严格包含最大边界,可能需要将 stop 值略微增加一个很小的量(例如 max_coord + epsilon),或者使用 num_points*1j 的语法(如 start:stop:num_points*1j),这会生成 num_points 个点,包含 start 和 stop。对于大多数应用,直接使用 step_size 且 stop 独占是可接受的。

单个边界框的采样代码示例:

import numpy as np

def sample_single_box(box_vertices, step_size):
    """
    在单个3D边界框内采样点。

    参数:
    box_vertices (np.ndarray): 形状为(8, 4)的数组,表示边界框的8个顶点,
                               每个顶点包含(x, y, z, label)。
    step_size (float): 采样步长。

    返回:
    np.ndarray: 形状为(N, 4)的数组,包含所有采样点及其标签(x, y, z, label)。
    """
    # 提取X, Y, Z坐标的最小值和最大值
    min_coords = np.min(box_vertices[:, :3], axis=0)
    max_coords = np.max(box_vertices[:, :3], axis=0)

    x_min, y_min, z_min = min_coords
    x_max, y_max, z_max = max_coords

    # 提取边界框的标签 (假设所有顶点标签相同)
    box_label = int(box_vertices[0, 3])

    # 使用np.mgrid生成网格点和标签
    # 注意:mgrid的stop是独占的,如果需要包含max,可能需要微调max_coords
    sampled_points_grid = np.mgrid[
        x_min : x_max : step_size,
        y_min : y_max : step_size,
        z_min : z_max : step_size,
        box_label : box_label + 1  # 为标签维度生成一个常量值
    ]

    # 将网格数组重塑为 (N, 4) 的点列表
    # reshape(4, -1) 将所有坐标和标签展平,然后转置
    points = sampled_points_grid.reshape(4, -1).T

    return points

# 示例用法
# 创建一个简单的立方体边界框,标签为7
example_box_vertices = np.array([
    [0., 0., 0., 7.], [1., 0., 0., 7.], [0., 1., 0., 7.], [0., 1., 1., 7.],
    [1., 0., 1., 7.], [1., 1., 0., 7.], [1., 1., 1., 7.], [0., 0., 1., 7.]
])
example_step_size = 0.6

sampled_points = sample_single_box(example_box_vertices, example_step_size)
print("单个边界框采样结果:")
print(sampled_points)
print(f"采样点总数: {sampled_points.shape[0]}")
登录后复制

扩展到多个边界框

对于包含 num_boxes 个边界框的数组 boxes,我们可以遍历每个边界框,并应用上述的 sample_single_box 函数。最后,将所有边界框的采样结果合并成一个大的数组。

import numpy as np

def sample_multiple_boxes(all_boxes_data, step_size):
    """
    在多个3D边界框内采样点。

    参数:
    all_boxes_data (np.ndarray): 形状为(num_boxes, 8, 4)的数组,
                                 包含所有边界框的顶点数据。
    step_size (float): 采样步长。

    返回:
    np.ndarray: 形状为(N_total, 4)的数组,包含所有边界框的采样点及其标签。
    """
    all_sampled_points = []

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

        # 提取X, Y, Z坐标的最小值和最大值
        min_coords = np.min(box_vertices[:, :3], axis=0)
        max_coords = np.max(box_vertices[:, :3], axis=0)

        x_min, y_min, z_min = min_coords
        x_max, y_max, z_max = max_coords

        # 提取边界框的标签 (假设所有顶点标签相同)
        box_label = int(box_vertices[0, 3])

        # 使用np.mgrid生成网格点和标签
        sampled_points_grid = np.mgrid[
            x_min : x_max : step_size,
            y_min : y_max : step_size,
            z_min : z_max : step_size,
            box_label : box_label + 1
        ]

        # 将网格数组重塑为 (N, 4) 的点列表
        points = sampled_points_grid.reshape(4, -1).T
        all_sampled_points.append(points)

    # 合并所有边界框的采样结果
    if all_sampled_points:
        return np.vstack(all_sampled_points)
    else:
        return np.empty((0, 4)) # 如果没有边界框,返回空数组

# 完整示例:创建多个边界框并进行采样
# 第一个边界框:[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]
])

# 第二个边界框:[5,5,5]到[6,7,8],标签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, 8.0, 2], [6.0, 5.0, 8.0, 2], [6.0, 7.0, 8.0, 2], [5.0, 7.0, 8.0, 2]
])

# 组合成一个包含多个边界框的数组
all_boxes = np.array([box1, box2])
sampling_step_size = 0.5

# 执行采样
final_sampled_points = sample_multiple_boxes(all_boxes, sampling_step_size)

print("\
登录后复制

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