小波变换:多分辨率的时频分析
STFT 用一个固定窗走天下,小波则带了一整套"变焦镜头": 看低频用长镜头、看高频用短镜头,每个频率都获得最合适的观察尺度。
🎯 本节学习目标
- 说清 STFT 固定窗的两难,以及小波如何用"变焦"化解
- 理解 Morlet 小波的构成:高斯包络 × 正弦振荡
- 掌握尺度 scale 与频率的换算关系
- 会用 Matlab 的
cwt,也能手写 fft 版小波卷积 - 能依据研究问题在 STFT 与小波之间做出选择并说明理由
一、STFT 的两难,与"变焦镜头"的解法
4.3 的结论:STFT 的窗长一旦选定,所有频率共用同一观察尺度—— 低频嫌窗短(糊)、高频嫌窗长(钝)。你被迫在一张图里做全局妥协。
想象用照相机拍风景:拍远山(低频慢节律)用长焦慢慢拍, 拍飞鸟(高频快事件)用广角抓瞬间。小波变换就是给时频分析装上变焦镜头: 对每个频率自动调整窗长——低频配长窗、高频配短窗——让每个频段都拿到 "恰好够用"的周期数。
STFT:所有频率共享一个固定窗(统一分辨率)。小波:每个频率配自己的窗(恒定相对分辨率)。小波牺牲了"所有频率时间分辨率一致"的直观,换来"每个频段都接近最优"。
二、Morlet 小波长什么样
连续小波变换(CWT)用的"镜头"是一组伸缩的母小波。 EEG 领域的母小波几乎清一色是 Morlet 小波(更准确说 Gaussian-windowed complex sinusoid),因为它频率意义明确:
% 亲手画一个 10Hz 的 Morlet 小波
fs = 500; f0 = 10; n_cyc = 6;
sigma_t = n_cyc / (2*pi*f0); % 高斯包络的标准差由周期数决定
t = -1 : 1/fs : 1;
w = exp(2i*pi*f0*t) .* exp(-t.^2/(2*sigma_t^2));
figure;
subplot(2,1,1); plot(t, real(w), 'b', t, abs(w), 'r--');
legend('实部(振荡)','包络'); title('Morlet 小波 = 高斯包络 × 正弦');
xlim([-0.4 0.4]);
subplot(2,1,2); plot(t, abs(w), 'r'); title('包络:决定有效窗长');
xlim([-0.4 0.4]);
两个组成部分各司其职:正弦振荡负责"探听"目标频率; 高斯包络负责把聆听限制在一小段时间内——包络的宽度就是窗长。 关键设计:周期数 n_cyc 固定。于是频率越低、周期越长,窗自然越长; 频率越高、窗越短——变焦自动完成。
包络内包含的目标频率周期个数。常用 3-4(高时间分辨率,适合诱发瞬态)到 7-10(高频率分辨率,适合节律分析)。频率分辨与时间分辨的权衡在这里转动旋钮。
三、卷积视角:小波变换在算什么
对每个频率 f,把对应的小波沿时间轴平移,与信号逐位置做卷积: 每个时刻得到一个复数——模是"该时刻该频率的包络功率",辐角是"该时刻该频率的相位"。 一组频率扫完,就得到与 STFT 同构的时频矩阵。
为什么卷积能完成这件事?直觉:小波像一把"钥匙",信号某处若存在与钥匙同频的振荡, 卷积(逐点相乘求和)就会产生大的共振响应;错频的成分正负抵消,响应趋零。 共振即检测。
四、尺度与频率的换算
小波文献常用"尺度 scale"而不是频率:尺度越大,小波被拉得越长,对应频率越低。 对 Morlet 小波,二者近似成反比:
% Morlet:频率 ≈ 中心频率 / 尺度(以母小波中心频率 f_c 归一)
% Matlab cwt 默认 Morse 小波时可用scal2freq换算:
% fb = 3, Morse 近似 Morlet(n_cyc 大致对应)
f_c = 1; % 母小波中心频率(示例)
scales = [0.05 0.1 0.25 0.5 1 2 4 8];
freqs = f_c ./ scales; % 频率 = 中心频率 / 尺度
disp(table(scales', freqs', 'VariableNames', {'scale','freq_Hz'}));
% 直觉:尺度是"拉长倍数"。拉长 2 倍 → 周期变 2 倍 → 频率减半
五、Matlab 实现 A:内置 cwt
% x : 一维信号;fs : 采样率
fs = 500;
[cfs, frq] = cwt(x, 'morse3', fs); % Morse(3) 近似经典 Morlet
figure;
surface(seconds(0:1/fs:(numel(x)-1)/fs), frq, abs(cfs));
axis xy; ylim([2 45]);
xlabel('时间 (s)'); ylabel('频率 (Hz)');
title('连续小波变换幅度谱');
colormap(parula); colorbar;
% 也可以直接用便捷绘图接口:
% cwt(x, fs) 自动配色与频率轴
六、Matlab 实现 B:手写 Morlet 卷积(fft 加速)
论文与教学场景常需要完全可控的手写版本(自定义 n_cyc、直接输出功率与相位)。 核心技巧:时域卷积 ↔ 频域相乘,把每个小波的卷积变成一次 FFT 乘法:
function [P, phase, f, t] = morletTFR(x, fs, fList, n_cyc)
% x: 1 x N 信号;fList: 频率列表(如 2:1:45);n_cyc: 周期数
x = x(:).'; N = numel(x);
t = (0:N-1) / fs;
nF = numel(fList); P = zeros(nF, N); phase = P;
X = fft(x); % 信号只变换一次
for k = 1:nF
f0 = fList(k);
s_t = n_cyc / (2*pi*f0); % 该频率下的包络宽度
tw = -3*s_t : 1/fs : 3*s_t; % 覆盖 ±3σ
w = exp(2i*pi*f0*tw) .* exp(-tw.^2/(2*s_t^2));
w = w / sqrt(s_t); % 能量归一化
W = fft(w, N); % 小波补零到信号长度
convr = ifft( X .* W ); % 频域相乘 = 时域卷积
convr = [convr(end-floor(numel(w)/2)+1:end), convr(1:end-floor(numel(w)/2))];
P(k,:) = abs(convr).^2; % 瞬时功率
phase(k,:) = angle(convr); % 瞬时相位(8.7 ITPC 会用到)
end
end
% 用法示例:
% [P, ph, f, t] = morletTFR(eeg_chan, 500, 2:1:45, 6);
% imagesc(t, f, 10*log10(P)); axis xy;
① n_cyc 可按频段定制(低频用大周期数、高频用小周期数),比统一窗长的 STFT 更贴合数据;② 同时输出相位,模块 6 的连接分析和 8.7 的 ITPC 都直接复用这套代码;③ 面试/组会时能讲清每一步。
七、小波 vs STFT:怎么选
| 维度 | STFT | 小波(Morlet) |
|---|---|---|
| 分辨率形态 | 全频率统一(固定窗) | 按频率自适应(低频细频率、高频细时间) |
| 参数直观性 | 窗长/重叠,直观 | n_cyc、频率列表,需理解权衡 |
| 计算量 | 低 | 略高(逐频率卷积) |
| 典型场景 | 短时程事件、γ 频段、需要时间轴均匀 | 跨宽频段的节律分析、同时关心 δ 与 γ |
| 相位输出 | 有(复数 STFT) | 有,且局部化更自然 |
选择建议一句话:只在单一窄频段内看事件动态 → STFT;跨宽频段、或后续要做相位类分析(ITPC/连接)→ 小波。EEG 论文里 Morlet 小波更常见,FieldTrip 的 mtmconvol 本质也是"可调窗长的滑动窗多锥变换",与小波思想同源。
八、本模块收官:频域分析的全景图
4.1 学会把信号拆成频率成分(PSD,无时间轴);4.2-4.3 学会给频谱装时间轴(STFT,统一分辨率)并处理加窗与基线;4.4 学会让每个频率各得其所(小波,自适应分辨率)。下一模块的 FieldTrip 会把这三层能力整合成工业级流水线,并为它们配上统一的统计检验。
📌 本节小结
- 小波 = 一组伸缩的 Morlet(高斯包络×正弦),实现"低频长窗、高频短窗"的变焦
- n_cyc 是旋钮:小值偏时间分辨率(诱发瞬态),大值偏频率分辨率(节律)
- 尺度与频率近似成反比:频率 = 母小波中心频率 / 尺度
- 手写 fft 版小波卷积同时输出功率与相位,后续模块直接复用
- 选型口诀:单一窄频段看事件用 STFT;跨宽频段或要做相位分析用小波
✏️ 课后练习
- 用
morletTFR对 4.2 的"10Hz→25Hz 跳变"仿真信号出图,对比spectrogram版本中 10Hz 与 25Hz 能量带的时间锐利度。 - 固定频率 10Hz,分别取 n_cyc = 3 与 9 重算 TFR,观察 10Hz 能量带在时间轴和频率轴上的"胖瘦"变化,用不确定性原理解释。
- 对一段真实静息数据分别做 PSD(pwelch)与 Morlet 时频图,在时频图上找到 α 个体峰频率,与 PSD 峰值对照是否一致。