我曾经创建了这个函数来将二维数组中的滑动块存储到列中,这样我们曾经认为在二维数组的滑动窗口中应用的任何操作都可以很容易地沿着列应用。阅读更多关于它的this solution
信息Implement Matlab's im2col 'sliding' in python
。
现在,NumPy 支持沿指定轴应用其大部分功能。因此,使用这个工具,我们将能够有效地以某种vectorized
方式在滑动窗口中应用几乎任何操作。这是它的正式定义-
def im2col(A,BLKSZ):
# Parameters
M,N = A.shape
col_extent = N - BLKSZ[1] + 1
row_extent = M - BLKSZ[0] + 1
# Get Starting block indices
start_idx = np.arange(BLKSZ[0])[:,None]*N + np.arange(BLKSZ[1])
# Get offsetted indices across the height and width of input array
offset_idx = np.arange(row_extent)[:,None]*N + np.arange(col_extent)
# Get all actual indices & index into input array for final output
return np.take (A,start_idx.ravel()[:,None] + offset_idx.ravel())
下面是我们如何使用这个工具来解决手头的问题,假设A
为 2D 输入数组 -
# Get 3x3 sliding blocks from A and set them as columns.
Acol = im2col(A,[3,3])
# Setup kernel mask
kernel = np.ones((3,3),dtype=bool)
kernel[2,1:] = 0
# Mask rows of Acol with kernel and perform any operation, let's say MAX
out = Acol[kernel.ravel()].max(0).reshape(A.shape[0]-2,A.shape[1]-2)
样品运行 -
In [365]: A
Out[365]:
array([[83, 84, 46, 9, 25],
[32, 8, 31, 45, 58],
[14, 8, 0, 51, 27],
[31, 40, 7, 27, 71]])
In [366]: kernel = np.ones((3,3),dtype=bool)
...: kernel[2,1:] = 0
...:
In [367]: im2col(A,[3,3])[kernel.ravel()].max(0).reshape(A.shape[0]-2,A.shape[1]-2)
Out[367]:
array([[84, 84, 58],
[32, 51, 58]])