Scipy中Bessel迭代滤波与单次滤波结果不一致问题
Bessel滤波单次处理与迭代处理结果不一致的原因与解决方法
问题根源
单次调用scipy.signal.lfilter()时,默认采用零初始条件(滤波器所有延迟单元的初始值为0);而scipy.signal.lfilter_zi()返回的是稳态初始条件——即假设输入信号为恒定值1时,滤波器进入稳态后的内部状态值。
当第一个输入值为0时,两种初始条件的差异会直接导致输出不同:
- 单次滤波:初始状态全0,输入0时输出直接为0
- 迭代滤波:初始状态是对应输入1的稳态值,输入0时滤波器会从稳态向0过渡,因此第一个输出接近1(即你看到的0.999...)
解决方法
要让迭代滤波与单次滤波结果完全一致,需将迭代版本的初始状态设置为零向量,替代lfilter_zi()返回的稳态值:
import scipy.signal import numpy as np fc_bessel = 0.14 # [Hz] ordre_bessel = 3 b,a = scipy.signal.bessel(ordre_bessel, fc_bessel, 'low', analog=False, output='ba', fs=300) # 初始化零初始状态,长度等于滤波器阶数 z = np.zeros(max(len(b), len(a)) - 1) filter_iter = [] for input_value in input_data: filtered_value, z = scipy.signal.lfilter(b, a, [input_value], zi=z) filter_iter.append(filtered_value[0])
补充说明
- 如果是实时处理冷启动场景(和单次处理未接收过任何数据的状态一致),零初始条件是正确选择。
- 如果需要滤波器快速跟踪恒定输入(比如系统启动后输入很快稳定),才适合使用
lfilter_zi()的稳态初始条件,此时可将zi缩放为zi * initial_input_value,让初始输出直接匹配输入稳态。
内容的提问来源于stack exchange,提问作者jpo38
相关产品推荐
相关产品推荐

