我想在MATLAB的conv2
函数上获得一些输入。假设我们的图片I
尺寸为5 x 5
,而内核K
则为3 x 3
。
conv2(I,K)
会返回7 x 7
矩阵。正在做什么额外的操作,我不知道?从数学的角度来看,我完全可以理解conv2(I,K,'valid')
和conv2(I,K,'same')
的工作原理。但是,默认操作返回一个更大的矩阵。有谁知道它实际上做了什么?
答案 0 :(得分:21)
如果你知道'valid
'标记和'same'
标记工作,然后它不是一个延伸到默认选项,这是'full'
选项。当您在图像/矩阵中滑动内核时,只要内核中的至少一个元素触及图像/矩阵中的任何元素,就会将其视为有效输出。当有有效输出时,操作的输出由内核所在的中心决定。例如,使用示例3 x 3内核I
查看下面的5 x 5图像K
:
I = [1 2 3 4 5 ] K = [1 0 1]
[6 7 8 9 10] [1 0 1]
[11 12 13 14 15] [1 0 1]
[16 17 18 19 20]
[21 22 23 24 25]
请注意,这些数字并不重要,但它们仅用于说明。还要注意内核是对称的,因此执行180度旋转会产生相同的内核。在我们开始之前,这需要卷积。在'full'
配置中,我们从左到右,从上到左,向下滑动内核。当内核的右下角接触图像/矩阵的左上角时,输出矩阵中第一个元素的输出发生:
[1 0 1]
[1 `0` 1]
[1 0 [1*1] 2 3 4 5]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
请注意,当我们扫描图像时,内核的中心是我们需要在图像中输出的位置,用“符号”表示。请记住,为了计算卷积,我们在内核中的每个元素与矩阵/图像中接触的位置之间找到产品的加权和元素总和。
请注意,对于内核的任何超出边界的元素,我们忽略,因此输出只是内核右下角和图像左上角的位置,我们将这些元素相乘。输出只是1*1 = 1
。现在让我们转到下一个元素,即右边的1:
[ 1 0 1]
[ 1 `0` 1]
[1 [0*1] [2*1] 3 4 5 ]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
注意中心的位置以及内核接触矩阵的元素。因此输出为0*1 + 2*1 = 2
。您将继续此操作,直到您到达该行的末尾,其中内核的左下角触及图像的右上角。然后,您将向下移动到下一行,在所有列上重复扫描并继续向上直到最后,直到内核的左上角触及图像/矩阵的右下角。
这里有几个例子,只是为了确保你的理论正确。让我们做内核触及图像/矩阵右上角的点
[ 1 0 1]
[ 1 `0` 1]
[1 2 3 4 [5*1]] 0 1]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[21 22 23 24 25]
请记住,我们会忽略内核没有触及图像/矩阵的所有位置。在这种情况下,输出只是5,并且还记录输出位置的位置。这是另一个例子:
[1 2 3 4 5 ]
[6 7 8 9 10]
[11 12 13 14 15]
[16 17 18 19 20]
[1 0 [[21*1] 22 23 24 25]
[1 `0` 1]
[1 0 1]
此位置位于图像/矩阵的左下角,此处的输出只是21*1
。另一个只是确定:
[1 2 3 4 5]
[6 7 8 9 10]
[11 12 13 14 [1*15]] 0 1]
[16 17 18 19 [1*20]] `0` 1]
[21 22 23 24 [1*25]] 0 1]
这个位置有点复杂。内核完全按照第一列与图像/矩阵重叠,因此输出只是1*15 + 1*20 + 1*25 = 60
。另请注意,输出位置位于倒数第三行,因为还有两行要执行的过滤。一个内核的前两行触摸底部的最后两行图像/矩阵,一个内核的第一行触及图像/矩阵的底部最后一行。
因此,最终输出矩阵看起来像这样。
[1 2 * * * * 5 ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * 60]
[* * * * * * *]
[21 * * * * * *]
标记为*
的元素未知,因为我还没有计算出这些元素,但重点是要注意矩阵的最终大小。具体来说,请注意输出位置的位置,我们需要在上面看到的前几种情况下写入矩阵。这就是为什么你得到一个更大的矩阵 - 当内核没有完全包含在图像/矩阵本身但仍然执行有效操作时,以适应结果。如您所见,您还需要两行:顶部为1,底部为1,另外两列:左侧为1,右侧为1。这会产生(5 + 2) x (5 + 2) = 7 x 7
输出矩阵。通常,如果内核大小为奇数,则使用'full'
2D卷积得到的输出通常是(rows + 2*floor(kernel_rows/2)) x (cols + 2*floor(kernel_cols/2))
,其中rows
和cols
是图像的行和列/要过滤的矩阵,kernel_rows
和kernel_cols
是内核的行和列。
如果你想看一下MATLAB实际产生的东西,我们可以。使用我之前定义的输入图像/矩阵和内核,这就是我们得到的:
>> I = reshape(1:25,5,5).'; %'
>> K = [1 0 1; 1 0 1; 1 0 1];
>> out = conv2(I,K)
out =
`1` `2` 4 6 8 4 `5`
7 9 18 22 26 13 15
18 21 42 48 54 27 30
33 36 72 78 84 42 45
48 51 102 108 114 57 `60`
37 39 78 82 86 43 45
`21` 22 44 46 48 24 25
请注意,我已经在MATLAB的输出中用“字符”标记了样本计算。这确实与计算一致。
现在你真正的问题是'valid'
和'same'
如何影响这一切。 'valid'
和'same'
进来的地方只是'full'
卷积的截断版本。 'same'
为您提供与要过滤的图像/矩阵大小相同的输出,'valid'
为您提供输出,使您只提供内核完全包含在图像内的输出/ matrix 。每当内核相对于图像/矩阵超出界限时,我们不会将这些输出作为最终输出的一部分。简单地说,'valid'
和'same'
使用' full'
结果,但删除结果边框的某些部分以方便您选择的选项。