【问题标题】:Image convolution with even-sized kernel具有均匀大小内核的图像卷积
【发布时间】:2013-06-06 19:40:00
【问题描述】:

我想执行一个简单的 2D 图像卷积,但我的内核是偶数大小的。我应该为我的内核中心选择哪些索引?我尝试在谷歌上搜索答案并查看现有代码。人们通常将他们的内核居中,所以在新的 0 之前会有一个样本。所以,如果我们有一个 4x4 内核,居中的索引应该是-2 -1 0 +1。那是对的吗?如果是,为什么会这样?有人可以解释为什么-2 -1 0 +1 是正确的而-1 0 +1 +2 不是吗?请记住,我想在不使用 FFT 的情况下执行卷积。

【问题讨论】:

    标签: image-processing convolution


    【解决方案1】:

    如果我正确理解您的问题,那么对于均匀大小的内核,您是正确的,约定将内核居中,以便在新零之前还有一个样本。

    因此,对于宽度为 4 的内核,居中的索引将是 -2 -1 0 +1,正如您在上面所说的。

    但是,这实际上只是一种约定——无论如何都很少使用不对称卷积,并且不对称的确切性质(左/右等)与“正确”结果无关。我想大多数实现都以这种方式运行的原因是,它们可以在给定相同输入的情况下给出可比较的结果。

    在频域中执行卷积时,无论如何都会填充内核以匹配图像大小,并且您已经声明您正在空间域中执行卷积。

    我对为什么首先需要使用偶数大小的内核更感兴趣。

    【讨论】:

    • 非常感谢您的回答我的朋友!我想使用点扩散函数 (PSF) 对一些图像进行卷积。这个 PSF 的大小恰好是均匀的 (44x44)。我想我可以将 PSF 的大小/重新采样为 43x43,但我对偶数内核的情况有点好奇。再次感谢!
    • @AstrOne 没问题,我建议按照您的建议重新采样 PSF,尽管在这种大小的内核上它可能不会有太大的不同。
    • 这里是一个answer 用于均匀大小的内核大小。
    • 感谢您的回答。 “以内核为中心的约定”是什么意思?什么是-2 - 1 0 +1。似乎我在内核中有一些坐标,但相对于哪个位置?
    【解决方案2】:

    正确的答案是返回左上角的结果像素,不管你的矩阵大小是否均匀。然后你可以简单地在一个简单的扫描线中执行操作,它们不需要内存。

    private static void applyBlur(int[] pixels, int stride) {
        int v0, v1, v2, r, g, b;
        int pos;
        pos = 0;
        try {
            while (true) {
                v0 = pixels[pos];
                v1 = pixels[pos+1];
                v2 = pixels[pos+2];
    
                r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
                g = ((v0 >> 8 ) & 0xFF) + ((v1 >>  8) & 0xFF) + ((v2 >>  8) & 0xFF);
                b = ((v0      ) & 0xFF) + ((v1      ) & 0xFF) + ((v2      ) & 0xFF);
                r/=3;
                g/=3;
                b/=3;
                pixels[pos++] = r << 16 | g << 8 | b;
            }
        }
        catch (ArrayIndexOutOfBoundsException e) { }
        pos = 0;
        try {
        while (true) {
                v0 = pixels[pos];
                v1 = pixels[pos+stride];
                v2 = pixels[pos+stride+stride];
    
                r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
                g = ((v0 >> 8 ) & 0xFF) + ((v1 >>  8) & 0xFF) + ((v2 >>  8) & 0xFF);
                b = ((v0      ) & 0xFF) + ((v1      ) & 0xFF) + ((v2      ) & 0xFF);
                r/=3;
                g/=3;
                b/=3;
                pixels[pos++] = r << 16 | g << 8 | b;
            }
        }
        catch (ArrayIndexOutOfBoundsException e) { }
    }
    

    【讨论】:

      【解决方案3】:

      在对偶数卷积及其在时间卷积网络中的应用进行了一些思考之后,我决定,下面的实验将为 tensorflow/keras 中偶数卷积的居中给出答案:

      import keras
      import numpy as np
      import tensorflow as tf
      import keras.backend as K
      import keras.layers as layers
      from keras.layers import Conv2D, Input
      from keras.initializers import Constant
      
      if __name__ == '__main__':
          inputs = Input(shape=(None,1,1))
          even_conv = Conv2D(1,(4,1),padding="same",
                             kernel_initializer=Constant(value=1.),use_bias=False)(inputs)
          f = K.function(inputs=[inputs],outputs=[even_conv])
          test_input = np.arange(10)[np.newaxis,...,np.newaxis,np.newaxis].astype(np.float)
          result = f(inputs=[test_input])[0]
          print(np.squeeze(test_input))
          # [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
          print(np.squeeze(result))
          # [ 3.  6. 10. 14. 18. 22. 26. 30. 24. 17.]
      

      正如您所见,“相同”填充输入数组在开头填充了 1 个零,最后填充了 2 个零:[0. 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 0. 0.]。因此对于 tensorflow,即使大小的内核中心将遵循 4 内核:-1 0 +1 +22*n 大小的内核:-(n-1), -(n-2),... -1, 0, +1,... +(n-1), +n,

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-15
        • 2021-03-17
        • 1970-01-01
        • 2018-12-10
        • 1970-01-01
        • 1970-01-01
        • 2021-02-05
        • 2015-10-04
        相关资源
        最近更新 更多