动态改变 scipys ndimage 过滤器中的过滤器大小

Dynamically varying the filter size in the scipys ndimage filters

How exactly does the “reflect” mode for scipys ndimage filters work? and Numpy Two-Dimensional Moving Average 之后,我有一个二维数组:

a
=> 
np.array([[ 0.,   1.,   2.,   3.,   4.],
       [  5.,   6.,   7.,   8.,   9.],
       [ 10.,  11.,  12.,  13.,  14.],
       [ 15.,  16.,  17.,  18.,  19.],
       [ 20.,  21.,  22.,  23.,  24.]])

当我使用 mode=constant3x3 filter size:

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

结果是:

=> 
array([[  1.33333333,   2.33333333,   3.        ,   3.66666667,          2.66666667],
       [  3.66666667,   6.        ,   7.        ,   8.        ,          5.66666667],
       [  7.        ,  11.        ,  12.        ,  13.        ,          9.        ],
       [ 10.33333333,  16.        ,  17.        ,  18.        ,         12.33333333],
       [  8.        ,  12.33333333,  13.        ,  13.66666667,          9.33333333]])

我了解此过滤器的内部工作原理,因为我在上面发布的链接中对其进行了很好的解释。

我的问题是,是否可以将数组中每个位置的总和除以值大于零的元素总数?

因此,例如,在我的数组中位置 [0,0] 中元素为 0,元素 (0, 0, 0, 0, 0, 1, 0, 5, 6) 的总和将除以 3(仅位置 [0,1] = 1、[1,0] = 5 和 [1,1] = 6 的值大于零)而不是 9。在数组的 [0,1] 位置,我将除以 5。在位置 [0,2],我除以 6,在位置 [1,2],我除以 9

在这种情况下,我的回答应该是;

=> 
array([[ 4.0 ,  4.2 ,  4.5 ,  5.5 ,  6.0  ],
       [ 6.60,  6.75,  7.0 ,  8.0 ,  8.5  ],
       [ 10.5,  11. ,  12. ,  13. ,  13.5 ],
       [ 15.5,  16. ,  17. ,  18. ,  18.5 ],
       [ 18.0,  18.5,  19.5,  20.5,  21.0 ]])

这是一种方法 -

from scipy.ndimage.filters import uniform_filter
from scipy.signal import convolve2d

size = 3       
kernel = np.ones((size,size),dtype=int)  
nonzero_count = convolve2d(a!=0, kernel,'same')
windowed_sum = uniform_filter(a, size=size, mode='constant')*size**2
out = windowed_sum/nonzero_count

步骤:

  • 获取形状滑动 windows 中的非零数:(size,size) 沿输入数组的行和列。 为此,我们可以使用 2D 卷积,所有 ones 的内核与内核具有相同的形状。或者,我们也可以使用 uniform_filter 获得非零计数:uniform_filter((a!=0).astype(float), size=size, mode='constant')*size**2.

  • 通过重新使用 uniform_filter 输出的平均值并按 size**2 缩放来获得滑动求和。或者,我们可以在这里再次使用 2D 卷积与 convolve2d(a, kernel,'same').

  • 最后,将这些总和除以非零计数,即所需的输出。

样本输入、中间输出和最终输出 -

In [51]: a
Out[51]: 
array([[  0.,   1.,   2.,   3.,   4.],
       [  5.,   6.,   7.,   8.,   9.],
       [ 10.,  11.,  12.,  13.,  14.],
       [ 15.,  16.,  17.,  18.,  19.],
       [ 20.,  21.,  22.,  23.,  24.]])

In [53]: nonzero_count
Out[53]: 
array([[3, 5, 6, 6, 4],
       [5, 8, 9, 9, 6],
       [6, 9, 9, 9, 6],
       [6, 9, 9, 9, 6],
       [4, 6, 6, 6, 4]])

In [54]: windowed_sum
Out[54]: 
array([[  12.,   21.,   27.,   33.,   24.],
       [  33.,   54.,   63.,   72.,   51.],
       [  63.,   99.,  108.,  117.,   81.],
       [  93.,  144.,  153.,  162.,  111.],
       [  72.,  111.,  117.,  123.,   84.]])

In [55]: out
Out[55]: 
array([[  4.  ,   4.2 ,   4.5 ,   5.5 ,   6.  ],
       [  6.6 ,   6.75,   7.  ,   8.  ,   8.5 ],
       [ 10.5 ,  11.  ,  12.  ,  13.  ,  13.5 ],
       [ 15.5 ,  16.  ,  17.  ,  18.  ,  18.5 ],
       [ 18.  ,  18.5 ,  19.5 ,  20.5 ,  21.  ]])