窗口/滑动均值滤波器,计算边界处的有效成员

时间:2019-05-29 05:11:39

标签: python numpy scipy

是否有与scipy.ndimage的uniform_filter或卷积函数相似(与Numpy Two-Dimensional Moving Average类似的问题),但平均值仅使用输入数组中的值计算(忽略角和边单元的填充值计数) )。一个类似的函数,其中填充值可以设置为np.nan,结果平均值计算为np.nanmean?

我的初始代码遍历数组以获取邻居并计算所得均值,但是此方法花费的时间太长。我已经尝试了Uniform_filter或convolve,但是结果不是我所需要的,因为所得到的角和边值太低(由于用0填充边)。

例如,如果我有数组:

a = np.ones((4,5))

从移动的3x3数组计算平均值也应得出:

array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

uniform_filter给出:

uniform_filter(a, size=3, mode='constant', cval=0.0)

array([[0.44444444, 0.66666667, 0.66666667, 0.66666667, 0.44444444],
       [0.66666667, 1.        , 1.        , 1.        , 0.66666667],
       [0.66666667, 1.        , 1.        , 1.        , 0.66666667],
       [0.44444444, 0.66666667, 0.66666667, 0.66666667, 0.44444444]])

我尝试设置cval = np.nan,但是单元格边缘的结果值为nan。

对于另一个数组,b

array([[1., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

我想使用3x3的平均窗口来获得一个数组,

array([[0.25      , 0.16666667, 0.        ],
       [0.16666667, 0.11111111, 0.        ],
       [0.        , 0.        , 0.        ]])

如下所示计算值 illustration

2 个答案:

答案 0 :(得分:1)

尝试将代码更改为

uniform_filter(a, size=3, mode='wrap')

这应该避免边缘值用零填充的问题

查看此选项以了解您可能更喜欢的其他模式: https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.uniform_filter.html

答案 1 :(得分:0)

获取窗口加总并除以每个窗口中的有效成员。我们可以使用scipy.signal.convolve2d来获得两者,因此有一个类似的解决方案-

from scipy.signal import convolve2d

def windowed_average(a, kernel_size, mode='same'):
    k = np.ones((kernel_size,kernel_size),dtype=int)
    window_sum = convolve2d(a,k,mode)
    window_count = convolve2d(np.ones(a.shape, dtype=bool),k,mode)
    return window_sum/window_count

替代#1

或者,如果您想使用uniform_filter来获取窗口加和,我们可以这样做,并且这样可能会更有效-

from scipy.ndimage import uniform_filter

n = kernel_size**2
window_sum = uniform_filter(a, kernel_size, mode='constant', cval=0.0)*n

样品运行-

In [54]: a
Out[54]: 
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

In [55]: windowed_average(a, kernel_size=3)
Out[55]: 
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

In [56]: b
Out[56]: 
array([[1., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

In [57]: windowed_average(b, kernel_size=3)
Out[57]: 
array([[0.25      , 0.16666667, 0.        ],
       [0.16666667, 0.11111111, 0.        ],
       [0.        , 0.        , 0.        ]])