You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用scipy.signal.decimate(ftype='fir')出现振荡,如何匹配Matlab结果?

Matlab与Scipy decimate(FIR模式)结果差异的原因及解决方案

问题重现

Matlab代码(v2019b)

artest = 1:109;
artestd = decimate(artest, 2, 'fir');
artestd(40:end)

输出末尾为连续奇数:79.0000 至 109.0000

Python代码(3.9.12,scipy 1.7.3)

import numpy as np
from scipy import signal as sg
artest = np.arange(1,110)
artestd = sg.decimate(artest, 2, ftype='fir')
artestd[39:]

输出末尾出现振荡:[79.0, 81.0,...114.35633594, 81.63376904]

差异原因分析

两者结果差异的核心在于滤波器设计参数、边缘处理逻辑的不同:

  1. 滤波器规格不匹配:
    • Matlab的decimate(A,2,'fir')默认使用30阶凯泽窗FIR滤波器(β=5),截止频率为归一化的0.25(对应下采样因子2的奈奎斯特频率的一半)。
    • Scipy的sg.decimate默认使用20阶凯泽窗FIR滤波器,且滤波采用单向的lfilter,未做延迟补偿。
  2. 边缘处理方式差异:
    • Matlab在处理FIR滤波时,会自动处理边界延迟,且滤波器阶数更高,通带内信号失真极小,下采样后能完整保留原信号的奇数点序列。
    • Scipy默认用lfilter做单向滤波,信号末尾采用零填充,当滤波器窗口无法覆盖足够样本时,会触发吉布斯振荡(边缘效应),导致末尾结果失真。

解决方案

要让Python输出与Matlab完全一致,需手动匹配Matlab的滤波器参数与处理流程:

import numpy as np
from scipy import signal as sg

# 1. 匹配Matlab的FIR滤波器参数:30阶凯泽窗(β=5),截止频率0.25
order = 30
cutoff = 1 / (2 * 2)  # 下采样因子为2,截止频率=1/(2*subsample)
window = sg.kaiser(order + 1, 5)
b = sg.fir1(order, cutoff, window=window)

artest = np.arange(1, 110)
# 2. 使用filtfilt双向滤波,消除延迟与边缘振荡
filtered_signal = sg.filtfilt(b, [1], artest)
# 3. 下采样取偶数索引(对应Matlab的1-based奇数位置)
artestd = filtered_signal[::2]

print(artestd[39:])

运行后输出末尾将与Matlab一致:[79.0, 81.0, ..., 109.0]

内容的提问来源于stack exchange,提问作者Warren Lewis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:41:06