与binary_dilation相反

问题描述 投票:1回答:1

是否有与binary_dilation相反的功能?我想从0和1的数组中删除'islands'。也就是说,如果2D数组中的值1不具有至少1个也是1的相邻邻居,则其值被设置为0(而不是将其邻居的值设置为等于binary_dilation中的1)。例如:

test = np.zeros((5,5))
test[1,1] = test[1,2] = test[3,3] = test[4,3] = test[0,3] = test[3,1] = 1

test
array([[0., 0., 0., 1., 0.],
       [0., 1., 1., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 1., 0., 1., 0.],
       [0., 0., 0., 1., 0.]])

而我正在寻求的功能将返回:

array([[0., 0., 0., 0., 0.],
       [0., 1., 1., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 1., 0.]])

请注意,位置[0,3]和[3,1]中的值从1更改为0,因为它们没有相邻的邻居,其值等于1(对角线不计为邻居)。

python numpy
1个回答
2
投票

您可以使用要检查的细胞创建一个遮罩,并使用test进行2d卷积,以识别与它们相邻的1s的细胞。逻辑和卷积和test应产生所需的输出。

首先定义你的面具。由于您只需要查找上/下和左/右邻接,因此您需要以下内容:

mask = np.ones((3, 3))
mask[1,1] = mask[0, 0] = mask[0, 2] = mask[2, 0] = mask[2, 2] = 0
print(mask)
#array([[0., 1., 0.],
#       [1., 0., 1.],
#       [0., 1., 0.]])

如果你想包括对角元素,你只需更新mask以在角落中包含1s。

现在应用testmask的2d卷积。这将乘以并添加两个矩阵的值。使用此掩码,这将具有返回每个单元格的所有相邻值的总和的效果。

from scipy.signal import convolve2d
print(convolve2d(test, mask, mode='same'))
#array([[0., 1., 2., 0., 1.],
#       [1., 1., 1., 2., 0.],
#       [0., 2., 1., 1., 0.],
#       [1., 0., 2., 1., 1.],
#       [0., 1., 1., 1., 1.]])

您必须指定mode='same',因此结果与第一个输入(test)的大小相同。请注意,您要从test中删除的两个单元格是卷积输出中的0

最后使用此输出和and执行元素明智的test操作以找到所需的单元格:

res = np.logical_and(convolve2d(test, mask, mode='same'), test).astype(int)
print(res)
#array([[0, 0, 0, 0, 0],
#       [0, 1, 1, 0, 0],
#       [0, 0, 0, 0, 0],
#       [0, 0, 0, 1, 0],
#       [0, 0, 0, 1, 0]])

更新

对于最后一步,您也可以只在clip卷积在0和1之间的值,并进行元素乘法。

res = convolve2d(test, mask, mode='same').clip(0, 1)*test
#array([[0., 0., 0., 0., 0.],
#       [0., 1., 1., 0., 0.],
#       [0., 0., 0., 0., 0.],
#       [0., 0., 0., 1., 0.],
#       [0., 0., 0., 1., 0.]])
© www.soinside.com 2019 - 2024. All rights reserved.