web-dev-qa-db-ja.com

pythonのfftバンドパスフィルター

私がしようとしているのは、fftでデータをフィルター処理することです。 500Hzで1Dアレイとして記録されたノイズの多い信号があります。高周波は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)

私が今得ているのは複素数です。だから何かが間違っているに違いない。何?コードを修正するにはどうすればよいですか?

11
men in black

bpの単位の大きさは必ずしもHz単位である必要はありませんが、信号のサンプリング周波数に依存しているため、 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

20
Hooked

ここでやろうとしていることには根本的な欠陥があります-周波数領域で長方形のウィンドウを適用しているため、sinc関数で畳み込まれた時間領域信号になります。言い換えると、周波数領域で導入したステップの変化により、時間領域の信号に大量の「リンギング」が発生します。この種の周波数領域フィルタリングを行う適切な方法は、周波数領域で適切な ウィンドウ関数 を適用することです。優れた入門DSPブックはこれをカバーする必要があります。

7
Paul R