我将从一个非常简短的卷积讨论开始,使用来自维基百科的以下图片:

如图所示,对两个一维函数进行卷积涉及反映其中一个(即卷积核),将两个函数相互滑动,并计算它们的乘积的积分。
当对二维矩阵进行卷积时,卷积核会在两个维度上反映出来,然后计算与另一个矩阵的每个唯一重叠组合的乘积之和。内核维度的这种反映是卷积的固有步骤。
然而,在执行过滤时,我们喜欢将过滤矩阵视为一个“模板”,直接按原样(即没有反射)放置在要过滤的矩阵上。换句话说,我们希望执行与卷积相同的操作,但不反映过滤矩阵的维度。为了消除卷积期间执行的反射,我们可以在执行卷积之前添加对滤波器矩阵维度的额外反射。
现在,对于任何给定的二维矩阵,您可以通过使用 MATLAB 中的FLIPDIM和ROT90A
函数向自己证明翻转两个维度相当于将矩阵旋转 180 度:
A = rand(5); %# A 5-by-5 matrix of random values
isequal(flipdim(flipdim(A,1),2),rot90(A,2)) %# Will return 1 (i.e. true)
这就是为什么filter2(f,A)
等同于conv2(A,rot90(f,2),'same')
. 为了进一步说明滤波器矩阵与卷积核的不同看法,我们可以看看当我们将FILTER2和CONV2应用于同一组矩阵f
和时会发生什么A
,定义如下:
>> f = [1 0 0; 0 1 0; 1 0 0] %# A 3-by-3 filter/kernel
f =
1 0 0
0 1 0
1 0 0
>> A = magic(5) %# A 5-by-5 matrix
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
现在,当执行B = filter2(f,A);
输出元素的计算时,B(2,2)
可以通过将过滤器的中心元素与A(2,2)
重叠元素对齐并相乘来可视化:
17*1 24*0 1*0 8 15
23*0 5*1 7*0 14 16
4*1 6*0 13*0 20 22
10 12 19 21 3
11 18 25 2 9
由于过滤器矩阵之外的元素被忽略,我们可以看到乘积之和为17*1 + 4*1 + 5*1 = 26
。请注意,这里我们只是像“模板”一样简单地放置f
在上面A
,这就是过滤器矩阵被认为对矩阵进行操作的方式。
当我们执行B = conv2(A,f,'same');
时,输出元素的计算B(2,2)
看起来像这样:
17*0 24*0 1*1 8 15
23*0 5*1 7*0 14 16
4*0 6*0 13*1 20 22
10 12 19 21 3
11 18 25 2 9
并且产品的总和将改为5*1 + 1*1 + 13*1 = 19
。请注意,当f
被视为卷积核时,我们必须先翻转其尺寸,然后再将其放置在A
.