我有大约 100,000 个二维数组,我需要在其中应用本地过滤器。两个维度的大小相同,窗口超过 2x2 block 并进一步移动 2 block ,因此每个元素都在窗口中一次。输出是一个相同大小的二进制二维数组,我的过滤器也是一个二进制 2x2 block 。我的过滤器的 0 部分将映射到 0,我的过滤器的 1 部分如果它们具有相同的值则全部映射到 1,如果它们不完全相同则映射到 0。这是一个例子:
Filter: 0 1 Array to filter: 1 2 3 2 Output: 0 1 0 0
1 0 2 3 3 3 1 0 0 0
当然我可以使用双 for 循环来做到这一点,但是这是非常低效的,必须有更好的方法。我读到这个:Vectorized moving window on 2D array in numpy但是我不确定如何将其应用到我的案例中。
最佳答案
您可以拆分每个 2x2
子数组,然后重新整形,使每个窗口 block 成为 2D
数组中的一行。
使用 boolean indexing
从每一行中提取出与 f==1
位置对应的元素.
然后,查看每行中所有提取的元素是否相同,以给我们一个掩码。使用此掩码与 f
相乘以获得整形后的最终二进制输出。
因此,假设 f
为过滤器数组,A
为数据数组,遵循这些步骤的矢量化实现如下所示 -
# Setup size parameters
M = A.shape[0]
Mh = M/2
N = A.shape[1]/2
# Reshape input array to 4D such that the last two axes represent the
# windowed block at each iteration of the intended operation
A4D = A.reshape(-1,2,N,2).swapaxes(1,2)
# Determine the binary array whether all elements mapped against 1
# in the filter array are the same elements or not
S = (np.diff(A4D.reshape(-1,4)[:,f.ravel()==1],1)==0).all(1)
# Finally multiply the binary array with f to get desired binary output
out = (S.reshape(Mh,N)[:,None,:,None]*f[:,None,:]).reshape(M,-1)
sample 运行-
1) 输入:
In [58]: A
Out[58]:
array([[1, 1, 1, 1, 2, 1],
[1, 1, 3, 1, 2, 2],
[1, 3, 3, 3, 2, 3],
[3, 3, 3, 3, 3, 1]])
In [59]: f
Out[59]:
array([[0, 1],
[1, 1]])
2) 中间输出:
In [60]: A4D
Out[60]:
array([[[[1, 1],
[1, 1]],
[[1, 1],
[3, 1]],
[[2, 1],
[2, 2]]],
[[[1, 3],
[3, 3]],
[[3, 3],
[3, 3]],
[[2, 3],
[3, 1]]]])
In [61]: S
Out[61]: array([ True, False, False, True, True, False], dtype=bool)
3) 最终输出:
In [62]: out
Out[62]:
array([[0, 1, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0],
[1, 1, 1, 1, 0, 0]])
关于python - 在移动窗口 numpy 数组上有效地应用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37514204/