计算 numpy 数组中具有 2 个或更多邻居的单元格数
Calculate number of cells with 2 neighboors or more, within a numpy array
我正在努力实现与此类似的目标 。
objective是统计至少有两个直接邻居(上、下、左、右)的1的个数,与我的版本唯一不同的是序列中必须至少有一个交叉或角。
例如,
array([[0, 0, 0, 0, 0, 1],
[0, 1,*1, 1, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 1, 0],
[1, 0, 0, 0, 1, 0]])
带星标的 *1 不算在内,因为它的邻居没有形成角或十字。右上角 1 也没有,因为它没有两个邻居。答案是 2(右下角和左下角)。
这是我尝试过的:
import numpy as np
a = np.zeros((6,6), dtype=np.int)
a[0,5] = 1
a[1,1] = a[1,2] = a[1,3] = 1
a[4,4] = a[5,4] = a[4,3] = 1
a[3,0] = a[4,0] = a[5,0] = a[4,1] = 1
from scipy import ndimage
kernel = ndimage.generate_binary_structure(2, 1)
kernel[1, 1] = 0
b = convolve(a, kernel, mode="constant")
c = b[a>0]
# At least 2 neighbours
return len(c[c >= 2])
但它仍然从第二行开始计算加星标的 *1(returns 3 而不是 2)!
感谢您的帮助!
您正在尝试二维卷积。您可能想尝试一个“十字形”内核,这将导致相关单元格的 3 或更多(=1+2,1 来自中心的 1,2 来自邻居)。 signal.convolve2d
来自 scipy
完成此操作,如下所示:
import numpy as np
from scipy import ndimage
from scipy import signal
a = np.zeros((6,6), dtype=np.int)
a[0,5] = 1
a[1,1] = a[1,2] = a[1,3] = 1
a[4,4] = a[5,4] = a[4,3] = 1
a[3,0] = a[4,0] = a[5,0] = a[4,1] = 1
print(a)
#kernel = ndimage.generate_binary_structure(2, 1)
#kernel[1, 1] = 0
kernel = np.array([[0,1,0], [1,1,1], [0,1,0]])
#b = np.convolve(a, kernel, mode="constant")
#c = b[a>0]
b = signal.convolve2d(a, kernel, mode='same')
# At least 2 neighbours
#return len(c[c >= 2])
print(b)
print(np.where(b > 2, b, 0))
产生(我用 np.where
过滤了结果):
[[0 0 0 0 0 1]
[0 1 1 1 0 0]
[0 0 0 0 0 0]
[1 0 0 0 0 0]
[1 1 0 1 1 0]
[1 0 0 0 1 0]]
[[0 1 1 1 1 1]
[1 2 3 2 1 1]
[1 1 1 1 0 0]
[2 2 0 1 1 0]
[4 2 2 2 3 1]
[2 2 0 2 2 1]]
[[0 0 0 0 0 0]
[0 0 3 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[4 0 0 0 3 0]
[0 0 0 0 0 0]]
已正确识别 1 的位置(3 或 4)。
您的标准可以重述为“至少一个水平邻居和至少一个垂直邻居”。因此,无论您最终选择的邻居检测是不是在 2D 中,而是在 1D 中选择两次,一次是水平的,一次是垂直的:
例如,使用 scipy.ndimage
提供 convolve1d
:
import scipy.ndimage as sn
(sn.convolve1d(in_,(1,3,1),axis=0,mode="constant")>>2) & (sn.convolve1d(in_,(1,3,1),axis=1,mode="constant")>>2)
# array([[0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [1, 0, 0, 0, 1, 0],
# [0, 0, 0, 0, 0, 0]])
(in_
是 OP 中的示例数组。)
我正在努力实现与此类似的目标
例如,
array([[0, 0, 0, 0, 0, 1],
[0, 1,*1, 1, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 1, 0],
[1, 0, 0, 0, 1, 0]])
带星标的 *1 不算在内,因为它的邻居没有形成角或十字。右上角 1 也没有,因为它没有两个邻居。答案是 2(右下角和左下角)。
这是我尝试过的:
import numpy as np
a = np.zeros((6,6), dtype=np.int)
a[0,5] = 1
a[1,1] = a[1,2] = a[1,3] = 1
a[4,4] = a[5,4] = a[4,3] = 1
a[3,0] = a[4,0] = a[5,0] = a[4,1] = 1
from scipy import ndimage
kernel = ndimage.generate_binary_structure(2, 1)
kernel[1, 1] = 0
b = convolve(a, kernel, mode="constant")
c = b[a>0]
# At least 2 neighbours
return len(c[c >= 2])
但它仍然从第二行开始计算加星标的 *1(returns 3 而不是 2)!
感谢您的帮助!
您正在尝试二维卷积。您可能想尝试一个“十字形”内核,这将导致相关单元格的 3 或更多(=1+2,1 来自中心的 1,2 来自邻居)。 signal.convolve2d
来自 scipy
完成此操作,如下所示:
import numpy as np
from scipy import ndimage
from scipy import signal
a = np.zeros((6,6), dtype=np.int)
a[0,5] = 1
a[1,1] = a[1,2] = a[1,3] = 1
a[4,4] = a[5,4] = a[4,3] = 1
a[3,0] = a[4,0] = a[5,0] = a[4,1] = 1
print(a)
#kernel = ndimage.generate_binary_structure(2, 1)
#kernel[1, 1] = 0
kernel = np.array([[0,1,0], [1,1,1], [0,1,0]])
#b = np.convolve(a, kernel, mode="constant")
#c = b[a>0]
b = signal.convolve2d(a, kernel, mode='same')
# At least 2 neighbours
#return len(c[c >= 2])
print(b)
print(np.where(b > 2, b, 0))
产生(我用 np.where
过滤了结果):
[[0 0 0 0 0 1]
[0 1 1 1 0 0]
[0 0 0 0 0 0]
[1 0 0 0 0 0]
[1 1 0 1 1 0]
[1 0 0 0 1 0]]
[[0 1 1 1 1 1]
[1 2 3 2 1 1]
[1 1 1 1 0 0]
[2 2 0 1 1 0]
[4 2 2 2 3 1]
[2 2 0 2 2 1]]
[[0 0 0 0 0 0]
[0 0 3 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[4 0 0 0 3 0]
[0 0 0 0 0 0]]
已正确识别 1 的位置(3 或 4)。
您的标准可以重述为“至少一个水平邻居和至少一个垂直邻居”。因此,无论您最终选择的邻居检测是不是在 2D 中,而是在 1D 中选择两次,一次是水平的,一次是垂直的:
例如,使用 scipy.ndimage
提供 convolve1d
:
import scipy.ndimage as sn
(sn.convolve1d(in_,(1,3,1),axis=0,mode="constant")>>2) & (sn.convolve1d(in_,(1,3,1),axis=1,mode="constant")>>2)
# array([[0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [1, 0, 0, 0, 1, 0],
# [0, 0, 0, 0, 0, 0]])
(in_
是 OP 中的示例数组。)