Фильтр оконного / скользящего среднего учитывает действительные элементы на границе - PullRequest
2 голосов
/ 29 мая 2019

Существует ли функция, аналогичная функции scipy.ndimageiform_filter или convolve (аналогичная проблема с Numpy двумерное скользящее среднее ), но среднее значение рассчитывается с использованием только значений во входном массиве (без учета числа заполнить значения для угловых и краевых ячеек). Аналогичная функция, в которой значение заполнения может быть установлено в np.nan, а полученное среднее значение рассчитывается как np.nanmean?

Мой исходный код перебирает массив, чтобы получить соседей и вычислить полученное среднее, но этот метод занимает слишком много времени. Я пробовал иiform_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.]])

iform_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.        ]])

Значения рассчитываются, как показано в этом иллюстрация

Ответы [ 2 ]

1 голос
/ 29 мая 2019

Попробуйте изменить код на

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

Это должно избежать проблемы заполнения нулями для значений ребер

Проверьте это для других режимов, которые вы можете предпочесть: https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.uniform_filter.html

0 голосов
/ 29 мая 2019

Получите оконные суммы и разделите их на действительные элементы в каждом окне.Мы можем использовать 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.        ]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...