SciPy - 短时傅里叶变换 (STFT)
SciPy 中的短时傅里叶变换
SciPy 中的 短时傅里叶变换 (STFT) 是一种用于同时分析信号在时域和频域的工具。它通过使用滑动窗口将信号分成小的、重叠的片段,然后对每个片段执行傅里叶变换来工作。
结果是信号的时频表示,显示了其频率内容随时间的变化。从数学上讲,信号 x(t) 的 STFT 定义如下 −
X(t, f) = - x() w( - t) e-j 2 f d
其中 −
- x() 是信号
- w(t) 是以时间为中心对齐的窗函数
- ej2f 表示傅里叶变换。
- 和 分别是时间和频率变量。
窗函数 确保只有围绕 的信号小片段对该点的傅里叶变换有贡献。
STFT 的步骤
在 SciPy 中执行短时傅里叶变换的步骤如下 −
- 加窗: 这使用窗函数将信号分成重叠片段。窗函数通常选择为最小化频谱泄漏,例如 Hann、Hamming、Blackman。
- 傅里叶变换: 然后对每个加窗片段应用傅里叶变换。
- 时频表示: 最后将所有片段的结果组合,形成具有时间和频率轴的 2D 表示。
SciPy 中的短时傅里叶变换 (STFT)
In SciPy 中,我们有函数 scipy.signal.stft() 来执行 Short-Time Fourier Transform,它在参数方面提供了灵活性,例如窗口类型、段长度、重叠和 FFT 大小。
Syntax
以下是 scipy.signal.stft() 函数的语法,用于执行 Short-Time Fourier Transform −
scipy.signal.stft(x,fs=1.0,window='hann',nperseg=256,noverlap=None,nfft=None,detrend=False,return_onesided=True,boundary='zeros',padded=True,axis=-1,scaling='spectrum')
Parameters
以下是函数 scipy.signal.stft() 的参数 −
- x(array_like): 输入信号。要变换的数据。
- fs(float, optional): 输入信号的采样频率。默认为 1.0。
- window(str or tuple or array_like, optional): 应用于每个段的期望窗口函数。默认为 'hann'。
- nperseg(int, optional): STFT 中每个段的长度。默认为 256。
- noverlap(int, optional): 段之间重叠的点数。如果未指定,默认为 nperseg 的一半。
- nfft(int, optional): FFT 计算的点数。如果未提供,默认为 nperseg。
- detrend(str or function or bool, optional): 指定如何对每个段进行去趋势处理。默认为 False(不进行去趋势)。
- return_onesided(bool, optional): 如果为 True,则对于实信号返回单边谱。默认为 True。
- boundary(str or None, optional): 指定如何处理信号边界。默认为 'zeros'。
- padded(bool, optional): 如果为 True,则将每个段填充到最接近的 2 的幂。默认为 True。
- axis(int, optional): 计算 STFT 的轴。默认为 -1(最后一个轴)。
- scaling(str, optional): 确定 STFT 输出的缩放。选项有 'spectrum'(默认)和 'density'。
Basic Example
以下示例使用默认参数,通过函数 scipy.signal.stft() 计算并绘制由两个正弦波组成的信号的 STFT −
import numpy as np
from scipy.signal import stft
import matplotlib.pyplot as plt
# 创建一个简单信号
fs = 1000 # 采样频率
t = np.linspace(0, 2, 2 * fs, endpoint=False) # 2 秒的时间向量
x = np.sin(2 * np.pi * 50 * t) + np.sin(2 * np.pi * 120 * t) # 两个正弦波
# 计算 STFT
f, t, Zxx = stft(x, fs=fs, window='hann', nperseg=256, noverlap=128)
# 绘制 STFT 幅度
plt.figure(figsize=(10, 6))
plt.pcolormesh(t, f, np.abs(Zxx), shading='gouraud')
plt.title('STFT Magnitude')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.colorbar(label='Magnitude')
plt.show()
以下是 STFT 基本示例的输出 −
Adjusting Overlap
此示例展示了如何将段之间的重叠更改为 75%,从而获得更平滑的时频分辨率 −
import numpy as np
from scipy.signal import stft
import matplotlib.pyplot as plt
# 创建一个简单信号
fs = 1000 # 采样频率
t = np.linspace(0, 2, 2 * fs, endpoint=False) # 2 秒的时间向量
x = np.sin(2 * np.pi * 50 * t) + np.sin(2 * np.pi * 120 * t) # 两个正弦波
# 计算 STFT
f, t, Zxx = stft(x, fs=fs, window='hann', nperseg=256, noverlap=128)
# 绘制 STFT 幅度
plt.figure(figsize=(10, 6))
plt.pcolormesh(t, f, np.abs(Zxx), shading='gouraud')
plt.title('STFT Magnitude')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.colorbar(label='Magnitude')
plt.show()
以下是使用函数 scipy.signal.stft() 调整重叠的 STFT 输出 −
STFT 的应用
以下是 SciPy Short Time Fourier Transform 的应用 −
- Speech and Audio Processing: 分析语音信号的时变频率内容。
- Music Analysis: 识别音乐中的谐波分量和节拍。
- Biomedical Signals: 分析非平稳信号,如 EEG 或 ECG。
- Vibration Analysis: 检测旋转机械中的故障。
- Communications: 解调时变频率信号。