如何向量化实现NumPy大数组指定边界框区域的数值填充
优化边界框填充速度的几种方案
你当前的循环写法速度慢的核心原因是Python层的循环每次都需要做元组索引、参数解析、数组边界检查,虽然单次切片赋值本身是NumPy底层C实现的,但超大数组场景下这些开销会被放大,可通过以下方式优化:
方案1:Numba JIT编译(性能提升最显著,改动最小)
如果可以引入Numba依赖,直接给循环加JIT装饰器即可,编译后会完全消除Python层开销,直接执行底层内存操作,速度通常可以提升5~10倍:
import numba import numpy as np @numba.njit # 开启无Python模式编译 def fill_boxes(large_arr, boxes_y, boxes_x, embeddings): box_count = len(boxes_y) for idx in range(box_count): y_low, y_high = boxes_y[idx] x_low, x_high = boxes_x[idx] large_arr[y_low:y_high, x_low:x_high] = embeddings[idx] return large_arr # 调用前先把坐标列表转成NumPy数组,适配numba输入要求 boxes_y_arr = np.array(boxes_y, dtype=np.int64) boxes_x_arr = np.array(boxes_x, dtype=np.int64) large = fill_boxes(large, boxes_y_arr, boxes_x_arr, embeddings)
方案2:纯NumPy掩码向量化赋值(无额外依赖)
如果不能安装第三方依赖,可通过二维掩码减少Python循环的操作量:掩码是远小于三维原数组的二维结构,循环仅做掩码赋值,最后一次性完成三维数组的向量化填充,适合边界框无重叠、或允许后定义的框覆盖先定义的框的场景:
# 生成全量坐标掩码,初始值-1代表无对应边界框 mask = np.zeros(large.shape[:2], dtype=np.int32) - 1 # 循环仅更新二维掩码,开销远小于直接操作三维数组 for i in range(400): y_low, y_high = boxes_y[i] x_low, x_high = boxes_x[i] mask[y_low:y_high, x_low:x_high] = i # 一次性完成向量化赋值 valid_pos = mask != -1 large[valid_pos] = embeddings[mask[valid_pos]]
方案3:原生循环优化(改动最小,无依赖)
如果不想改原有逻辑,仅需要小幅提速,可先把坐标转成NumPy数组,减少Python层元组操作的开销:
boxes_y_arr = np.array(boxes_y) boxes_x_arr = np.array(boxes_x) for i in range(400): y1, y2 = boxes_y_arr[i] x1, x2 = boxes_x_arr[i] large[y1:y2, x1:x2] = embeddings[i]
内容的提问来源于stack exchange,提问作者Shadovx
相关产品推荐
相关产品推荐

