Документация Engee
Notebook

Методы Фурье

Открыть пример в Engee

Для обработки сигналов часто применяется такой метод, как преобразование Фурье. Этот метод позволяет преобразовывать сигнал между временной областью и частотной областью. Эффективный алгоритм быстрого преобразования Фурье (БПФ) реализован в Julia с использованием библиотеки FFTW.

In [ ]:
using FFTW

1D преобразование Фурье

Давайте начнем с рассмотрения преобразования Фурье в одном измерении. Мы создадим тестовые данные во временной области, используя функцию широкого прямоугольника.

In [ ]:
f = [abs(x) <= 1 ? 1 : 0 for x in -5:0.1:5];
plot(real(f))
Out[0]:

Теперь преобразуем данные в частотную область, используя fft(), и построим спектр сигнала с помощью модуля комплексного числа.

In [ ]:
FFT = fft(f);
typeof(FFT)
Out[0]:
Vector{ComplexF64} (alias for Array{Complex{Float64}, 1})
In [ ]:
abs_FFT = sqrt.(real(FFT).^2+imag(FFT).^2)
plot(abs_FFT)
Out[0]:

Данные частотной области представляют собой массив типа Complex с той же длиной, что и данные временной области.

Поскольку каждое комплексное число состоит из двух частей (действительной и мнимой), кажется, что мы каким-то образом удвоили информационное содержание нашего сигнала. Это не так: половина данных частотной области избыточна. Функция fftshift() удобно перестраивает данные в частотной области таким образом, что отрицательные частоты находятся слева.

In [ ]:
F = fftshift(FFT);
abs_F = sqrt.(real(F).^2+imag(F).^2)
plot(abs_F)
Out[0]:

Аналитическое преобразование Фурье функции прямоугольника представляет собой функцию sinc , которая хорошо согласуется с числовыми данными на графиках выше.

Двумерное преобразование Фурье

Рассмотрим аналогичную двумерную задачу. Но на этот раз мы пойдем в противоположном направлении, начав с двумерной функции sinc и взяв ее преобразование Фурье.

Построить массив данных sinc легко с помощью генератора списков.

In [ ]:
f = [(r = sqrt(x^2 + y^2); sinc(r)) for x in -6:0.125:6, y in -6:0.125:6];
plot(f)
Out[0]:

Нет особого смысла думать о двумерной функции во временной области. Но преобразование Фурье работает как с временным сигналом, так и с пространственным сигналом (или сигналом практически в любой другой области). Итак, предположим, что наши двумерные данные находятся в пространственной области.

In [ ]:
heatmap(f)
Out[0]:

Генерация преобразования Фурье для многомерных сигналов также выполняется при помощи fft().

In [ ]:
F = fft(f);
F = fftshift(F);
abs_F = sqrt.(real(F).^2+imag(F).^2)
heatmap(abs_F)
Out[0]:

Вывод

Помимо описанного выше, применять БПФ удобно и к данным более высокой размерности.

Большая часть функционала библиотеки FFTW реализована в интерфейсе Julia.

Как именно:

  1. Генерировать планы для оптимизированных БПФ, используя plan_fft();
  2. Использовать дискретное косинусное преобразование при помощи dct();
  3. Использовать сопряженную симметрию в реальных преобразованиях, используя rfft();
  4. Также можно запустить несколько потоков через FFTW.set_num_threads().