6.14. FFT

Fourierova transformace rozkládá signál v časové oblasti na jeho jednotlivé frekvenční složky. Rychlá Fourierova transformace (FFT) je standardní algoritmus pro její efektivní výpočet – důvod, proč tento modul existuje, a důvod, proč jsou na mikrokontroléru vůbec zvládnutelné transformace dostatečně dlouhé na to, aby byly užitečné (1024 bodů, 4096 bodů).

Na kameře je vstupem obvykle buffer rovnoměrně rozložených vzorků z mikrofonu, z osy akcelerometru, z proudového senzoru nebo z vibrační sondy; výstupem je spektrum, které aplikace následně zkoumá kvůli vrcholům, energii nebo příznakům pro klasifikátor.

numpy.fft poskytuje jednorozměrnou diskrétní Fourierovu transformaci. Tyto dvě funkce jsou fft() (dopředná) a ifft() (zpětná, normalizovaná hodnotou N).

Délka transformace musí být mocninou dvou. Jiné délky vyvolají ValueError. N = 256 a N = 1024 jsou běžné volby: dostatečně dlouhé pro použitelné frekvenční rozlišení při většině vestavěných vzorkovacích frekvencí, dostatečně krátké, aby se vešly do RAM a dokončily se s rezervou během jedné periody snímku.

fft() přijímá reálnou část vstupu jako svůj první poziční argument a volitelnou imaginární část jako druhý a vrací 2-tici (real, imag) reálných polí.

6.14.1. Reálný vstup, výstup velikosti (magnitudy)

Když aplikace předává pouze reálný vstup a potřebuje pouze spektrum velikostí (magnitud):

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

Výsledkem je reálné ndarray o stejné délce jako vstup. Pomocná funkce spectrogram() dělá přesně toto bez mezilehlých alokací – správná volba uvnitř streamovací smyčky.

6.14.2. Zpětná transformace

ifft() je normalizována tak, aby celý cyklus vrátil původní vstup v rámci chyby pohyblivé řádové čárky. Oba volání přijímají a vracejí dvojici reálných polí:

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

6.14.3. Nalezení dominantní frekvence

Běžným vzorem je nalezení největšího vrcholu v bufferu vzorků – zvuk, vibrace, modulované IR. Postup:

  1. Zachyťte N vzorků, kde N je mocnina dvou.

  2. Proveďte FFT.

  3. Najděte bin s největší velikostí (magnitudou).

  4. Převeďte index binu na Hz pomocí vzorkovací frekvence.

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")