我有大约100,000个二维数组,我需要应用本地过滤器。两个尺寸均匀,窗口超过2x2,进一步移动2个,因此每个元素都在一个窗口中。输出是相同大小的二进制二维数组,我的过滤器也是二进制2x2。我的过滤器的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
当然我可以使用double for循环来做到这一点,但这是非常低效的,必须有更好的方法。我读到这个:Vectorized moving window on 2D array in numpy但我不确定如何将其应用于我的案例。
答案 0 :(得分:4)
您可以拆分每个2x2
子阵列,然后重新整形,使每个窗口块成为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)
示例运行 -
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]])