Методы Фурье
Для обработки сигналов часто применяется такой метод, как преобразование Фурье. Этот метод позволяет преобразовывать сигнал между временной областью и частотной областью. Эффективный алгоритм быстрого преобразования Фурье (БПФ) реализован в Julia с использованием библиотеки FFTW.
using FFTW
1D преобразование Фурье
Давайте начнем с рассмотрения преобразования Фурье в одном измерении. Мы создадим тестовые данные во временной области, используя функцию широкого прямоугольника.
f = [abs(x) <= 1 ? 1 : 0 for x in -5:0.1:5];
plot(real(f))
Теперь преобразуем данные в частотную область, используя fft(), и построим спектр сигнала с помощью модуля комплексного числа.
FFT = fft(f);
typeof(FFT)
abs_FFT = sqrt.(real(FFT).^2+imag(FFT).^2)
plot(abs_FFT)
Данные частотной области представляют собой массив типа Complex с той же длиной, что и данные временной области.
Поскольку каждое комплексное число состоит из двух частей (действительной и мнимой), кажется, что мы каким-то образом удвоили информационное содержание нашего сигнала. Это не так: половина данных частотной области избыточна. Функция fftshift() удобно перестраивает данные в частотной области таким образом, что отрицательные частоты находятся слева.
F = fftshift(FFT);
abs_F = sqrt.(real(F).^2+imag(F).^2)
plot(abs_F)
Аналитическое преобразование Фурье функции прямоугольника представляет собой функцию sinc , которая хорошо согласуется с числовыми данными на графиках выше.
Двумерное преобразование Фурье
Рассмотрим аналогичную двумерную задачу. Но на этот раз мы пойдем в противоположном направлении, начав с двумерной функции sinc и взяв ее преобразование Фурье.
Построить массив данных sinc легко с помощью генератора списков.
f = [(r = sqrt(x^2 + y^2); sinc(r)) for x in -6:0.125:6, y in -6:0.125:6];
plot(f)
Нет особого смысла думать о двумерной функции во временной области. Но преобразование Фурье работает как с временным сигналом, так и с пространственным сигналом (или сигналом практически в любой другой области). Итак, предположим, что наши двумерные данные находятся в пространственной области.
heatmap(f)
Генерация преобразования Фурье для многомерных сигналов также выполняется при помощи fft().
F = fft(f);
F = fftshift(F);
abs_F = sqrt.(real(F).^2+imag(F).^2)
heatmap(abs_F)
Вывод
Помимо описанного выше, применять БПФ удобно и к данным более высокой размерности.
Большая часть функционала библиотеки FFTW реализована в интерфейсе Julia.
Как именно:
- Генерировать планы для оптимизированных БПФ, используя plan_fft();
- Использовать дискретное косинусное преобразование при помощи dct();
- Использовать сопряженную симметрию в реальных преобразованиях, используя rfft();
- Также можно запустить несколько потоков через FFTW.set_num_threads().