我有一个由0和1组成的numpy数组(数据)。
import numpy as np
data = np.array([[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0],
[1, 1, **1**, 1, 1, 0],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1]])
我想提取指数' 1'周围是由1s组成的相邻5 * 5元素。
预期指数用星号表示,即(3,3)。 布尔数组形式的答案也没问题。
[[False False False False 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]]
我试过
from scipy.ndimage.morphology import binary_erosion
kernel = np.ones((5,5))
result = binary_erosion(data, kernel)
print result
[[False False False False False False]
[False False False False False False]
[False False True False False False]
[False False True False False False]
[False False False False False False]
[False False False False False False]]
它产生了两个真实的'我只想要一个位置(3,3)。
怎么做?
编辑:链接问题中显示的解决方案也给出了意想不到的答案。
答案 0 :(得分:2)
除binary_erosion
之外,您可以使用scipy.ndimage.generic_filter
来实现此目的,
from scipy.ndimage import generic_filter
generic_filter(data, np.all, size=(5,5), mode='constant', cval=0).astype(np.bool)
但是,您将获得与上述相同的结果,
array([[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]) # using 1, 0 instead of True, False for readability
因为这是您问题的正确答案。示例矩阵中的6行是对称的,对于给定的内核,结果中将有2个对称True
元素。
如果你想避免这种情况,你可以使用非对称内核大小:size=(6,5)
,虽然这会在第3行产生一个真正的元素而不是第2行。这可以修复,手动填充{{1使用kernel
时使用零的数组。
答案 1 :(得分:1)
另一种类似于@rth
的方法由于您的数据来自1
和0
,因此您可以将其放在int
数组中并使用uniform_filter
来实现相同的目标:
>>> mask = uniform_filter(data, 5, mode='constant')
>>> mask
array([[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]])
未被1包围的平均值小于1
并且舍入为0
,因为它是整数数组。
要获得第一个索引,您可以执行以下操作:
>>> y, x = np.where(mask)
>>> y[0], x[0]
(2, 2)