问题描述
因此,我知道一个事实,即卷积具有交换/关联属性,而关联却没有但从来没有真正写出一个简单的例子来测试这一点。 (在那里存在等式形式的证明)
我只是尝试这个简单的例子:
Image : [1 0 -1 0 1 0 1 1]
A kernel = [-1 0 1]
B kernel = [-1 0 1]
使用卷积,I *(A * B)应该等于(I * A)* B,但是当我尝试这样做时,它们并不相等..这让我很困惑。谁能帮忙?也许我在计算时犯了一个人为错误..但是它们应该是对的吗? (假设边界被视为0)
使用相关性,正如我所理解的那样,它们不应该相等。但是,我的卷积也不是那么大声笑(但应该如此!)
任何帮助将不胜感激。
另外, A * B(卷积)为[0 -2 0]对吗? 和AxB(互相关)是否为[0 2 0]?解决方法
卷积运算符是可交换的。因此,I*(A*B)
应该等于(I*A)*B
是正确的。让我们首先将其转换为矩阵形式。内核A的卷积可以通过以下卷积矩阵C转换为乘法:
C=
[-1 0 1 0 0 0 0 0]
[ 0 -1 0 1 0 0 0 0]
[ 0 0 -1 0 1 0 0 0]
[ 0 0 0 -1 0 1 0 0]
[ 0 0 0 0 -1 0 1 0]
[ 0 0 0 0 0 -1 0 1]
[ 1 0 0 0 0 0 -1 0]
[ 0 1 0 0 0 0 0 -1]
我们采用了内核[-1 0 1],并在第一行中用5个零对它进行了零填充。然后,下面的每一行是前一行右侧的1个位置的循环移位。 因此,如果我们想用I计算内核A的卷积:
I = [1 0 -1 0 1 0 1 1]
我们只需计算矩阵向量乘法:
C*I^T
(其中I ^ T是转置向量)。
按照上述公式,我们得到:
I*(A*B) = (C*C)*I^T
计算C * C,您将得到以下矩阵:
C^2=
[ 1 0 -2 0 1 0 0 0]
[ 0 1 0 -2 0 1 0 0]
[ 0 0 1 0 -2 0 1 0]
[ 0 0 0 1 0 -2 0 1]
[ 1 0 0 0 1 0 -2 0]
[ 0 1 0 0 0 1 0 -2]
[-2 0 1 0 0 0 1 0]
[ 0 -2 0 1 0 0 0 1]
和:
I*(A*B) = (C*C)*I^T =
[ 4]
[ 0]
[-2]
[ 1]
[ 0]
[-2]
[-2]
[ 1]
而(I*A)*B
在矩阵公式C*(C*I^T)
中,根据矩阵关联性,它等于I*(A*B)=(C*C)*I^T
。
您可以通过运行以下numpy代码来验证此结果:
import numpy as np
C = [[-1,1,0]]
for k in range(7):
C.append(np.roll(C[0],k+1))
C = np.array(C)
#print(C)
I = np.transpose(np.array([[1,-1,1]]))
print(f'C=\n{C}\n')
print(f'C^2=\n{C@C}\n')
print(f'(C*C)*I=\n{(C@C)@I}\n')
print(f' C*(C*I)=\n{C@(C@I)}\n')
运行以上代码的结果是:
C=
[[-1 0 1 0 0 0 0 0]
[ 0 -1 0 1 0 0 0 0]
[ 0 0 -1 0 1 0 0 0]
[ 0 0 0 -1 0 1 0 0]
[ 0 0 0 0 -1 0 1 0]
[ 0 0 0 0 0 -1 0 1]
[ 1 0 0 0 0 0 -1 0]
[ 0 1 0 0 0 0 0 -1]]
C^2=
[[ 1 0 -2 0 1 0 0 0]
[ 0 1 0 -2 0 1 0 0]
[ 0 0 1 0 -2 0 1 0]
[ 0 0 0 1 0 -2 0 1]
[ 1 0 0 0 1 0 -2 0]
[ 0 1 0 0 0 1 0 -2]
[-2 0 1 0 0 0 1 0]
[ 0 -2 0 1 0 0 0 1]]
(C*C)*I=
[[ 4]
[ 0]
[-2]
[ 1]
[ 0]
[-2]
[-2]
[ 1]]
C*(C*I)=
[[ 4]
[ 0]
[-2]
[ 1]
[ 0]
[-2]
[-2]
[ 1]]
所以您可以看到获得了相同的结果。
请注意,A*B
不是[0 -2 0]而是[1 0 -2 0 1],因为您采用A = [-1 0 1](将其两边都加2的零填充为零)并在B = [-1 0 1]上将其作为滑动窗口移动,因此首先您将得到:[-1 -1,0 -1 + -1 0,- 1 1 + 0 0 + 1 -1,1 0 + 0 1,1 1] = [1 0 -2 0 1]。宽度为n的2个内核的卷积结果将为长度2 n-1。