Использование страйдов для эффективного фильтра скользящего среднего

Я недавно узнал о strides в ответе на этот пост и задался вопросом, как я могу использовать их для вычисления фильтра скользящего среднего более эффективно, чем то, что я предложил в этом посте (используя фильтры свертки).

Вот что у меня получилось на данный момент. Он берет представление исходного массива, затем сворачивает его на необходимую величину и суммирует значения ядра для вычисления среднего. Я знаю, что края обрабатываются неправильно, но я могу позаботиться об этом позже... Есть ли лучший и более быстрый способ? Цель состоит в фильтрации больших массивов с плавающей запятой размером до 5000x5000 x 16 слоев, задача, с которой scipy.ndimage.filters.convolve справляется довольно медленно.

Обратите внимание, что я ищу 8-соседнюю связность, то есть фильтр 3x3 берет среднее значение из 9 пикселей (8 вокруг фокального пикселя) и присваивает это значение пикселю в новом изображении.

import numpy, scipy

filtsize = 3
a = numpy.arange(100).reshape((10,10))
b = numpy.lib.stride_tricks.as_strided(a, shape=(a.size,filtsize), strides=(a.itemsize, a.itemsize))
for i in range(0, filtsize-1):
    if i > 0:
        b += numpy.roll(b, -(pow(filtsize,2)+1)*i, 0)
filtered = (numpy.sum(b, 1) / pow(filtsize,2)).reshape((a.shape[0],a.shape[1]))
scipy.misc.imsave("average.jpg", filtered)

EDIT Уточнение того, как я вижу, как это работает:

Текущий код:

  1. используйте stride_tricks для создания массива типа [[0,1,2],[1,2,3],[2,3,4]...], который соответствует верхней строке ядра фильтра.
  2. Прокрутите вдоль вертикальной оси, чтобы получить средний ряд ядра [[10,11,12],[11,12,13],[13,14,15]...] и добавьте его к массиву, который я получил в пункте 1)
  3. Повторите, чтобы получить нижний ряд ядра [[20,21,22],[21,22,23],[22,23,24]...]. На этом этапе я беру сумму каждого ряда и делю ее на количество элементов в фильтре, получая среднее значение для каждого пикселя (сдвинутое на 1 row и 1 col, и с некоторыми странностями по краям, но об этом я позабочусь позже).

Я надеялся на лучшее использование stride_tricks для получения 9 значений или суммы элементов ядра напрямую, для всего массива, или на то, что кто-то сможет убедить меня в другом более эффективном методе...

29
задан Community 23 May 2017 в 12:02
поделиться