filtfilt
est un filtrage de phase zéro, qui ne décale pas le signal pendant qu'il filtre. La phase étant nulle à toutes les fréquences, elle est également linéaire. Le filtrage en arrière dans le temps vous oblige à prévoir l'avenir, il ne peut donc pas être utilisé dans des applications réelles "en ligne", uniquement pour le traitement hors ligne d'enregistrements de signaux.
lfilter
est un filtrage causal direct dans le temps uniquement, semblable à un filtre électronique réel. Cela ne peut pas être en phase zéro. Il peut s'agir d'une phase linéaire (FIR symétrique), mais ce n'est généralement pas le cas. Habituellement, il ajoute différentes quantités de retard à différentes fréquences.
Un exemple et une image devraient le rendre évident. Bien que l'amplitude de la réponse en fréquence des filtres soit identique (en haut à gauche et en haut à droite), le passe-bas à phase nulle s'aligne avec le signal d'origine, juste sans contenu haute fréquence, tandis que le filtrage de phase minimum retarde le signal de manière causale :
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")