[英]Majority filter Numpy array
我有一個由零、一和 NaN 組成的 numpy ndarray。 我想在該數組上使用多數過濾器,這意味着我想設置一個內核窗口(例如,3X3 單元格),它將遍歷數組並將中心單元格的值更改為發生的值在其鄰居中最多。 這個過濾器應該維持兩個約束,它應該忽略 NaN,如果中心單元格的值為 1,那么它應該保持為 1。
這是我正在尋找的一個小例子:輸入數組:
array([[ 1., 1., 1., 0., 0.],
[ 1., 1., nan, 1., 1.],
[nan, 1., 1., 0., 1.],
[ 0., 0., 0., 0., 1.]])
應用多數過濾器輸出數組:
array([[ 1., 1., 1., 1., 1.],
[ 1., 1., nan, 1., 1.],
[nan, 1., 1., 1., 1.],
[ 0., 0., 0., 1., 1.]])
我正在查看scipy 過濾器,但找不到任何足夠的東西。 我想建立一個通用的卷積過濾器,但我不確定如何為大多數目的做到這一點。 感覺這是應該存在的基本過濾器,但我似乎找不到它。
這是一個基於convolution
矢量化思想。 鑒於這些限制,我們似乎只需要編輯0s
位。 對於每個滑動窗口,獲取 1 的計數,然后是非 NaN,這決定了決定 1 是否為多數的閾值。 如果是,將那些也是 0 的地方設置為 1。
實現看起來像這樣 -
from scipy.signal import convolve2d
def fill0s(a):
# Mask of NaNs
nan_mask = np.isnan(a)
# Convolution kernel
k = np.ones((3,3),dtype=int)
# Get count of 1s for each kernel window
ones_count = convolve2d(np.where(nan_mask,0,a),k,'same')
# Get count of elements per window and hence non NaNs count
n_elem = convolve2d(np.ones(a.shape,dtype=int),k,'same')
nonNaNs_count = n_elem - convolve2d(nan_mask,k,'same')
# Compare 1s count against half of nonNaNs_count for the first mask.
# This tells us if 1s are majority among non-NaNs population.
# Second mask would be of 0s in a. Use Combined mask to set 1s.
final_mask = (ones_count >= nonNaNs_count/2.0) & (a==0)
return np.where(final_mask,1,a)
請注意,由於我們正在使用那種 1s 內核執行統一過濾,因此我們也可以使用uniform_filter
。
樣品運行 -
In [232]: a
Out[232]:
array([[ 1., 1., 1., 0., 0.],
[ 1., 1., nan, 1., 1.],
[nan, 1., 1., 0., 1.],
[ 0., 0., 0., 0., 1.]])
In [233]: fill0s(a)
Out[233]:
array([[ 1., 1., 1., 1., 1.],
[ 1., 1., nan, 1., 1.],
[nan, 1., 1., 1., 1.],
[ 0., 0., 0., 1., 1.]])
試試下面的代碼:
請注意,結果與您的有點不同,這是由於 numpy.argmax 在多個索引具有相同最大值時的行為(您可能想要編寫自己的 argmax 函數... x=np.argwhere(x==np .max(x))[:,0] 給出所有索引而不是第一個)
import numpy as np
def block_fn(x,center_val):
unique_elements, counts_elements = np.unique(x.ravel(), return_counts=True)
if np.isnan(center_val):
return np.nan
elif center_val == 1:
return 1.0
else:
return unique_elements[np.argmax(counts_elements)]
def majority_filter(x,block_size = (3,3)):
#Odd block sizes only ( ? )
assert(block_size[0]%2 != 0 and block_size[1]%2 !=0)
yy =int((block_size[0]-1)/2)
xx =int((block_size[1]-1)/2)
output= np.zeros_like(x)
for i in range(0,x.shape[0]):
miny,maxy = max(0,i-yy),min(x.shape[0]-1,i+yy)
for j in range(0,x.shape[1]):
minx,maxx = max(0,j-xx),min(x.shape[1]-1,j+xx)
#Extract block to take majority filter over
block=x[miny:maxy+1,minx:maxx+1]
output[i,j] = block_fn(block,center_val=x[i,j])
return output
inp=np.array([[ 1., 1., 1., 0., 0.],
[ 1., 1., np.nan, 1., 1.],
[np.nan, 1., 1., 0., 1.],
[ 0., 0., 0., 0., 1.]])
print(majority_filter(inp))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.