用FFT实现二维卷积

2024-03-29 07:39:03 发布

您现在位置:Python中文网/ 问答频道 /正文

TensorFlow.conv2d()在用大内核(过滤器)卷积大图像时速度慢得不切实际。将1024x1024映像与相同大小的内核卷积需要几分钟时间。为了进行比较,cv2.filter2D()立即返回结果。在

我找到了tf.fft2()和{}。在

然而,我不清楚如何使用这些函数执行简单的图像过滤。在

如何使用快速傅里叶变换实现快速二维图像滤波?在


Tags: 函数图像过滤器tftensorflow时间cv2内核
2条回答

这可以通过类似于实现scipy.signal.fftconvolve的方式来实现。在

这里是一个例子,假设我们有一个图像(二维,如果你也有多个通道,你可以用3d代替2个函数)(im)和一个滤波器(例如高斯)。在

首先,对图像进行傅立叶变换并定义fft_lenghts(如果过滤器的形状不同,则很有用,在这种情况下,它将得到零填充)

fft_lenght1 = tf.shape(im)[0]
fft_lenght2 = tf.shape(im)[1]
im_fft = tf.signal.rfft2d(im, fft_length=[fft_lenght1, fft_lenght2])

接下来,使用滤波器的FFT(注意,对于2d高斯滤波器,请确保中心位于左上角,即仅使用“四分之一”)

^{pr2}$

最后,进行反变换得到卷积图像

im_blurred = tf.signal.irfft2d(im_fft * kernel_fft, [fft_lenght1, fft_lenght2])

使用卷积定理和离散时间傅里叶变换(DTFT)可以计算出x * y形式的线性离散卷积。如果x * y是一个循环离散卷积,那么它可以用离散傅立叶变换(DFT)来计算。在

卷积定理状态{}可以用Fourier变换作为

Convolution theorem

其中Fourier transform表示傅里叶变换,Inverse Fourier transform表示傅里叶逆变换。当x和{}是离散的并且它们的卷积是线性卷积时,使用DTFT作为

Discrete convolution theorem

如果x和{}是离散的并且它们的卷积是循环卷积,则上面的DTFT将被DFT代替。注:线性卷积问题可以嵌入到循环卷积问题中。在


我对MATLAB比较熟悉,但是通过阅读^{}^{}的TensorFlow文档,下面的解决方案应该可以通过替换MATLAB函数fft2ifft2轻松转换为TensorFlow。在

在MATLAB(和TensorFlow)中,fft2(和tf.fft2d)使用快速傅立叶变换算法计算DFT。如果xy的卷积是圆形的,则可以通过

ifft2(fft2(x).*fft2(y))

其中.*表示MATLAB中元素的逐元素乘法。但是,如果它是线性的,则必须计算DTFT。这可以通过将数据补零到长度2N-1来计算,其中N是一维的长度(问题中有1024个)。在MATLAB中,这可以用两种方法中的一种来计算。首先,通过

^{pr2}$

其中,MATLAB计算x和{}的{}-点2D傅立叶变换,然后计算2*N-1点2D傅里叶逆变换。这个方法不能用在TensorFlow中(从我对文档的理解来看),所以下一个是唯一的选择。在MATLAB和TensorFlow中,卷积可以通过先将xy扩展到2*N-1x2*N-1的大小,然后计算2*N-1-点二维傅里叶变换和傅立叶逆变换

x_extended = x;
x_extended(2*N-1, 2*N-1) = 0;

y_extended = y;
y_extended(2*N-1, 2*N-1) = 0;

h_extended = ifft2(fft2(x_extended).*fft2(y_extended));

在MATLAB中,h和{}完全相等。x和{}的卷积可以不用Fourier变换来计算

hC = conv2(x, y);

在MATLAB中。在


在我的笔记本电脑上的MATLAB中,conv2(x, y)需要55秒,而Fourier变换方法只需要不到0.4秒。在

相关问题 更多 >