TensorFlow.conv2d()
实际上很慢。将1024x1024图像与相同大小的内核进行卷积需要几分钟。为了进行比较,cv2.filter2D()
会立即返回结果。
我找到了tf.fft2()
和tf.rfft()
。
然而,我不清楚如何使用这些功能执行简单的图像过滤。
如何使用FFT实现TensorFlow的快速2D图像滤波?
答案 0 :(得分:2)
形式x * y
的线性离散卷积可以使用卷积定理和离散时间傅立叶变换(DTFT)来计算。如果x * y
是圆形离散卷积,则可以使用离散傅立叶变换(DFT)计算。
卷积定理状态x * y
可以使用傅里叶变换计算
其中表示傅立叶变换,表示逆傅里叶变换。当x
和y
是离散的并且它们的卷积是线性卷积时,这是使用DTFT计算的
如果x
和y
是离散的并且它们的卷积是循环卷积,则上面的DTFT将被DFT取代。 注意:线性卷积问题可以嵌入循环卷积问题中。
我对MATLAB更熟悉,但是通过阅读tf.fft2d
和tf.ifft2d
的TensorFlow文档,下面的解决方案应该可以通过替换MATLAB函数fft2
轻松转换为TensorFlow。 ifft2
。
在MATLAB(和TensorFlow)中fft2
(和tf.fft2d
)使用快速傅里叶变换算法计算DFT。如果x
和y
的卷积是循环的,则可以通过
ifft2(fft2(x).*fft2(y))
其中.*
表示MATLAB中的逐元素乘法。但是,如果它是线性的,则必须计算DTFT。这可以通过将数据填充为零来计算长度为2N-1
,其中N
是一维的长度(问题中为1024)。在MATLAB中,这可以通过两种方式之一进行计算。首先,通过
h = ifft2(fft2(x, 2*N-1, 2*N-1).*fft2(y, 2*N-1, 2*N-1));
其中MATLAB通过零填充计算2*N-1
- 点x
和y
的二维傅立叶变换,然后计算2*N-1
- 点二维傅里叶逆变换。这个方法不能在TensorFlow中使用(根据我对文档的理解),所以下一个是唯一的选择。在MATLAB和TensorFlow中,可以通过首先将x
和y
扩展到大小2*N-1
x 2*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中,h
和h_extended
完全相同。 x
和y
的卷积可以在没有使用
hC = conv2(x, y);
在MATLAB中。
在我的笔记本电脑conv2(x, y)
上的MATLAB中需要55秒,而傅立叶变换方法需要不到0.4秒。
答案 1 :(得分:0)
这可以通过类似于实现scipy.signal.fftconvolve
的方式来完成。
这里是一个例子,假设我们有一个图像(2维,如果您还有多个通道,则可以使用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高斯滤波器,请确保中心在左上角,即仅使用“四分之一”)
kernel_fft = tf.signal.rfft2d(kernel, fft_length=[fft_lenght1, fft_lenght2])
最后,进行逆变换以获取卷积图像
im_blurred = tf.signal.irfft2d(im_fft * kernel_fft, [fft_lenght1, fft_lenght2])