6.14. FFT

تُحلِّل تحويلة فورييه (Fourier transform) إشارةً في المجال الزمني إلى مكوناتها الترددية. أما تحويلة فورييه السريعة (FFT) فهي الخوارزمية القياسية لحساب ذلك بكفاءة -- وهي سبب وجود هذه الوحدة، وسبب أن التحويلات الطويلة بما يكفي لتكون مفيدة (1024 نقطة، 4096 نقطة) قابلة للتنفيذ على متحكم دقيق من الأساس.

على الكاميرا، يكون الدخل عادةً مخزنًا مؤقتًا من عينات متباعدة بالتساوي مأخوذة من ميكروفون، أو محور مقياس تسارع، أو مستشعر تيار، أو مجس اهتزاز؛ ويكون الخرج طيفًا يفحصه التطبيق بعد ذلك بحثًا عن القمم أو الطاقة أو ميزات المصنِّف.

توفر 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. أوجِد الخانة ذات أكبر مقدار.

  4. حوِّل دليل الخانة إلى هرتز باستخدام معدل أخذ العينات.

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