6.14. FFT

การแปลงฟูเรียร์ (Fourier transform) จะแยกสัญญาณในโดเมนเวลาออกเป็นความถี่ส่วนประกอบต่าง ๆ การแปลงฟูเรียร์แบบเร็ว (FFT) คืออัลกอริทึมมาตรฐานสำหรับการคำนวณนี้อย่างมีประสิทธิภาพ ซึ่งเป็นเหตุผลที่โมดูลนี้มีอยู่ และเป็นเหตุผลที่การแปลงที่มีความยาวเพียงพอสำหรับการใช้งานจริง (1024 จุด, 4096 จุด) สามารถทำได้บนไมโครคอนโทรลเลอร์

สำหรับกล้อง อินพุตมักจะเป็นบัฟเฟอร์ของตัวอย่างที่เว้นระยะห่างเท่ากันจากไมโครโฟน แกนของมาตรวัดความเร่ง เซนเซอร์กระแสไฟ หรืออุปกรณ์ตรวจจับการสั่นสะเทือน ส่วนเอาต์พุตคือสเปกตรัมที่แอปพลิเคชันตรวจสอบหาจุดสูงสุด พลังงาน หรือลักษณะเด่นสำหรับตัวจำแนกประเภท

numpy.fft ให้การแปลงฟูเรียร์แบบแยกส่วนหนึ่งมิติ ฟังก์ชันทั้งสองคือ fft() (ไปข้างหน้า) และ ifft() (ผกผัน ทำให้เป็นมาตรฐานโดย N)

ความยาวของการแปลงต้องเป็นกำลังของสอง ความยาวอื่น ๆ จะทำให้เกิด ValueError โดย N = 256 และ N = 1024 เป็นตัวเลือกทั่วไป ยาวพอสำหรับความละเอียดความถี่ที่ใช้งานได้ในอัตราการสุ่มตัวอย่างแบบฝังตัวส่วนใหญ่ และสั้นพอที่จะพอดีกับ RAM และเสร็จสิ้นภายในเวลาหนึ่งช่วงเฟรม

fft() รับส่วนจริงของอินพุตเป็นอาร์กิวเมนต์เชิงตำแหน่งแรก และส่วนจินตภาพเป็นตัวเลือกที่สอง แล้วคืนค่าเป็น 2-tuple (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. การหาความถี่ที่โดดเด่น

รูปแบบทั่วไปคือการหาจุดสูงสุดที่ใหญ่ที่สุดในบัฟเฟอร์ของตัวอย่าง ไม่ว่าจะเป็นเสียง การสั่นสะเทือน หรือ IR แบบมอดูเลต สูตร:

  1. จับตัวอย่าง N รายการ โดยที่ N เป็นกำลังของสอง

  2. ทำ FFT

  3. หาถังที่มีขนาดใหญ่ที่สุด

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