MATLAB的conv2函数如何执行完全卷积?

4
我正在尝试了解MATLAB的conv2函数。假设我们有一个尺寸为5 x 5的图像I和一个尺寸为3 x 3的卷积核Kconv2(I,K)将返回一个7 x 7的矩阵。我不知道还进行了哪些额外的操作?从数学角度来看,我完全可以理解conv2(I,K,'valid')conv2(I,K,'same')的工作原理。然而,默认操作会返回一个更大的矩阵。有人知道它实际上是做什么吗?
1个回答

29

如果你知道'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个。这导致一个 (5 + 2) x (5 + 2) = 7 x 7 的输出矩阵。通常情况下,如果核大小为奇数,则使用 'full' 2D 卷积得到的输出通常为 (rows + 2*floor(kernel_rows/2)) x (cols + 2*floor(kernel_cols/2)),其中 rowscols 是要过滤的图像/矩阵的行和列,而 kernel_rowskernel_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”。它们是“full”卷积的简化版本。“same”会输出与要过滤的图像/矩阵大小相同的输出,“valid”会输出仅包含核完全包含在图像/矩阵内的输出。当核超出图像/矩阵范围时,我们不将这些输出作为最终输出的一部分。简而言之,“valid”和“same”使用“full”结果,但移除结果的某些边框部分,以便于您选择的选项。


1
你的最后一段话解除了所有疑虑。非常棒的努力 :) - Rishabh Agrahari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接