使用另一个 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]])
我有两个相同形状的 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]])