卷积模糊图像-Python

时间:2018-08-10 09:39:59

标签: python numpy convolution

我下面的代码几乎可以正常工作-这里我唯一需要的是卷积的输出必须除以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 个答案:

答案 0 :(得分: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。这里等效的是 floor -ing,因此请使用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