我想执行一个简单的2D图像卷积,但我的卷积核的大小是偶数。 我应该选择哪些索引作为卷积核中心? 我尝试在谷歌上寻找答案并查看现有代码。 人们通常将卷积核居中,以便新的零值之前有一个样本。 因此,如果我们有一个4x4的卷积核,则中心索引应为-2 -1 0 +1
。 这是正确的吗? 如果确实如此,为什么会这样呢? 有人能解释一下为什么-2 -1 0 +1
是正确的,而-1 0 +1 +2
不是吗? 请记住,我想执行卷积,而不使用FFT。
我想执行一个简单的2D图像卷积,但我的卷积核的大小是偶数。 我应该选择哪些索引作为卷积核中心? 我尝试在谷歌上寻找答案并查看现有代码。 人们通常将卷积核居中,以便新的零值之前有一个样本。 因此,如果我们有一个4x4的卷积核,则中心索引应为-2 -1 0 +1
。 这是正确的吗? 如果确实如此,为什么会这样呢? 有人能解释一下为什么-2 -1 0 +1
是正确的,而-1 0 +1 +2
不是吗? 请记住,我想执行卷积,而不使用FFT。
如果我正确理解你的问题,那么对于偶数大小的卷积核,你说的居中是惯例,以便在新零点之前有一个样本。
因此,对于宽度为4的卷积核,居中的索引将是-2 -1 0 +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) { }
}
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.]
如您所见,“same”填充的输入数组在开头填充了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,