使用python卷积周期图像

时间:2013-08-11 13:54:15

标签: python numpy scipy convolution

我想卷积一个概念上是周期性的n维图像。

我的意思如下:如果我有2D图像

>>> image2d = [[0,0,0,0],
...            [0,0,0,1],
...            [0,0,0,0]]

我想用这个内核卷积它:

>>> kernel = [[ 1,1,1],
...           [ 1,1,1],
...           [ 1,1,1]]

然后我希望结果是:

>>> result = [[1,0,1,1],
...           [1,0,1,1],
...           [1,0,1,1]]

如何在python / numpy / scipy中执行此操作?

请注意,我对创建内核不感兴趣,但主要是卷积的周期性,即结果图像中最左边的三个(如果有意义的话)。

3 个答案:

答案 0 :(得分:3)

这已经内置了scipy.signal.convolve2d的可选boundary='wrap',它给出了周期性边界条件作为卷积的填充。这里的mode选项为'same',以使输出大小与输入大小相匹配。

In [1]: image2d = [[0,0,0,0],
    ...            [0,0,0,1],
    ...            [0,0,0,0]]

In [2]: kernel = [[ 1,1,1],
    ...           [ 1,1,1],
    ...           [ 1,1,1]]

In [3]: from scipy.signal import convolve2d

In [4]: convolve2d(image2d, kernel, mode='same', boundary='wrap')
Out[4]: 
array([[1, 0, 1, 1],
       [1, 0, 1, 1],
       [1, 0, 1, 1]])

这里唯一的缺点是你不能使用通常更快的scipy.signal.fftconvolve

答案 1 :(得分:2)

image2d = [[0,0,0,0,0],
           [0,0,0,1,0],
           [0,0,0,0,0],
           [0,0,0,0,0]]
kernel = [[1,1,1],
          [1,1,1],
          [1,1,1]]
image2d = np.asarray(image2d)
kernel = np.asarray(kernel)

img_f = np.fft.fft2(image2d)
krn_f = np.fft.fft2(kernel, s=image2d.shape)

conv = np.fft.ifft2(img_f*krn_f).real

>>> conv.round()
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  1.,  1.],
       [ 1.,  0.,  0.,  1.,  1.],
       [ 1.,  0.,  0.,  1.,  1.]])

请注意,内核的左上角位于图像中1的位置。你需要滚动结果才能得到你想要的东西:

k_rows, k_cols = kernel.shape
conv2 = np.roll(np.roll(conv, -(k_cols//2), axis=-1),
                -(k_rows//2), axis=-2)
>>> conv2.round()
array([[ 0.,  0.,  1.,  1.,  1.],
       [ 0.,  0.,  1.,  1.,  1.],
       [ 0.,  0.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  0.,  0.]])

答案 2 :(得分:1)

这种“周期性卷积”更好地称为循环或循环卷积。见http://en.wikipedia.org/wiki/Circular_convolution

在n维图像的情况下,就像在这个问题中的情况一样,可以使用scipy.ndimage.convolve函数。它有一个参数 mode ,可以设置为 wrap 进行循环卷积。

result = scipy.ndimage.convolve(image,kernel,mode='wrap')

>>> import numpy as np
>>> image = np.array([[0, 0, 0, 0],
...                   [0, 0, 0, 1],
...                   [0, 0, 0, 0]])
>>> kernel = np.array([[1, 1, 1],
...                    [1, 1, 1],
...                    [1, 1, 1]])
>>> from scipy.ndimage import convolve
>>> convolve(image, kernel, mode='wrap')
array([[1, 0, 1, 1],   
       [1, 0, 1, 1],
       [1, 0, 1, 1]])