Документация 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))

Теперь преобразуем данные в частотную область, используя 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)

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

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

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

Аналитическое преобразование Фурье функции прямоугольника представляет собой функцию 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]:
020406080−0.200.20.40.60.81
y1y2y3y4y5y6y7y8y9y10y11y12y13y14y15y16y17y18y19y20y21y22y23y24y25y26y27y28y29y30y31y32y33y34y35y36y37y38y39y40y41y42y43y44y45y46y47y48y49y50y51y52y53y54y55y56y57y58y59y60y61y62y63y64y65y66y67y68y69y70y71y72y73y74y75y76y77y78y79y80y81y82y83y84y85y86y87y88y89y90y91y92y93y94y95y96y97

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

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

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

Вывод

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

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

Как именно:

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