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

时间:2016-05-10 18:05:20

标签: matlab image-processing computer-vision signal-processing convolution

我想在MATLAB的conv2函数上获得一些输入。假设我们的图片I尺寸为5 x 5,而内核K则为3 x 3

conv2(I,K)会返回7 x 7矩阵。正在做什么额外的操作,我不知道?从数学的角度来看,我完全可以理解conv2(I,K,'valid')conv2(I,K,'same')的工作原理。但是,默认操作返回一个更大的矩阵。有谁知道它实际上做了什么?

1 个答案:

答案 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)),其中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'如何影响这一切。 'valid''same'进来的地方只是'full'卷积的截断版本。 'same'为您提供与要过滤的图像/矩阵大小相同的输出,'valid'为您提供输出,使您只提供内核完全包含在图像内的输出/ matrix 。每当内核相对于图像/矩阵超出界限时,我们不会将这些输出作为最终输出的一部分。简单地说,'valid''same'使用' full'结果,但删除结果边框的某些部分以方便您选择的选项。