полосовой фильтр fft в python

Я пытаюсь фильтровать свои данные с помощью fft. У меня есть шумный сигнал, записанный с 500Гц в 1д массив. Моя высокочастотная должна отрезать с 20Hz и моя низкочастотная с 10Hz. То, что я пробовал, это:

fft=scipy.fft(signal) 
bp=fft[:]  
for i in range(len(bp)): 
    if not 10<i<20:
        bp[i]=0

ibp=scipy.ifft(bp)

теперь я получаю комплексные числа. Значит, что-то не так. Что? Как я могу исправить свой код?

2 ответов


стоит отметить, что величина единиц bp не обязательно будут В Гц, но зависят от частоты дискретизации сигнала, вы должны использовать scipy.fftpack.fftfreq для преобразования. Также, если ваш сигнал вы должны использовать scipy.fftpack.rfft. Вот минимальный рабочий пример, который отфильтровывает все частоты меньше указанной суммы:

import numpy as np
from scipy.fftpack import rfft, irfft, fftfreq

time   = np.linspace(0,10,2000)
signal = np.cos(5*np.pi*time) + np.cos(7*np.pi*time)

W = fftfreq(signal.size, d=time[1]-time[0])
f_signal = rfft(signal)

# If our original signal time was in seconds, this is now in Hz    
cut_f_signal = f_signal.copy()
cut_f_signal[(W<6)] = 0

cut_signal = irfft(cut_f_signal)

мы можем построить эволюцию сигнала в реальном и Фурье пространство:

import pylab as plt
plt.subplot(221)
plt.plot(time,signal)
plt.subplot(222)
plt.plot(W,f_signal)
plt.xlim(0,10)
plt.subplot(223)
plt.plot(W,cut_f_signal)
plt.xlim(0,10)
plt.subplot(224)
plt.plot(time,cut_signal)
plt.show()

enter image description here


есть фундаментальный недостаток в том, что вы пытаетесь сделать здесь - вы применяете прямоугольное окно в частотной области, которое приведет к сигналу временной области, который был свернут с функцией sinc. Другими словами, в сигнале временной области будет большое количество "звона" из-за изменений шага, которые вы ввели в частотной области. Правильный способ сделать этот вид фильтрации частотной области-применить подходящий функция окна в частотная область. Любая хорошая вводная книга DSP должна охватывать это.