scipy.signalでフィルターを適用する:lfilterまたはfiltfiltを使用しますか?


21

私はSOスレッドで、のfiltfilt代わりに後方/前方フィルタリングを実行するための提案を使用しましたlfilter

他の手法に対して1つを使用する動機は何ですか?


Filtfiltが遅い
アーロン14年


1
@Aaron filtfiltは同じフィルターを反対方向にlfilter2回行うため、1方向に2回行うよりも遅くなりません。これは同じ周波数応答を得る方法です。
エンドリス

ええ、それだけです。それは2倍遅いです。
アーロン14

私はこれが初めてであり、filtfiltを使用するために見回っていました。@endolithは、scipy.signalは元の信号を使用すると述べました。元の信号が何を意味し、どのようにそれを取得するのか分かりません。システムに読み込むWAVファイルがありますが、numpy配列とサンプル数に分割されているため、元の信号ではないと思います。誰か助けてください。ありがとうございました!
アルニマパタニア18

回答:


30
  • filtfiltゼロ位相フィルタリングであり、フィルタリング時に信号をシフトしません。位相はすべての周波数でゼロであるため、線形位相でもあります。時間をさかのぼってフィルタリングするには、将来を予測する必要があるため、「オンライン」の実際のアプリケーションでは使用できず、信号の記録のオフライン処理にのみ使用できます。

  • lfilterは、実際の電子フィルターに似た、因果的な前方フィルタリングのみです。ゼロフェーズにすることはできません。線形位相(対称FIR)にできますが、通常はそうではありません。通常、異なる周波数で異なる量の遅延を追加します。

例と画像はそれを明らかにするはずです。フィルターの周波数応答の大きさは同じですが(左上と右上)、ゼロ位相ローパスは元の信号と並んでおり、高周波成分はまったくありませんが、最小位相フィルタリングは信号を因果的に遅延させます:

filtfilt vs lfilter

from __future__ import division, print_function
import numpy as np
from numpy.random import randn
from numpy.fft import rfft
from scipy import signal
import matplotlib.pyplot as plt

b, a = signal.butter(4, 0.03, analog=False)

# Show that frequency response is the same
impulse = np.zeros(1000)
impulse[500] = 1

# Applies filter forward and backward in time
imp_ff = signal.filtfilt(b, a, impulse)

# Applies filter forward in time twice (for same frequency response)
imp_lf = signal.lfilter(b, a, signal.lfilter(b, a, impulse))

plt.subplot(2, 2, 1)
plt.semilogx(20*np.log10(np.abs(rfft(imp_lf))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('lfilter')

plt.subplot(2, 2, 2)
plt.semilogx(20*np.log10(np.abs(rfft(imp_ff))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('filtfilt')

sig = np.cumsum(randn(800))  # Brownian noise
sig_ff = signal.filtfilt(b, a, sig)
sig_lf = signal.lfilter(b, a, signal.lfilter(b, a, sig))
plt.subplot(2, 1, 2)
plt.plot(sig, color='silver', label='Original')
plt.plot(sig_ff, color='#3465a4', label='filtfilt')
plt.plot(sig_lf, color='#cc0000', label='lfilter')
plt.grid(True, which='both')
plt.legend(loc="best")

4
lfilterは必ずしも最小位相ではなく、フィルター係数に応じて何でもかまいませんが、いずれにせよ因果関係があり、そうでfiltfiltはありません。したがって、filtfilt遅延がゼロで、lfilter常に何らかの遅延が追加される比較の結果は、filtfiltそもそも非因果的であるため、正確には真ではありません。実際に重要なのは、filtfilt位相歪みを引き起こさないのに対し、それlfilterが線形位相FIRフィルターとして使用されない限り、つまり分母= 1の場合です。
マットL. 14年

また、N次のfiltfiltフィルタリングは、(2N-1)次のフィルタリングに対応することに注意してくださいlfilter
トーマスアリドセン14年

@ThomasArildsenそれはちょうど2Nではありませんか?それは私がスクリプトに示されているものだ
endolith

@ArunimaPathaniaあなたは質問の下ではなく、私の答えの下にコメントすべきです。「オリジナル信号」とは、フィルタリングしている信号を意味します。lfilterまたはでフィルタリングできますfiltfilt。示したように彼らは、異なる動作を
endolith

7

@endolithによる回答は完全かつ正確です!最初に彼の投稿を読んでから、それに加えてこれを読んでください。評判が悪いため、コメントに返信できませんでした @ Thomas Arildsen@endolithが次の方法で得られたフィルターの効果的な順序について議論返信filtfilt

  • lfilter 与えられたフィルターを適用し、フーリエ空間でこれはフィルター伝達関数を一度適用するようなものです。

  • filtfilt同じフィルターを2回適用すると、効果はフィルター伝達関数SQUAREDを適用するようなものになります。バタワースフィルターの場合(scipy.signal.butter)の、伝達関数

Gn=11ω2nどこで n フィルターの順序

有効なゲインは

Gnfltflt=Gn2=11ω2n

そして、これはとして解釈することはできません2n2n1次のバタワースフィルター

GnfltfltG2n

1
回答としてコメントを追加しないようにしてください。ただし、SE.DSPへようこそ。私から+1を受け取っています。私はこれが答えに追加すると思う...少なくともコメントするのに十分な担当者を獲得しようとする!:-)
ピーターK。

私はこれが真実だとは思わない。G(n)は、フィルターの振幅ゲインです。複雑な伝達関数をカスケードすると、2nになります。
マイク

クイックシミュレーションで、6次のバターワースは2 x(3次のバターワース)カスケードと同じG(ω)を与えるが、3次のカットオフ周波数は1.6にスケーリングされることを確認しました。結果は、カットオフ周波数のスケーリングを除いて同一です。そのため、次数は2nでスケーリングしますが、カスケードすると通過帯域が減少し、補正する必要があることに注意してください。誰かが自由に理論を説明できますが、私は本当にすべての数学をやりたくありません。
マイク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.