6.14. FFT

Fourier-muunnos hajottaa aika-alueen signaalin sen muodostaviin taajuuksiin. Nopea Fourier-muunnos (FFT) on vakioalgoritmi sen tehokkaaseen laskemiseen – syy tämän moduulin olemassaoloon ja syy siihen, että hyödyllisen pituiset muunnokset (1024 pistettä, 4096 pistettä) ovat ylipäätään käsiteltävissä mikro-ohjaimella.

Kamerassa syöte on tyypillisesti puskuri tasavälisiä näytteitä mikrofonista, kiihtyvyysanturin akselilta, virta-anturilta tai tärinäkoettimesta; tuloste on spektri, jota sovellus sitten tarkastelee huippujen, energian tai luokittelijan piirteiden varalta.

numpy.fft tarjoaa yksiulotteisen diskreetin Fourier-muunnoksen. Kaksi funktiota ovat fft() (eteenpäin) ja ifft() (käänteinen, normalisoitu kertoimella N).

Muunnoksen pituuden on oltava kahden potenssi. Muut pituudet nostavat ValueError. N = 256 ja N = 1024 ovat yleisiä valintoja: riittävän pitkiä käyttökelpoiseen taajuusresoluutioon useimmilla sulautetuilla näytteenottotaajuuksilla, riittävän lyhyitä mahtuakseen RAM-muistiin ja valmistuakseen hyvin yhden kehysjakson sisällä.

fft() ottaa syötteen reaaliosan ensimmäisenä paikkaargumenttinaan ja valinnaisen imaginaariosan toisena, ja palauttaa 2-monikon (real, imag) reaaliarvotaulukoita.

6.14.1. Reaalisyöte, magnitudituloste

Kun sovellus syöttää vain reaalisyötettä ja tarvitsee vain magnitudispektrin:

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

Tulos on reaaliarvoinen ndarray, joka on samanpituinen kuin syöte. Apufunktio spectrogram() tekee juuri tämän ilman välivaiheen varauksia – oikea kutsu suoratoistosilmukan sisällä.

6.14.2. Käänteismuunnos

ifft() on normalisoitu siten, että edestakainen kierros palauttaa alkuperäisen syötteen liukulukutarkkuuden rajoissa. Molemmat kutsut ottavat ja palauttavat parin reaaliarvotaulukoita:

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

6.14.3. Hallitsevan taajuuden löytäminen

Yleinen kaava on suurimman huipun paikantaminen näytepuskurista – ääni, tärinä, moduloitu IR. Resepti:

  1. Kaappaa N näytettä, missä N on kahden potenssi.

  2. Ota FFT.

  3. Etsi suurimman magnitudin omaava lokero.

  4. Muunna lokeron indeksi hertseiksi näytteenottotaajuuden avulla.

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