【问题标题】:Convolving a periodic image with python用python卷积一个周期性图像
【发布时间】:2013-09-06 18:17:11
【问题描述】:

我想对概念上周期性的 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 中做到这一点?

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

【问题讨论】:

  • 我认为您必须编写自己的代码,使用 FFT 和 convolution theorem 非常容易。唯一棘手的部分可能是如何填充内核以获得正确的答案。

标签: python numpy scipy convolution


【解决方案1】:

这已经内置,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,这通常更快。

【讨论】:

    【解决方案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.]])
    

    【讨论】:

      【解决方案3】:

      这种“周期性卷积”更好地称为循环或循环卷积。见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]])
      

      【讨论】:

      • scipy.signal.fftconvolve 不支持'wrap' 模式。
      • 否,但它执行循环卷积。
      • 它不会在我的系统上执行循环条件,而不是文档中列出的任何模式。在用于数据之前,请务必使用样本测试其中任何一个。
      猜你喜欢
      • 2021-02-11
      • 1970-01-01
      • 2020-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-29
      相关资源
      最近更新 更多