6.14. FFT¶
傅立葉轉換(Fourier transform)會將時域訊號分解為其組成頻率。快速傅立葉轉換(fast Fourier transform,FFT)則是高效計算傅立葉轉換的標準演算法,這正是本模組存在的原因,也是長度足以實用的轉換(1024 點、4096 點)能在微控制器上順利完成的關鍵。
在相機上,輸入通常是一段來自麥克風、加速度計某一軸、電流感測器或振動探針的等間隔取樣緩衝區;輸出則是一段頻譜,供應用程式接著從中檢查峰值、能量或分類器特徵。
numpy.fft 提供一維離散傅立葉轉換。其兩個函式分別為 fft()(正轉換)與 ifft()(逆轉換,以 N 進行正規化)。
轉換長度必須是 2 的次方。其他長度會引發 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. 尋找主頻¶
一種常見的模式是在一段取樣緩衝區中尋找最大峰值,無論是音訊、振動還是調變紅外線。做法如下:
擷取
N個樣本,其中N為 2 的次方。進行 FFT。
找出幅值最大的頻率區間(bin)。
使用取樣率將頻率區間索引換算成 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")