Python 如何获得链式IIR过滤器的b,a(分子/分母)?
假设我们已经先后应用了3个过滤器:Python 如何获得链式IIR过滤器的b,a(分子/分母)?,python,numpy,scipy,signal-processing,Python,Numpy,Scipy,Signal Processing,假设我们已经先后应用了3个过滤器: b, a = iirfilter(...) # or bilinear(...) or anything else producing b, a y = lfilter(b, a, x) b, a = iirfilter(...) y = lfilter(b, a, y) b, a = iirfilter(...) y = lfilter(b, a, y) 如何获得与3个过滤器等效的系数b2,a2,这样我们只需一次lfilter: y = lfilte
b, a = iirfilter(...) # or bilinear(...) or anything else producing b, a
y = lfilter(b, a, x)
b, a = iirfilter(...)
y = lfilter(b, a, y)
b, a = iirfilter(...)
y = lfilter(b, a, y)
如何获得与3个过滤器等效的系数b2
,a2
,这样我们只需一次lfilter
:
y = lfilter(b2, a2, x)
?
编辑:卷积似乎不起作用:
fs = 44100
b2, a2 = iirfilter(2, 2.0/fs * np.asarray([40, 60]), btype='bandstop') # 50 hz reject
b3, a3 = iirfilter(2, 2.0/fs * np.asarray([85, 115]), btype='bandstop') # 100 hz reject
b = np.convolve(b2, b3)
a = np.convolve(a2, a3)
w, h = signal.freqz(b, a, worN=10000)
给出:
我尝试使用np.convolve的相同的,完整的,有效的参数,但没有一个解决问题。请参阅
你可以分别卷积分子和分母
import scipy as sp
import scipy.signal as sig
# Individual filters
b1, a1 = sig.iirfilter(...)
b2, a2 = sig.iirfilter(...)
# Cascaded filter
a = sp.convolve(a1, a2)
b = sp.convolve(b1, b2)
y = sig.lfilter(b, a, x)
例如,给定的采样率太高,并且复合过滤器的阶数不够长,无法对接近的空值给出如此多的拒绝。降低采样率,然后向上插值44.1 kHz
以下是采样率降至4410 Hz的结果
fs = 4410.0
b2, a2 = sig.iirfilter(2, 2.0/fs * sp.asarray([40, 60]), btype='bandstop') # 50 hz reject
w2, h2 = sig.freqz(b2, a2, worN=4096)
b3, a3 = sig.iirfilter(2, 2.0/fs * sp.asarray([85, 115]), btype='bandstop') # 100 hz reject
w3, h3 = sig.freqz(b3, a3, worN=4096)
b = sp.convolve(b2, b3)
a = sp.convolve(a2, a3)
w, h = sig.freqz(b, a, worN=4096)
f = w/2.0*fs
然后将IIR滤波器的输出通过一个10倍内插滤波器,以返回到44.1 kHz采样率
或者,减少过滤器顺序:
fs = 44100.0
b2, a2 = sig.iirfilter(1, 2.0/fs * sp.asarray([40, 60]), btype='bandstop') # 50 hz reject
w2, h2 = sig.freqz(b2, a2, worN=4096)
b3, a3 = sig.iirfilter(1, 2.0/fs * sp.asarray([85, 115]), btype='bandstop') # 100 hz reject
w3, h3 = sig.freqz(b3, a3, worN=4096)
b = sp.convolve(b2, b3, 'full')
a = sp.convolve(a2, a3, 'full')
w, h = sig.freqz(b, a, worN=4096)
其原始采样率为44.1 kHz
是的,np.卷积。抱歉。请参阅我的问题@fstop_22末尾的编辑,它似乎不适用于convalve
。感谢您更新的答案。奇怪的是,我们不能用fs=44100来链接它们,因为当一个接一个地应用带阻时,过滤效果非常好。lfilter(b2,a2,lfilter(b3,a3,x))在数学上做什么?即使在50hz和100hz很接近的情况下,我们不能将其重写为单个lfilter吗?级联响应的零极点图是什么样子的?我不知道(在Python中从未这样做过),但在我的示例中,y=lfilter(b2,a2,x)
然后y=lfilter(b3,a3,y)
起作用(并且过滤非常完美),所以我想应该可以找到a,b
,这样我们就可以一次完成y=lfilter(b,a,x)
,而不考虑极点零点?如果你把第二个滤波器的零点移离第一个滤波器的零点,比如[850,1000],级联响应是正确的,并且显示两个零点。我怀疑两个滤波器的零极点位置相互干扰。不幸的是,scipy中没有zplane函数来显示零极点的位置。Hm ok@fstop_22,不确定是否完全理解。。。你能修改答案并给出一个在这种情况下的工作示例吗?(50 hz时的IIR滤波器带阻+100 hz时的IIR滤波器带阻)提前感谢您。