6.14. FFT

Перетворення Фур’є розкладає сигнал у часовій області на складові частоти. Швидке перетворення Фур’є (FFT) — це стандартний алгоритм ефективного обчислення цього перетворення; саме тому існує цей модуль і саме тому перетворення достатньої довжини (1024 точки, 4096 точок) є прийнятними на мікроконтролері.

На камері вхідними даними зазвичай є буфер рівновіддалених зразків від мікрофона, осі акселерометра, датчика струму або вібродавача; на виході — спектр, який застосунок аналізує на наявність піків, енергії або ознак класифікатора.

numpy.fft забезпечує одновимірне дискретне перетворення Фур’є. Дві функції: fft() (пряме) та ifft() (обернене, нормалізоване на N).

Довжина перетворення має бути степенем двійки. Інші довжини викликають ValueError. N = 256 та N = 1024 — поширені варіанти: достатньо довгі для прийнятної частотної роздільної здатності на більшості вбудованих частот дискретизації, і достатньо короткі, щоб поміститися в RAM і завершитися задовго до закінчення одного кадрового інтервалу.

fft() приймає дійсну частину вхідних даних як перший позиційний аргумент та необов’язкову уявну частину як другий, і повертає двокортеж (real, imag) із дійсних масивів.

6.14.1. Дійсний вхід, амплітудний вихід

Коли застосунок подає лише дійсний вхід і потребує лише амплітудного спектра:

real, imag = np.fft.fft(x)
magnitude  = np.sqrt(real * real + imag * imag)

Результат — дійсний ndarray тієї самої довжини, що й вхід. Допоміжна функція spectrogram() виконує рівно те саме без проміжних виділень пам’яті — це правильний виклик у циклі потокової обробки.

6.14.2. Обернене перетворення

ifft() нормалізована так, що цикл прямого та оберненого перетворення повертає вихідний вхід з точністю до похибки операцій з рухомою крапкою. Обидва виклики приймають і повертають пару дійсних масивів:

real, imag       = np.fft.fft(y)
re_back, im_back = np.fft.ifft(real, imag)

6.14.3. Пошук домінантної частоти

Поширений шаблон — пошук найбільшого піка в буфері зразків (звук, вібрація, модульований ІЧ-сигнал). Алгоритм:

  1. Зчитати N зразків, де N є степенем двійки.

  2. Обчислити FFT.

  3. Знайти бін з найбільшою амплітудою.

  4. Перетворити індекс біна в Гц, використовуючи частоту дискретизації.

from ulab import numpy as np

N  = 1024
fs = 8000.0                       # sample rate, Hz

# ... fill ``samples`` with N data points ...

real, imag = np.fft.fft(samples)
spectrum   = np.sqrt(real * real + imag * imag)

half      = spectrum[:N // 2]     # only first half is meaningful
peak_bin  = np.argmax(half)
peak_hz   = peak_bin * fs / N

print("peak at", peak_hz, "Hz")