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

Dst*_*Pk. 4 matlab signal-processing image-processing convolution computer-vision

我试图获得关于MATLAB conv2函数的一些输入.假设我们有一个形象I的尺寸5 x 5和内核K3 x 3.

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

ray*_*ica 24

如果你知道'valid'flag和'same'flag 是如何工作的,那么就可以选择默认选项了'full'.当您在图像/矩阵中滑动内核时,只要内核中的至少一个元素触及图像/矩阵中的任何元素,就会将其视为有效输出.当有有效输出时,操作的输出由内核所在的中心决定.例如,I使用示例3 x 3内核查看下面的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]
Run Code Online (Sandbox Code Playgroud)

请注意,这些数字并不重要,但它们用于说明.还要注意内核是对称的,因此执行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] 
Run Code Online (Sandbox Code Playgroud)

请注意,当我们扫描图像时,内核的中心是我们需要在图像中输出的位置,用"符号"表示.请记住,为了计算卷积,我们在内核中的每个元素与矩阵/图像中接触的位置之间找到产品的加权和元素之和.

请注意,对于内核的任何超出范围的元素,我们忽略,因此输出只是内核右下角和图像左上角的位置,我们将这些元素相乘.输出很简单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]
Run Code Online (Sandbox Code Playgroud)

注意中心的位置以及内核接触矩阵的元素.因此输出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]
Run Code Online (Sandbox Code Playgroud)

请记住,我们忽略内核不接触图像/矩阵的所有位置.在这种情况下,输出只是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]
Run Code Online (Sandbox Code Playgroud)

此位置位于图像/矩阵的左下角,此处的输出就是这样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]
Run Code Online (Sandbox Code Playgroud)

这个位置有点复杂.内核完全按照第一列与图像/矩阵重叠,因此输出很简单1*15 + 1*20 + 1*25 = 60.另请注意,输出位置位于倒数第三行,因为还有两行要执行的过滤.一个内核的前两行触摸底部的最后两行图像/矩阵,一个内核的第一行触及图像/矩阵的底部最后一行.

因此,最终输出矩阵看起来像这样.

[1 2 * * * * 5 ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * 60]
[* * * * * *  *]
[21 * * * * * *]
Run Code Online (Sandbox Code Playgroud)

标记为的元素*是未知的,因为我没有计算这些元素,但关键是要注意矩阵的最终大小是什么.具体来说,请注意输出位置的位置,我们需要在上面看到的前几种情况下写入矩阵.这就是为什么你得到一个更大的矩阵 - 当内核没有完全包含在图像/矩阵本身但仍然执行有效操作时,以适应结果.如您所见,您还需要两行:顶部为1,底部为1,另外两列:左侧为1,右侧为1.这导致(5 + 2) x (5 + 2) = 7 x 7输出矩阵.一般来说,如果内核大小是奇数,你用得到的输出'full'二维卷积通常是(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
Run Code Online (Sandbox Code Playgroud)

请注意,我已经在MATLAB输出中使用``字符标记了样本计算.这确实与计算一致.

现在你真正的问题是如何'valid''same'考虑所有这些.其中'valid''same'进来只是卷积的截断版本'full'. 'same'为您提供与要过滤的图像/矩阵大小相同的输出,并'valid'为您提供输出,使您只提供内核完全包含在图像/矩阵内的输出.每当内核相对于图像/矩阵超出界限时,我们不会将这些输出作为最终输出的一部分.简单地说,'valid''same'使用' full'结果但删除结果边界的某些部分,以方便您选择的选项.