0

0

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

心靈之曲

心靈之曲

发布时间:2025-11-24 11:56:00

|

787人浏览过

|

来源于php中文网

原创

使用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) 形式。

Autoppt
Autoppt

Autoppt:打造高效与精美PPT的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("\

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

535

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

17

2026.01.06

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

go语言 数组和切片
go语言 数组和切片

本专题整合了go语言数组和切片的区别与含义,阅读专题下面的文章了解更多详细内容。

46

2025.09.03

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

68

2026.01.16

全民K歌得高分教程大全
全民K歌得高分教程大全

本专题整合了全民K歌得高分技巧汇总,阅读专题下面的文章了解更多详细内容。

127

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

R 教程
R 教程

共45课时 | 5.2万人学习

SQL 教程
SQL 教程

共61课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号