Реализация 2D свертки с использованием БПФ - PullRequest
0 голосов
/ 21 мая 2018

TensorFlow.conv2d() нереально медленно для свертки больших изображений с большими ядрами (фильтры).Требуется несколько минут, чтобы объединить изображение 1024x1024 с ядром того же размера.Для сравнения, cv2.filter2D() немедленно возвращает результат.

Я обнаружил tf.fft2() и tf.rfft().

Однако мне не было понятно, как выполнить простую фильтрацию изображений с помощью этих функций.

Как реализовать быструю фильтрацию 2D-изображений с помощью TensorFlow с использованием FFT?

1 Ответ

0 голосов
/ 24 мая 2018

Линейная дискретная свертка в форме x * y может быть вычислена с использованием теоремы о свертке и дискретного преобразования времени Фурье (DTFT).Если x * y является круговой дискретной сверткой, то ее можно вычислить с помощью дискретного преобразования Фурье (DFT).

Состояния теоремы свертки x * y могут быть вычислены с использованием преобразования Фурье как

Convolution theorem

, где Fourier transform обозначает преобразование Фурье, а Inverse Fourier transform обратное преобразование Фурье.Когда x и y являются дискретными и их свертка представляет собой линейную свертку, она вычисляется с использованием DTFT как

Discrete convolution theorem

Если x иy являются дискретными, и их свертка представляет собой круговую свертку, приведенная выше DTFT заменяется на DFT Примечание: задачи линейной свертки могут быть встроены в задачи круговой свертки.


Я более знаком с MATLAB, но прочитал документацию TensorFlow для tf.fft2d и tf.ifft2d приведенное ниже решение должно быть легко преобразовано в TensorFlow путем замены функций MATLAB fft2 и ifft2.

в MATLAB (и TensorFlow) fft2tf.fft2d) вычисляет ДПФ с использованием алгоритма быстрого преобразования Фурье.Если свертка 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.


В MATLAB на моем ноутбуке conv2(x, y) занимает 55 секундтогда как метод преобразования Фурье занимает менее 0,4 секунды.

...