[英]Bandpass butterworth filter frequencies in scipy
I'm designing a bandpass filter in scipy following the cookbook . 我正在按照食谱设计scipy中的带通滤波器。 However, if I decrecrease the filtering frequencies too much I end up with garbage at high order filters.
但是,如果我过多地降低滤波频率,我会在高阶滤波器中使用垃圾。 What am I doing wrong?
我究竟做错了什么?
from scipy.signal import butter, lfilter
def butter_bandpass(lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band')
return b, a
if __name__ == "__main__":
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import freqz
# Sample rate and desired cutoff frequencies (in Hz).
fs = 25
# Plot the frequency response for a few different orders.
plt.figure(1)
plt.clf()
for order in [1, 3, 5, 6, 9]:
b, a = butter_bandpass(0.5, 4, fs, order=order)
w, h = freqz(b, a, worN=2000)#np.logspace(-4, 3, 2000))
plt.semilogx((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Gain')
plt.grid(True)
plt.legend(loc='best')
plt.figure(2)
plt.clf()
for order in [1, 3, 5, 6, 9]:
b, a = butter_bandpass(0.05, 0.4, fs, order=order)
w, h = freqz(b, a, worN=2000)#np.logspace(-4, 3, 2000))
plt.semilogx((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Gain')
plt.grid(True)
plt.legend(loc='best')
plt.show()
Update: the issue was discussed and apparently solved on Scipy 0.14. 更新:在Scipy 0.14上讨论并明显解决了这个问题。 However, the plot still looks really bad after Scipy update.
然而,在Scipy更新后,情节看起来仍然很糟糕。 What's wrong?
怎么了?
b, a = butter
for high-order filters, whether in Matlab or SciPy or Octave. b, a = butter
,无论是在Matlab,SciPy还是Octave中。 Transfer function format has numerical stability problems , because some of the coefficients are very large while others are very small. z, p, k = butter(output='zpk')
and then work with poles and zeros instead of numerator and denominator. z, p, k = butter(output='zpk')
,然后使用极点和零而不是分子和分母。 This is a common problem in digital filters. 这是数字滤波器中的常见问题。 High order filters with cutoff frequencies far below the nyquist frequency tend to have unstable coefficients due to the limited precision of floating point numbers.
由于浮点数的精度有限,截止频率远低于奈奎斯特频率的高阶滤波器往往具有不稳定的系数。 Last I checked (admittedly a couple of years ago) Matlab did a much better job of conserving precision than scipy, although it will still give problems with sufficiently extreme filters.
最后我检查了(不可否认的是几年前)Matlab在保存精度方面做得比scipy好得多,尽管它仍然会给出足够极端的过滤器问题。
There are a couple of options if you can't use matlab. 如果你不能使用matlab,有几个选项。 The first is to break your filter up into cascaded second order sections.
首先是将过滤器分解为级联的二阶段。 Basically you compute your desired poles and zeros, break them up into complex conjugate pairs, and compute the transfer function for each pair.
基本上,您计算所需的极点和零点,将它们分解为复共轭对,并计算每对的传递函数。
The second option is to resample to a sample rate more similar to the filter frequency. 第二种选择是重新采样到更类似于滤波器频率的采样率。 For instance, in your second example your sample rate is 25 and your highest cutoff frequency is .4.
例如,在您的第二个示例中,您的采样率为25,最高截止频率为.4。 You can use a low-pass anti-aliasing filter and then decimate by a factor of 10 to a sample rate of 2.5.
您可以使用低通抗混叠滤波器,然后将系数抽取10倍,采样率为2.5。 With the lower sampling rate, your bandpass filter coefficients will be less sensitive to rounding errors.
采样率越低,带通滤波器系数对舍入误差的敏感度越低。 If you do this, you have to make sure the anti-aliasing filter doesn't have the same problem.
如果这样做,您必须确保抗锯齿滤波器没有相同的问题。
What happens is that the orders of the bandpass (BP) filters created in the script are in fact the double of those shown in the plot . 会发生的是, 脚本中创建的带通(BP)过滤器的顺序实际上是图中显示的顺序的两倍 。 Recall that the order of the filter is the order of the polynomial in the denominator of the transfer function.
回想一下,滤波器的阶数是传递函数分母中多项式的阶数。 Canonic bandpass filters are always of even order .
Canonic 带通滤波器总是有序的 。
Those numbers shown are the orders of the low-pass (LP) prototype (usually normalized to a cutoff frequency of 1 rad/s) which is used to apply the LP-to-BP transformation which doubles the order of the filter. 所示的数字是低通(LP)原型的阶数(通常标准化为1rad / s的截止频率),其用于应用LP-to-BP变换,其使滤波器的阶数加倍。 So, for instance, if we start with an LP of order 1, we end up with a second order bandpass:
因此,例如,如果我们从订单1的LP开始,我们最终会得到二阶带通:
1/(S+1) => LP-2-BP transf.
1 /(S + 1) => LP-2-BP transf。 => ks/(s^2+a.s+b)
=> ks /(s ^ 2 + a.s + b)
Where k , a and b are constants. 其中k , a和b是常数。 The numerator of a standard bandpass filter is ks^ (N/2) and so the order N of the filter has to be even.
标准带通滤波器的分子是ks ^(N / 2) ,因此滤波器的阶数N必须是偶数。
This order issue for bandpass (which also happens to notches or band-reject filters) is not mentioned in SciPy documentation . 在SciPy 文档中未提及带通的订单问题(也适用于陷波或带阻滤波器)。 In fact, if you print the length of denominator a (by using
print(len(a))
) before plt.show()
, you will see it has 19 coefficients, what corresponds to a polynomial of 18th order. 事实上,如果你在
plt.show()
之前print(len(a))
分母a的长度(通过使用print(len(a))
plt.show()
,你会看到它有19个系数,对应于18阶多项式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.