Numpy无循环从二维数组中批量选取多个指定矩形区域的实现方法
Numpy批量裁剪二维数组矩形区域的无循环方案
错误原因说明
你之前的写法报错是因为Python原生切片语法start:end仅支持标量作为起止值,不支持直接传入数组批量生成多个切片,必须使用Numpy高级索引实现需求。
分场景解决方案
场景1:所有待裁剪矩形尺寸完全相同
这种场景可以使用sliding_window_view生成无内存拷贝的视图,性能最高:
import numpy as np # 初始化示例数据 arr = np.arange(50).reshape(5, 10) crop_params = np.array([[1,3,2,5], [2,2,0,3]]) # 统一的裁剪高度和宽度 crop_h, crop_w = 3, 5 # 生成所有可能的滑动窗口视图,无额外内存开销 windows = np.lib.stride_tricks.sliding_window_view(arr, (crop_h, crop_w)) # 按参数提取对应窗口,展平为一维数组 result = windows[crop_params[:, 0], crop_params[:, 2]].reshape(len(crop_params), -1)
场景2:待裁剪矩形尺寸不一致
这种场景用广播生成索引,核心操作全为Numpy向量化运算,仅最后拆分不规则结果时的循环开销可忽略:
def vectorized_crop(arr, crop_params): y_start, y_len, x_start, x_len = crop_params.T max_y = y_len.max() max_x = x_len.max() # 广播生成所有矩形的行索引和掩码 y_idx = y_start[:, None] + np.arange(max_y) y_mask = np.arange(max_y) < y_len[:, None] # 广播生成所有矩形的列索引和掩码 x_idx = x_start[:, None] + np.arange(max_x) x_mask = np.arange(max_x) < x_len[:, None] # 高级索引批量取值 cropped_arr = arr[y_idx[:, :, None], x_idx[:, None, :]] # 按掩码过滤填充部分,返回每个矩形的展平结果 return [cropped_arr[i][y_mask[i]][:, x_mask[i]].ravel() for i in range(len(crop_params))] # 调用示例 result = vectorized_crop(arr, crop_params)
运行后得到的result与你期望的输出完全一致:
[array([12, 13, 14, 15, 16, 22, 23, 24, 25, 26, 32, 33, 34, 35, 36]), array([20, 21, 22, 30, 31, 32])]
内容的提问来源于stack exchange,提问作者Binyamin Even
相关产品推荐
相关产品推荐

