簡體   English   中英

使用另一個 numpy ndarray 過濾 numpy ndarray

[英]Filter a numpy ndarray using another numpy ndarray

我有兩個相同形狀的(15081, 56724, 3, 3) 我想做的是如下:

假設我們有第一個數組array1[1, 1, :, :]的橫截面,如下所示:

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

我想將它轉換為 boolean ,每行的最大值為True , rest 為False 在整個數組中,這對應於axis=3 所以數組在轉換后看起來像這樣:

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

現在我想過濾另一個數組array2 ,使用這個 boolean 數組得到如下所示的內容。 我只想保留array1中與True對應的array2的那些值,並將 rest 設置為零。

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

我可以使用循環來做到這一點,但它需要一定的時間(甚至更多)。 我期待類似numpy.where(array1.is_max(axis=3), True, False)的東西,但是在 python 中沒有像is_max這樣的 function,除此之外軸 3 被折疊並且我無法使用array1過濾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_axisnp.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]])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM