4

我想对概念上周期性的 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 中执行此操作?

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

4

3 回答 3

4

这已经是内置的,带有scipy.signal.convolve2d's 可选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通常更快的方法。

于 2013-08-12T15:48:18.990 回答
3
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.]])
于 2013-08-11T16:44:44.037 回答
1

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

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

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]])
于 2013-08-22T14:33:16.217 回答