通过Numpy阵列优化迭代,以进行邻居检查



是否可以通过检查邻居检查以下迭代:

for i in range(1, A.shape[0]):
    for j in range(1, A.shape[1]):
        v = (A[i, j], A[i-1,j-1], A[i-1, j], A[i, j-1])
        if v == something: print(v)

其中 A是一个(非常大的(numpy阵列为0和1, vsomething是元组(例如(0,1,1,0,0,0((。

首先创建测试数据:

import numpy as np
np.random.seed(1)
A = np.random.randint(0, 2, size=(10, 8)).astype(np.uint8)

a:

array([[1, 1, 0, 0, 1, 1, 1, 1],
       [1, 0, 0, 1, 0, 1, 1, 0],
       [0, 1, 0, 0, 0, 1, 0, 0],
       [1, 0, 0, 0, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 1, 0, 1],
       [1, 0, 0, 1, 0, 0, 1, 1],
       [1, 0, 1, 0, 0, 1, 1, 0],
       [1, 1, 1, 1, 0, 0, 1, 1],
       [0, 0, 0, 0, 1, 1, 1, 0]], dtype=uint8)

然后创建一个使用位来表示邻居值的数组:

a = A[:-1, :-1] << 3
a |= A[:-1, 1:] << 2
a |= A[1:, :-1] << 1
a |= A[1:, 1:]

检查邻居的值

11
00

您可以使用:

a == int("1100", 2)

输出:

array([[False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False],
       [False,  True, False, False,  True, False, False],
       [False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False],
       [ True,  True,  True, False, False, False, False]], dtype=bool)

这是 @matt.st在评论中建议的基于卷积的方法。

>>> import numpy as np
>>> from scipy import signal
>>> a = np.random.randint(0, 2, (n, n))
>>> t = np.random.randint(0, 2, (2, 2))
>>> 
>>> 
>>> tt = 2*t[::-1, ::-1] - 1
>>> ts = t.sum()
>>> 
>>> result = signal.convolve2d(a, tt, 'valid') == ts
>>> 
>>> a
array([[1, 0, 1, 0, 1, 0, 0, 1, 0, 1],
       [0, 1, 1, 1, 0, 1, 1, 1, 0, 0],
       [0, 1, 0, 1, 1, 1, 0, 1, 0, 0],
       [0, 1, 1, 1, 0, 0, 1, 1, 1, 1],
       [1, 1, 0, 1, 1, 1, 1, 0, 1, 0],
       [1, 1, 0, 0, 1, 0, 0, 1, 1, 1],
       [1, 1, 1, 0, 1, 0, 0, 1, 1, 1],
       [0, 1, 0, 1, 0, 1, 0, 0, 1, 0],
       [0, 0, 0, 1, 1, 0, 0, 1, 0, 1],
       [1, 1, 0, 1, 0, 0, 1, 1, 1, 0]])
>>> t
array([[0, 1],
       [1, 1]])
>>> result
array([[False,  True, False, False, False, False,  True, False, False],
       [False, False, False, False,  True, False, False, False, False],
       [False, False,  True, False, False, False,  True, False, False],
       [ True, False, False, False, False,  True, False, False, False],
       [False, False, False, False, False, False, False,  True, False],
       [False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False,  True, False, False]], dtype=bool)

您要做的就是生成布尔条件的四个阵列。大致:

spot = A == v[0]
upleft = np.roll(A, (1,1), (0,1)) == v[1]
left = np.roll(A, 1, 1) == v[2]
up = np.roll(A, 1, 0) == v[3]

然后,您可以找到四个属性的地方:

res = spot & upleft & left & up

这为您提供了一个布尔数组,无论符合所有条件的地方,它都是真实的。您应该忽略第一行和列,因为它们无法计算:

res = res[1:,1:]
# or
res[0,:] = False
res[:,0] = False

最新更新