使用傅立叶变换进行卷积?

时间:2016-11-20 11:57:29

标签: python numpy filter deep-learning convolution

根据卷积定理(links),我们可以用傅里叶变换算子进行卷积。

使用python和scripy,我的代码在下面,但不正确。 你能帮我解释一下吗?

import tensorflow as tf
import sys
from scipy import signal

from scipy import linalg
import numpy as np

x = [[1 , 2] , [7 , 8]]

y = [[4 , 5] , [3 , 4]]


print "conv:" ,  signal.convolve2d(x , y , 'full')

new_x = np.fft.fft2(x)
new_y = np.fft.fft2(y)


print "fft:" , np.fft.ifft2(np.dot(new_x , new_y))

代码的结果:

conv: [[ 4 13 10]
 [31 77 48]
 [21 52 32]]

fft: [[  20.+0.j   26.+0.j]
 [ 104.+0.j  134.+0.j]]

我很困惑!

2 个答案:

答案 0 :(得分:3)

问题可能在于离散和连续卷积之间的差异。卷积核(即y)将超出x的边界,这些区域需要在卷积中计算。

默认情况下,scipy.signal.convolve将使用0填充超出范围的区域,这将偏向结果: https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.convolve2d.html

默认情况下,傅立叶乘法不会这样做 - 您可以通过填充x,y数组并比较结果来测试它。

这些技术之间的差异应该随着内核大小远小于图像尺寸而减小。

进一步说明 - 你不应该使用new_x,new_y之间的点积。相反,只需将数组与*运算符相乘即可。

希望这有帮助。

答案 1 :(得分:2)

我回答我的问题。 正确的代码。

import sys
from scipy import signal

from scipy import linalg
import numpy as np

x = [[1 , 0 , 0 , 0] , [0 , -1 , 0 , 0] , [0 , 0 , 3 , 0] , [0 , 0 , 0 , 1]]
x = np.array(x)
y = [[4 , 5] , [3 , 4]]
y = np.array(y)

print "conv:" ,  signal.convolve2d(x , y , 'full')

s1 = np.array(x.shape)
s2 = np.array(y.shape)

size = s1 + s2 - 1


fsize = 2 ** np.ceil(np.log2(size)).astype(int)
fslice = tuple([slice(0, int(sz)) for sz in size])


new_x = np.fft.fft2(x , fsize)


new_y = np.fft.fft2(y , fsize)
result = np.fft.ifft2(new_x*new_y)[fslice].copy()

print "fft for my method:" , np.array(result.real , np.int32)

print "fft:" , np.array(signal.fftconvolve(x ,y) , np.int32)