短时傅里叶变换(STFT)及matlab

笔记~自用版~

短时傅里叶变换的基础理论

        短时傅里叶变换(Short-Time Fourier Transform, STFT)是一种时频分析方法,它将信号在时间域上分成若干个短时段,对每个短时段进行窗函数加窗后再做傅里叶变换,得到每个时刻的频率成分。与离散傅里叶变换(Discrete Fourier Transform, DFT)和连续傅里叶变换(Continuous Fourier Transform, CFT)相比,STFT具有时间和频率分辨率都高的优点。

        在STFT中,使用一个滑动窗口(也称为时间窗口、分析窗口),将输入信号分成若干个短时段。对于每个短时段,都可计算出它的傅里叶变换。由于窗函数的存在,每个短时段的傅里叶变换只能反映该短时段内的频率信息。这个过程的结果是,在时间轴上得到了一系列变换后的频谱图

        例如,假设对一段音频信号进行时频分析。首先将该信号分成若干个长度为W的短时段,假设窗函数为h(n),那么第k个短时段的STFT可以表示为:

其中,x(n)为原始信号,n为时域采样点,k表示第k个短时段,ω表示频率。这个公式的意思是:对第k个短时段的信号进行窗函数加窗后,再做傅里叶变换,得到该短时段的频率成分

       将所有的短时段的STFT组合起来,就可以得到整个信号的时频图谱。其中,横轴表示时间轴,纵轴表示频率轴,颜色表示该时刻该频率成分的幅度大小

       STFT一个很明显的缺点——窗函数长度不能太短,否则无法准确反映频率信息,也不能太长,否则时域分辨率将下降。这个问题可以通过使用一些基于STFT的变种方法来解决,例如连续小波变换(Continuous Wavelet Transform, CWT)和可变长窗口的短时傅里叶变换(Variable-Length Window STFT, VSTFT)等.......后续讨论

Matlab使用与演示

STFT(短时傅里叶变换)是一种时频分析方法,可以将信号在时间域和频率域上进行矩阵表示。具体来说,STFT 将整段信号分成若干小段,并对每个小段信号在时域上进行窗函数和 DFT 处理,最后得到了信号在时间和频率两个维度上的矩阵表达。

Matlab 中计算 STFT 变换的函数是 spectrogram,语法如下:

[S,F,T,P] = spectrogram(x, window, noverlap, nfft, fs);

其中,'x'表示输入信号,'window'表示窗函数的长度(以采样点为单位),'noverlap'表示相邻两个窗口之间的重叠长度(以采样点为单位,默认为 'window*0.5'),'nfft' 表示进行 DFT 变换时采用的点数(必须是2的幂次方,默认为256),'fs' 表示采样率。函数返回值包括:

- 'S':STFT 谱矩阵,行数为 'nfft/2+1',列数为 STFT 小段数。
- 'F':频率向量,单位为 Hz,长度为 'nfft/2+1'。
- 'T':时间向量,单位为秒,长度为 STFT 小段数。
- 'P':功率谱矩阵,与 STFT 谱矩阵 'S' 相同。

现在,我们来看一下示例代码的具体实现过程:

% 生成一个包含两个正弦波的信号
Fs = 1000; % 采样率
t = 0:1/Fs:1; % 时间序列
x = sin(2*pi*50*t) + sin(2*pi*120*t);

% STFT 参数设置
winlen = 0.5; % 每个小段的长度
overlap = 0.25; % 相邻小段的重叠长度
nfft = 1024; % DFT 点数

% 计算 STFT
[S,F,T,P] = spectrogram(x, round(winlen*Fs), round((1-overlap)*winlen*Fs), nfft, Fs);

step1: 首先,生成一个包含两个正弦波的信号 'x',采样率为 1000 Hz,时长为 1 秒。

step2: 然后,设置了 STFT 的参数。其中,'winlen'表示每个小段的长度为 0.5 秒,'overlap' 表示相邻两个小段之间重叠 0.25 秒,即两个小段之间有 0.25 秒的重复数据。'nfft' 表示进行 DFT 变换时采用 1024 个点进行傅里叶变换。

step3: 最后,调用'spectrogram'函数,计算 'x' 的 STFT 变换。实际上,该函数还会返回功率谱矩阵 'P',但在这里未加以使用。函数返回的 'S'、'F' 和 'T' 分别表示 STFT 谱矩阵、频率向量和时间向量。

在本例中,将 STFT 谱矩阵(即 'S')传递给 'imagesc'函数,以可视化 STFT 的频谱图。如下:

% 绘制 STFT 频谱图
imagesc(T, F, 20*log10(abs(S)));
axis xy;
xlabel('Time (s)');
ylabel('Frequency (Hz)');
title('STFT Spectrogram');
colorbar;

        使用 'imagesc' 函数将 STFT 显示为频谱图,其中输入参数 'T' 和 'F' 分别是时间向量频率向量,输入参数 'abs(S)' 表示 STFT 谱矩阵的模值(因为模值更能体现信号在不同频率下的强度)。同时使用 '20*log10' 函数对 STFT 谱矩阵取对数,并乘以 20,目的是将 STFT 谱矩阵从线性单位(即幅度)转换为对数单位(即分贝),以增强其可视化效果。最后,使用 'axis xy' 让横轴表示时间,纵轴表示频率,通过 'colorbar' 添加颜色条,最后用 'xlabel'、'ylabel' 和 'title' 函数添加轴标签和标题。得到图像:

 也可以选择对S做归一化处理。如下:

S = abs(S)/ max(abs(S(:)));
imagesc(T, F, S);
axis xy;
xlabel('Time (s)');
ylabel('Frequency (Hz)');
title('STFT Spectrogram');
colorbar;

得到图像:

可以非常清晰的看到结果~  

猜你喜欢

转载自blog.csdn.net/weixin_43681559/article/details/130338137