在scipys ndimage过滤器

时间:2017-07-24 09:39:06

标签: python numpy image-processing filtering moving-average

关注How exactly does the “reflect” mode for scipys ndimage filters work?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 ]])

1 个答案:

答案 0 :(得分:2)

这是一种方法 -

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

步骤:

  • 沿着输入数组的行和列,在形状:(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.  ]])