6.14. FFT

傅立葉轉換(Fourier transform)會將時域訊號分解為其組成頻率。快速傅立葉轉換fast Fourier transformFFT)則是高效計算傅立葉轉換的標準演算法,這正是本模組存在的原因,也是長度足以實用的轉換(1024 點、4096 點)能在微控制器上順利完成的關鍵。

在相機上,輸入通常是一段來自麥克風、加速度計某一軸、電流感測器或振動探針的等間隔取樣緩衝區;輸出則是一段頻譜,供應用程式接著從中檢查峰值、能量或分類器特徵。

numpy.fft 提供一維離散傅立葉轉換。其兩個函式分別為 fft()(正轉換)與 ifft()(逆轉換,以 N 進行正規化)。

轉換長度必須是 2 的次方。其他長度會引發 ValueErrorN = 256N = 1024 是常見的選擇:在大多數嵌入式取樣率下足以提供可用的頻率解析度,又夠短到能放進 RAM 並在單一影格週期內充裕完成。

fft() 以輸入的實部作為第一個位置引數、以可選的虛部作為第二個引數,並回傳由實數陣列組成的二元組 (real, imag)

6.14.1. 實數輸入、幅值輸出

當應用程式僅輸入實數、且只需要幅值頻譜時:

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

結果是一個與輸入等長的實數 ndarrayspectrogram() 輔助函式正好能完成此事,且不需中間的記憶體配置,是串流迴圈內的正確選擇。

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 的次方。

  2. 進行 FFT。

  3. 找出幅值最大的頻率區間(bin)。

  4. 使用取樣率將頻率區間索引換算成 Hz。

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