带有python的低频带通滤波器

信息处理 过滤器 Python 带通
2021-12-24 07:34:55

我有一个以 1 kHz 采样的信号,我想在第三个八度频带中进行分析。为此,我定义了具有比例带宽的巴特沃斯滤波器。这适用于较高的频率,但会产生非常奇怪的低频结果。我错过了什么?绘制的是巴特沃斯滤波器的频率响应。我在 Hanning 过滤器中发现了类似的行为,并认为我遗漏了一些基本的东西。

各种带通滤波器的频率响应 各种带通滤波器的频率响应

用于定义过滤器的代码:

import scipy
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt
def butter_bandpass(lowcut, highcut, fs, order=5, label=None):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = signal.butter(order, [low, high], btype='band')
    w, h = signal.freqz(b,a,worN=2000)
    plt.plot((fs * 0.5 / np.pi) * w, abs(h), label=label)
    return b, a

center_freqs = np.array([0.5* 2 ** (n * 1 / 3.) for n in range(0, 29)])
center_freqs.sort()
lower_freqs = 2. ** (-1 / 6.) * center_freqs
for lf in lower_freqs:
    butter_bandpass(lf, lf*2**(1/3.), fs=1000, order=5)

plt.show()
2个回答

我敢打赌这只是传递函数中的数值错误。尝试使用butter_sos = butter(..., output='sos')代替ba格式,而sosfreqz(butter_sos, ...)不是freqz. 这能解决吗?

https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.signal.sosfreqz.html

编辑:我刚刚尝试过,它确实如此。:D

import scipy
import numpy as np
from scipy import signal
from matplotlib import pyplot as plt
def butter_bandpass(lowcut, highcut, fs, order=5, label=None):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    sos = signal.butter(order, [low, high], btype='band', output='sos')
    w, h = signal.sosfreqz(sos,worN=20000)
    plt.semilogx((fs * 0.5 / np.pi) * w, abs(h), label=label)
    return sos

center_freqs = np.array([0.5* 2 ** (n * 1 / 3.) for n in range(0, 29)])
center_freqs.sort()
lower_freqs = 2. ** (-1 / 6.) * center_freqs
for lf in lower_freqs:
    butter_bandpass(lf, lf*2**(1/3.), fs=1000, order=5)

plt.show()

对数频率轴上的带通滤波器

通常,由于极点非常接近单位圆,因此具有仅占采样率一小部分的过渡带的 IIR 滤波器往往会变得不稳定(取决于使用的数字),因此差分方程中的状态变量由于相对于采样率的低频截止,需要为幅度响应累积足够大的数字和非常小的分数,以便脉冲响应持续大量的采样时间。