使用傅里叶变换做卷积?
using Fourier transforms to do convolution?
根据Convolution theorem,我们可以将傅立叶变换算子转化为卷积
使用 Python 和 Scipy,我的代码如下但不正确。
你能帮我解释一下吗?
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]]
我很困惑!
问题可能在于离散卷积和连续卷积之间的差异。卷积核(即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 之间使用点积。相反,只需将数组与 * 运算符相乘。
希望对您有所帮助。
我回答我的问题。
正确的代码。
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)
根据Convolution theorem,我们可以将傅立叶变换算子转化为卷积
使用 Python 和 Scipy,我的代码如下但不正确。 你能帮我解释一下吗?
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]]
我很困惑!
问题可能在于离散卷积和连续卷积之间的差异。卷积核(即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 之间使用点积。相反,只需将数组与 * 运算符相乘。
希望对您有所帮助。
我回答我的问题。 正确的代码。
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)