如果您知道'valid' 标志和'same' 标志是如何工作的,那么使用默认选项(即'full' 选项)并不难。当您在图像/矩阵上滑动内核时,只要内核中的至少一个元素接触到图像/矩阵中的任何元素,就被认为是有效输出。当有有效输出时,操作的输出由内核所在的中心决定。例如,看看下面的 5 x 5 图像 I 以及一个示例 3 x 3 内核 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' 为您提供输出,以便您仅提供内核完全包含在图像/矩阵中的输出强>。每当内核相对于图像/矩阵超出范围时,我们都不会将这些输出作为最终输出的一部分。简单地说,'valid' 和 'same' 使用 'full' 结果,但删除了结果的某些部分边框以方便您选择。