6.14. FFT

התמרת פורייה מפרקת אות במישור הזמן לתדרים המרכיבים אותו. התמרת פורייה המהירה (FFT) היא האלגוריתם הסטנדרטי לחישוב יעיל של התמרה כזו – הסיבה שמודול זה קיים, והסיבה שהתמרות ארוכות מספיק כדי להיות שימושיות (1024 נקודות, 4096 נקודות) ניתנות לחישוב על גבי מיקרו-בקר מלכתחילה.

במצלמה, הקלט הוא בדרך כלל חוצץ (buffer) של דגימות במרווחים שווים ממיקרופון, מציר של מד תאוצה, מחיישן זרם או מגשש רעידות; הפלט הוא ספקטרום שהיישום בודק לאחר מכן לאיתור פסגות, אנרגיה או מאפיינים עבור מסווג.

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. מצא את התא (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")