我正在尝试从MATLAB的conv2
函数中获取一些输入假设我们有一个维度I
的图像5 x 5
和一个内核K
,即3 x 3
。conv2(I,K)
将返回一个7 x 7
矩阵我不知道在做什么额外的手术我完全可以从数学的角度理解conv2(I,K,'valid')
和conv2(I,K,'same')
是如何工作的但是,默认操作返回一个较大的矩阵有人知道它到底是干什么的吗?
最佳答案
如果您知道'valid
'标志和'same'
标志是如何工作的,那么转到默认选项(即'full'
选项)就不难了当您在图像/矩阵上滑动内核时,只要内核中至少有一个元素接触到图像/矩阵中的任何元素,就认为这是有效的输出当存在有效输出时,操作的输出由内核所在的中心决定例如,使用示例3x 3内核查看下面的5x 5图像:
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度旋转会得到相同的内核在我们开始之前,这是卷积的要求在
I
配置中,我们以从左到右、从上到下的方式将内核从左上到右下滑动输出矩阵中第一个元素的输出发生在内核右下角接触图像/矩阵左上角时:[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]
注意,当我们扫过图像时,内核的中心是我们需要在图像中输出的位置,用``符号表示记住,要在这里计算卷积,我们会找到核中每个元素与其在矩阵/图像中的接触点之间乘积的加权和。
请注意,对于超出边界的内核元素,我们忽略,因此输出只是内核右下角和图像左上角接触的地方,我们将这些元素相乘输出只是
K
现在让我们转到下一个元素,即右边的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]
注意中心在哪里,以及内核接触矩阵的元素因此输出
'full'
您将继续此操作,直到到达此行的末尾,在该行中,内核的左下角与图像的右上角接触然后向下移动到下一行,在所有列上重复扫描,并继续向上移动,直到内核的左上角接触到图像/矩阵的右下角为止。这里还有几个例子来确保你的理论是正确的让我们做一个点,内核接触到图像/矩阵的右上角
[ 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]
这个位置在图像/矩阵的左下角,这里的输出将是
1*1 = 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 2 * * * * 5 ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * * ]
[* * * * * * 60]
[* * * * * * *]
[21 * * * * * *]
标记为
0*1 + 2*1 = 2
的元素是未知的,因为我没有计算这些元素,但重点是要注意矩阵的最终大小具体地说,请注意,对于上面看到的前两种情况,输出位置是我们需要写入矩阵的位置这就是为什么你会得到一个更大的矩阵-当内核没有完全包含在图像/矩阵中,但是仍然执行有效的操作时,为了适应结果如您所见,您将需要两个额外的行:1个用于顶部,1个用于底部,以及两个额外的列:1个用于左侧,1个用于右侧这会产生一个21*1
输出矩阵一般来说,如果核的大小是奇数,那么通过使用2D卷积得到的输出通常是1*15 + 1*20 + 1*25 = 60
,其中*
和(5 + 2) x (5 + 2) = 7 x 7
是要过滤的图像/矩阵的行和列,'full'
和(rows + 2*floor(kernel_rows/2)) x (cols + 2*floor(kernel_cols/2))
是核的行和列。如果你想看看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输出中所做的示例计算这与计算结果相符。
现在你真正的问题是如何将这些因素考虑进去其中
rows
和cols
是kernel_rows
卷积的简单截断形式kernel_cols
为您提供与要过滤的图像/矩阵大小相同的输出,并且'valid'
为您提供的输出仅限于内核完全包含在图像/矩阵中的情况任何时候,当内核超出图像/矩阵的边界时,我们都不将这些输出作为最终输出的一部分简单地说,'same'
和'valid'
使用“'same'
结果,但删除结果边框的某些部分,以方便您选择选项。
关于matlab - 使用MATLAB的conv2函数如何执行完全卷积?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37145895/