Сверточное размывание изображения - питон

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

import scipy
import scipy.signal
import numpy as np

def boxBlur(image):
    matrix = np.array(image)
    W = np.array([[1, 1, 1],
              [1, 1, 1],
              [1, 1, 1]])
    np.pad(matrix, 1, mode='constant')
    return scipy.signal.convolve2d(matrix, W, mode='valid')

Итак, для этого примера:

boxBlur([[1,1,1],[1,7,1],[1,1,1]])

Прямой выходной сигнал сейчас равен [[15]], но он должен быть [[1]] (15/9=1 6666 округлено в сторону уменьшения =1)

Есть ли способ не только использовать свернутые изображения на матрице, но и делать что-то еще.

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

1 ответ

Решение

Это называется равномерной фильтрацией, поэтому используйте SciPy uniform_filter, который должен быть быстрее -

from scipy.ndimage import uniform_filter

uniform_filter(image.astype(float))[1:-1,1:-1]

Пробный прогон -

In [38]: np.random.seed(0)
    ...: image = np.random.randint(0,9,(7,7))

In [39]: boxBlur(image)/9.0
Out[39]: 
array([[4.55555556, 5.        , 5.55555556, 5.44444444, 5.11111111],
       [4.44444444, 5.        , 5.        , 4.88888889, 4.22222222],
       [4.33333333, 4.44444444, 3.44444444, 3.44444444, 3.77777778],
       [2.22222222, 2.55555556, 2.88888889, 3.44444444, 3.55555556],
       [2.44444444, 2.11111111, 2.44444444, 3.55555556, 4.33333333]])

In [40]: uniform_filter(image.astype(float))[1:-1,1:-1]
Out[40]: 
array([[4.55555556, 5.        , 5.55555556, 5.44444444, 5.11111111],
       [4.44444444, 5.        , 5.        , 4.88888889, 4.22222222],
       [4.33333333, 4.44444444, 3.44444444, 3.44444444, 3.77777778],
       [2.22222222, 2.55555556, 2.88888889, 3.44444444, 3.55555556],
       [2.44444444, 2.11111111, 2.44444444, 3.55555556, 4.33333333]])

Сроки -

In [42]: np.random.seed(0)
    ...: image = np.random.randint(0,9,(7000,7000))

In [43]: %timeit boxBlur(image)/9.0
1 loop, best of 3: 2.11 s per loop

In [44]: %timeit uniform_filter(image.astype(float))[1:-1,1:-1]
1 loop, best of 3: 612 ms per loop

Округление вниз

Для округления с исходным решением это будет: boxBlur(image)//9, Эквивалентный здесь будет с напольным покрытием, так что используйте np.floor(), но это может иметь проблемы с точностью. Таким образом, мы могли бы вместо этого использовать np.round с заданным количеством знаков после запятой для точности, а затем пол с .astype(int) -

n = 10 # number of decimal places for precision
np.around(uniform_filter(image.astype(float))[1:-1,1:-1], decimals=n).astype(int)

Для ввода с целочисленными значениями другой способ может заключаться в 9 и круглый, а затем пол -

np.round(uniform_filter(image.astype(float))[1:-1,1:-1]*9)//9
Другие вопросы по тегам