Фильтр с оконным/скользящим средним, учитывающий допустимые элементы на границе

Есть ли аналогичная функция для uniform_filter или convolve scipy.ndimage (аналогичная проблема с Двумерная скользящая средняя Numpy), но среднее значение рассчитывается с использованием только значений во входном массиве (игнорируйте количество значений заполнения для угловых и краевых ячеек). Аналогичная функция, в которой значение заполнения может быть установлено равным 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(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.        ]])

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
342
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

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

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

Я уже пробовал этот и другие режимы. Независимо от значения заполнения, я хотел, чтобы они были замаскированы при расчете среднего значения.

gsm17 29.05.2019 07:45

Не могли бы вы предоставить ожидаемый результат. Прямо сейчас вопрос кажется открытым.

Surya Palaniswamy 29.05.2019 07:47
Ответ принят как подходящий

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

Другие вопросы по теме