[Python] python信号处理绘制信号频谱

python信号处理绘制信号频谱:scipy.signal.welch

scipy.signal.welch 是 Python 中用于计算信号功率谱密度(PSD)的常用函数,采用 Welch 方法实现。这种方法通过将信号分段、加窗和平均来减少频谱估计的方差。以下是详细说明:

一、函数介绍

f, Pxx = scipy.signal.welch(
    x,                   # 输入信号
    fs=1.0,              # 采样频率
    window='hann',       # 窗函数
    nperseg=None,        # 每段长度
    noverlap=None,       # 重叠点数
    nfft=None,           # FFT长度
    detrend='constant',  # 去趋势方法
    return_onesided=True,# 是否返回单边谱
    scaling='density',   # 缩放类型
    axis=-1,             # 计算轴
    average='mean'       # 平均方法
)

二、核心参数详解

参数默认值说明
x-输入信号(1D数组或2D数组)
fs1.0采样频率(Hz),影响频率坐标
window‘hann’窗函数类型:‘hann’(汉宁窗)、‘hamming’(汉明窗)、‘blackman’(布莱克曼窗)、‘boxcar’(矩形窗)等
npersegNone每段长度(点数)。None时取256或len(x)较小值
noverlapNone段间重叠点数。None时为nperseg // 2(50%重叠)
nfftNoneFFT长度。None时等于nperseg;大于nperseg时进行零填充
detrend‘constant’去趋势方法:‘constant’(去均值)、‘linear’(去线性趋势)、False(不去趋势)
scaling‘density’输出缩放:‘density’(PSD, V²/Hz)、‘spectrum’(功率谱, V²)
average‘mean’平均方法:‘mean’(算术平均)、‘median’(中位数平均)

三、返回值

返回值说明
f频率数组(Hz)
Pxx功率谱密度数组(单位取决于scaling参数)

四、算法原理

  1. 分段:将长度为N的信号分成K段

    • 每段长度:nperseg
    • 段数: K = N − noverlap nperseg − noverlap K = \frac{N - \text{noverlap}}{\text{nperseg} - \text{noverlap}} K=npersegnoverlapNnoverlap
  2. 处理每段

    for segment in segments:
        # 1. 去趋势 (detrend)
        # 2. 加窗 (apply window)
        # 3. 计算FFT
        # 4. 计算周期图: |FFT|²
    
  3. 平均:对所有段的周期图进行平均
    P x x = avg ( ∣ F F T k ∣ 2 ) f s ⋅ S 2 P_{xx} = \frac{\text{avg}(|FFT_k|^2)}{f_s \cdot S_2} Pxx=fsS2avg(FFTk2)
    其中 S 2 = ∑ n = 0 N − 1 w [ n ] 2 S_2 = \sum_{n=0}^{N-1} w[n]^2 S2=n=0N1w[n]2 是窗函数的能量补偿因子

五、关键特性

  1. 方差减小:通过分段平均降低随机噪声影响
  2. 频率分辨率 Δ f = f s nperseg \Delta f = \frac{f_s}{\text{nperseg}} Δf=npersegfs
    • 增加nperseg ➔ 提高分辨率
    • 增加noverlap ➔ 增加段数(降低方差)
  3. 偏置-方差权衡
    • 长分段:低偏置、高方差
    • 短分段:高偏置、低方差

六、完整示例

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt

# 生成测试信号
fs = 1000  # 采样率
t = np.arange(0, 1, 1/fs)
x = np.sin(2*np.pi*50*t) + 0.5*np.sin(2*np.pi*120*t)  # 50Hz + 120Hz
x += 0.8 * np.random.randn(len(t))  # 添加高斯噪声

# 计算功率谱密度
f, Pxx = signal.welch(
    x,
    fs=fs,
    window='hann',      # 汉宁窗(默认)
    nperseg=1024,       # 每段1024点
    noverlap=512,       # 50%重叠
    nfft=2048,          # 2048点FFT(零填充)
    detrend='constant', # 去除均值
    scaling='density'   # 功率谱密度
)

# 绘制结果
plt.figure(figsize=(10, 5))
plt.semilogy(f, Pxx)  # 对数坐标
plt.title('Power Spectral Density (Welch Method)')
plt.xlabel('Frequency [Hz]')
plt.ylabel('PSD [V²/Hz]')
plt.xlim(0, 200)  # 限制显示范围
plt.grid(True)
plt.show()

绘制得到频谱图如下:
在这里插入图片描述

七、应用场景推荐配置

场景推荐参数
平稳信号nperseg=1024, noverlap=512
低信噪比信号增加noverlap(如75%)
高分辨率需求增大nperseg(牺牲计算速度)
瞬态信号分析减小nperseg,使用detrend='linear'
精确峰值测量使用window='flattop'(平坦窗)

八、常见问题解决

  1. 频率泄露

    • 改用旁瓣衰减更好的窗(如window='blackman'
    • 增加nperseg提高分辨率
  2. 弱信号被淹没

    # 使用中位数平均增强弱信号可见性
    f, Pxx = welch(..., average='median')
    
  3. 直流偏移影响

    # 确保去趋势
    f, Pxx = welch(..., detrend='constant')
    
  4. 频率坐标错误

    • 检查fs是否设置正确
    • 确认return_onesided=True(实信号)

九、与FFT方法的对比

特性welch直接FFT
方差
计算量中高
频率分辨率可调节固定
抗噪能力
适合信号类型长时记录、噪声信号短信号、瞬态信号

Welch 方法特别适合分析实际工程信号,在噪声环境下能提供更稳定的频谱估计结果。


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值