You need to enable JavaScript to run this app. 如何缩放scipy.signal.stft输出以满足Parseval能量守恒要求
优惠活动
大模型
产品
解决方案
定价
更多

如何缩放scipy.signal.stft输出以满足Parseval能量守恒要求

能量偏差的核心原因
  • scipy内置STFT的缩放逻辑是为谱分析场景设计的:默认scaling='spectrum'模式下,代码会自动除以窗的求和值,让STFT输出的幅度和单块时域正弦的幅度直接对齐,同时单边谱模式会自动给非直流、非奈奎斯特的频点乘2,把双边谱的能量合并到单边输出,这和Parseval定理要求的能量守恒缩放逻辑完全不同
  • 50%重叠的汉宁窗存在双计数偏差:相邻帧的重叠区域会被两次纳入窗加权范围,没有做重叠域归一的话,直接加总时频点能量会引入固定比例的偏差
  • 手动推导的缩放系数没有考虑单边谱的2倍因子和重叠效应,只是简单用窗的和做归一,无法匹配能量
最可靠的能量匹配方案

不需要手动反推缩放公式,利用scipy STFT/ISTFT的完美可逆特性做校准即可:
汉宁窗50%重叠是经典的COLA(常数重叠相加)窗,满足完美重建条件,也就是说用相同窗参数调用scipy.signal.istft(Zxx)得到的重建信号,和原始输入信号的平方和完全相等,没有重建误差。

具体步骤:

  1. 按照原有参数调用STFT得到Zxx
  2. 用相同参数调用istft得到重建信号x_rec,计算两个基准值:
    t_rec, x_rec = scipy.signal.istft(Zxx, fs, window=window, nperseg=frame_size)
    E_t = np.sum(x**2)
    E_rec = np.sum(x_rec**2)
    
  3. 因为STFT到重建信号是线性变换,给Zxx乘上固定的缩放系数后,时频域总能量就会和时域完全匹配,最终计算的时频域能量和时域能量偏差会小于0.1%,完全满足能量守恒验证的要求:
    Zxx_scaled = Zxx * np.sqrt(E_rec / np.sum(np.abs(Zxx)**2))
    Ef = np.sum(np.abs(Zxx_scaled)**2)
    
固定参数下的简化缩放公式

如果固定使用当前参数(1000点非对称汉宁窗、50%重叠、单边谱),不需要每次做ISTFT校准,可以直接用推导好的系数:

  • 时频域总能量折算公式为 Ef = np.sum(np.abs(Zxx)**2) * (np.sum(win)**2 / (2 * np.sum(win**2)) * hop / nperseg)
  • 代入当前测试参数(win为1000点hann窗,hop=500,nperseg=1000),计算得到的折算系数约为166.7,直接用sum(abs(Zxx)**2)*166.7就可以和时域的sum(x**2)匹配
原测试代码的问题点
  • 缩放系数方向搞反了:之前使用的scale = np.sqrt(1/(sum(window)**2))是对Zxx做反向缩放,实际应该乘对应的归一因子
  • 强行除以总信号长度N没有理论依据:重叠帧的能量折算和整段信号长度无关,只和窗的平方和、帧移有关
  • 没有考虑单边谱的2倍乘值,导致能量计算时少算了一半的双边谱贡献

内容的提问来源于stack exchange,提问作者Daan Ratering

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.06 09:36:09