6.14. FFT¶
Преобразование Фурье раскладывает сигнал из временной области на составляющие его частоты. Быстрое преобразование Фурье (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. Поиск доминирующей частоты¶
Распространённая задача – нахождение наибольшего пика в буфере отсчётов: аудио, вибрация, модулированный ИК-сигнал. Рецепт:
Захватите
Nотсчётов, гдеN– степень двойки.Выполните FFT.
Найдите бин с наибольшей амплитудой.
Преобразуйте индекс бина в Гц, используя частоту дискретизации.
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")