使用另一个 numpy ndarray 过滤一个 numpy ndarray

Filter a numpy ndarray using another numpy ndarray

我有两个相同形状的 numpy ndarrays (15081, 56724, 3, 3)。我想做的事情如下:

假设我们有第一个数组的横截面,array1[1, 1, :, :],看起来像这样:

[[120, 110, 220],
 [ 85,  99,  72],
 [197,  80,  75]]

我想将其转换为布尔值,每行的最大值为 True,其余为 False。在整个数组中,这对应于axis=3。所以数组在转换后看起来像这样:

[[False, False,  True],
 [False,  True, False],
 [ True, False, False]]

现在我想过滤另一个数组 array2,使用这个布尔数组得到如下所示的内容。我只想保留 array2 对应于 array1 中的 True 的那些值,并将其余值设置为零。

[[  0,   0,  65],
 [  0, 179,   0],
 [125,   0,   0]]

我可以使用循环来做到这一点,但它需要一定的时间(甚至更多)。 我期待像 numpy.where(array1.is_max(axis=3), True, False) 这样的东西,但是 python 中没有像 is_max 这样的功能,除此之外轴 3 被折叠并且我无法使用 [=21= 过滤 array2 ].

在 numpy 中,is_max 大约是 argmax:

indices = array1.argmax(axis=-1)

这将为您提供线性索引,而不是掩码,因此您可以这样做

array2b = np.zeros_like(array2)
index = np.indices(array2.shape[:-1], sparse=True) + (indices,)
array2b[index] = array1[index]

你可以用np.take_along_axis and np.put_along_axis做类似的事情:

indices = np.expand_dims(array1.argmax(-1), array1.ndim - 1)
array2b = np.zeros_like(array2)
np.put_along_axis(array2b, indices, np.take_along_axis(array2, indices, -1), -1)

如果你想要一个基于掩码的方法,你可以像这样创建掩码:

mask = array1 != array1.max(-1, keepdims=True)

现在可以直接将所有元素置零:

array2[mask] = 0

或者你可以做类似的事情

mask = array1 == array1.max(-1, keepdims=True)
array2 *= mask

更新

根据您在评论中的描述,您正在寻找完全不同的操作。您可以从 array1 阈值开始(我假设它代表模糊图像和原始图像之间的差异):

mask = array1 >= 100  # find a threshold that works
array2 *= mask

mask = array1 < 100
array2[mask] = 0

您可能也在寻找图像中的局部最小值。您可以通过找到比周围环境大的像素来获得这些像素。为此,运行 图像上的非线性滤波器,如 scipy.ndimage.maximum_filter:

 mask = array1 == scipy.ndimage.maximum_filter(array1, 5)
 array2 *= mask

可以用

完成
array2[array1 != np.tile(np.max(array1,axis=1), (array1.shape[0],1)).T] = 0

方法如下。

对于您的特定示例,我建议使用 np.tile,您可以在其中使用一维蒙版中的元素创建重复图案。

假设我们的矩阵 a 具有值

array1 = [[120, 110, 220]
          [85, 99, 72]
          [197, 80, 75]]

那么矩阵每一行的最大值为

maxes = np.max(array1,axis=1)

这将具有值

array([220,  99, 197])

现在,我们需要在每一行的每一行元素中使用这些值中的每一个。简单来说,我们需要将220与第一行的每个元素进行比较。这意味着实际上我们需要重复值 220,以便能够在单个向量中执行操作,这可以通过以下方式完成:

np.tile(maxes, (array1.shape[0],1)).T

这给了我们

array([[220, 220, 220],
       [ 99,  99,  99],
       [197, 197, 197]])

过滤相当简单:

a != np.tile(maxes, (3,1)).T 

足以创建面具。

长话短说,操作可以在单个衬里完成,如下所示

array2[array1 != np.tile(maxes, (a.shape[0],1)).T] = 0

这使得 a 具有以下值

array2 = array([[0, 0, 65]
                [0, 179, 0]
                [125, 0, 0]])