Python中高效将二维数组分割为逆时针补丁的最优方法
用Numpy高效提取二维数组的矩形补丁顶点
给定尺寸为(W,H)的二维数组(例如示例中的(3,4)),将数组内每个点视为矩形补丁的顶点。要求按行优先顺序,从每个补丁的左上角顶点开始逆时针提取四个顶点,生成尺寸为((W-1)*(H-1),4)的二维数组(示例对应(6,4))。目前已通过双重循环实现功能,现寻求仅用Python基础函数和Numpy的更高效实现方式。
现有双重循环实现代码
import numpy as np A = np.array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) H = A.shape[0] W = A.shape[1] patches = [] for y in range(H-1): for x in range(W-1): patches.append([A[y, x], A[y+1, x], A[y+1, x+1], A[y, x+1]]) patches = np.array(patches) print(patches)
高效矢量化实现方法
方法一:切片拼接+重塑
利用Numpy切片直接提取四个顶点的区域,通过矢量化操作替代循环,效率大幅提升:
import numpy as np A = np.array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) # 提取四个顶点对应的一维数组(行优先展平) top_left = A[:-1, :-1].ravel() bottom_left = A[1:, :-1].ravel() bottom_right = A[1:, 1:].ravel() top_right = A[:-1, 1:].ravel() # 按顺序拼接为目标形状 patches = np.stack([top_left, bottom_left, bottom_right, top_right], axis=1) print(patches)
操作说明:
A[:-1, :-1]:取所有行(除最后一行)、所有列(除最后一列),对应所有补丁的左上角顶点;ravel():将二维区域展平为一维,保证行优先的顺序;np.stack(..., axis=1):将四个一维数组按列拼接,每行对应一个补丁的四个顶点。
方法二:滑动窗口(Numpy 1.20+)
若使用Numpy 1.20及以上版本,可借助sliding_window_view直观提取补丁窗口,再提取目标顶点:
import numpy as np from numpy.lib.stride_tricks import sliding_window_view A = np.array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) # 生成所有2x2的补丁窗口 windows = sliding_window_view(A, window_shape=(2, 2)) # 从每个窗口中提取逆时针四个顶点:(0,0), (1,0), (1,1), (0,1) patches = windows[:, :, [[0,1,1,0], [0,0,1,1]]].reshape(-1, 4) print(patches)
操作说明:
sliding_window_view(A, (2,2)):生成形状为((H-1),(W-1),2,2)的数组,每个元素是对应位置的2x2补丁窗口;[:, :, [[0,1,1,0], [0,0,1,1]]]:按索引从每个窗口中提取指定的四个顶点;reshape(-1,4):将结果展平为((H-1)*(W-1),4)的目标形状。
以上两种方法均为矢量化操作,避免了Python循环的开销,在处理大尺寸数组时,效率会远高于原循环实现。
内容的提问来源于stack exchange,提问作者KyroHere
相关产品推荐
相关产品推荐

