用FFT实现二维卷积

2022-04-02 00:00:00 python tensorflow image-processing fft

问题描述

TensorFlow.conv2d()对于卷积大图像和大核(滤镜)来说,速度非常慢。将1024x1024图像与相同大小的内核进行卷积需要几分钟时间。为了进行比较,cv2.filter2D()立即返回结果。

我找到tf.fft2()tf.rfft()

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

如何使用FFT使用TensorFlow实现快速2D图像过滤?


解决方案

x * y形式的线性离散卷积可以使用卷积定理和离散时间傅里叶变换计算。如果x * y是圆形离散卷积,则可以使用离散傅里叶变换(DFT)进行计算。

卷积定理状态x * y可以使用傅里叶变换计算为

其中表示傅里叶变换和傅立叶逆变换。当xy是离散的并且它们的卷积是线性卷积时,这是使用DTFT计算的

如果xy是离散的,并且它们的卷积是循环卷积,则用DFT代替上面的DTFT。注意:线性卷积问题可以嵌入到循环卷积问题中。


我对MatLab比较熟悉,但通过阅读tf.signal.fft2dtf.signal.ifft2d的TensorFlow文档,下面的解决方案应该可以通过替换MatLab函数fft2ifft2轻松转换为TensorFlow。

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

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

其中.*表示在MatLab中逐个元素相乘。然而,如果它是线性的,那么我们将数据零填充到长度2N-1,其中N是一维的长度(在问题中是1024)。在MatLab中,这可以用两种方法之一来计算。首先,由

h = ifft2(fft2(x, 2*N-1, 2*N-1).*fft2(y, 2*N-1, 2*N-1));
其中,MatLab通过填零来计算xy2*N-1点2D傅立叶变换,然后计算2*N-1点2D逆傅立叶变换。此方法不能在TensorFlow中使用(根据我对文档的理解),因此下一步是唯一的选择。在MatLab和TensorFlow中,可以通过首先将xy扩展到大小2*N-1x2*N-1,然后计算2*N-1点2D傅立叶变换和逆傅立叶变换

来计算卷积
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中,hh_extended完全相等。xy的卷积可以在不进行傅里叶变换的情况下计算
hC = conv2(x, y);

在MatLab中。


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

相关文章