使用偶数大小的内核进行图像卷积

时间:2013-06-11 03:05:52

标签: image-processing convolution

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

3 个答案:

答案 0 :(得分:7)

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

因此,对于宽度为4的内核,如上所述,居中索引将为-2 -1 0 +1

然而,这实际上只是一个惯例 - 非对称卷积很少被使用,不对称的确切性质(左/右等)与“正确”结果无关。我认为大多数实现都采用这种方式的原因是它们可以在给定相同输入的情况下给出可比较的结果。

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

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

答案 1 :(得分:1)

正确答案是返回左上角的结果像素,无论矩阵的大小是否均匀。然后,您只需在简单的扫描线中执行操作,它们就不需要内存。

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) { }
}

答案 2 :(得分:0)

在对偶数卷积及其在时间卷积网络中的应用进行了思考之后,我决定,以下实验将为在张量流/ 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 +2和大小为2*n的内核:-(n-1), -(n-2),... -1, 0, +1,... +(n-1), +n,