一、为什么要进行分窗?
1. 分窗的作用
信号进行 FFT 变换容易因为非周期截断造成频谱泄露,加窗可以更好地满足 FFT 处理的周期性要求,减少频谱泄露。频谱泄露详解见:【20211228】【信号处理】从 Matlab 仿真角度理解频谱泄露
(参考:数字信号预处理--加窗的重要性)
(参考:为什么要对信号加窗)
(参考:窗函数作用和性质)
2. 分窗使用范围
分窗只适用于关注的频率在各时间点上分布均匀的信号。比如:在信号的前半段信号频率为 f1,在信号的后半段信号频率为 f2,这种信号是不适合用分窗算法来进行分析的!
3. 分窗的本质
加窗本质相当于滤波器,通带内的系统函数不一定是常数值,加窗在时域进行,在时域信号点乘窗函数等价于频域信号频谱卷积窗函数频谱。
(参考:为什么要对信号加窗、几种常见窗函数的特性)
(参考:加窗原理和频谱泄露 深入理解)
(参考:“时域加窗”和“频域加窗”的区别,如何选择一个合适的“窗”?)
二、窗函数的选择
1. 窗函数选取的原则
加窗是用来减少频谱泄露的,减少频谱泄漏的方式是:尽量使频谱的能量主要集中在主瓣,尽量使旁瓣的能量低,也就是尽量提高峰值旁瓣比。
窗函数选取原则:(1)窗函数频谱主瓣尽量窄,以提高频率分辨率;(2)旁瓣衰减和旁瓣衰减速率应尽量大,以减少频谱拖尾;
通常情况下,窗函数的选择是上述两个条件的折衷。如果信号存在强干扰频率分量,且和感兴趣的分量相距较远,那么应该选择高旁瓣衰减速率的平滑窗(减少频谱泄露);如果信号存在强干扰频率,且和感兴趣分量相距较近,那么应该选择具有低最大旁瓣高度的窗(减少频谱泄露);如果感兴趣频率包含两种或多种频率距离很近的信号,那么应该选择主瓣宽度窄的平滑窗(提高频率分辨率)。
(参考:FFT频谱泄露和加窗 (二))
2. 几种常见窗函数
常见窗函数的有:矩形窗、切比雪夫窗、汉明窗、海宁窗、三角窗、高斯窗、凯泽窗、布莱克曼窗、平顶窗等。
窗函数的差别在于:主瓣宽度(也称有效噪声带宽)、幅度失真度、最高旁瓣高度、旁瓣衰减速率等参数。主瓣宽度主要影响信号能量分布和频率分辨能力,主瓣越宽,频率分辨率越低;旁瓣高低和旁瓣衰减速率影响能量泄露程度(频谱拖尾效应),旁瓣越高说明能量泄露越严重;衰减速率越慢说明频谱拖尾越严重。
几种窗函数特性比较:
一般情况下,海宁窗(hanning)适用于 95% 的情况,它不仅具有较高的频率分辨率,还可以减少频谱泄露。
(参考:几种常见窗函数的特性)
(参考:什么是窗函数?)
三、仿真对比
%% 窗函数
clear; clc; close all; warning off;
%% 生成信号
fs = 1000; % 采样频率
L = 10;
t = 0 : 1/fs : L;
N = length(t);
f = 10; % 信号频率
s = 10 * sin(2 * pi * f * t); % 原始信号
%% 信号加窗
w1 = chebwin(N)'; % 切比雪夫窗
w2 = hamming(N)'; % 汉明窗
w3 = hanning(N)'; % 海宁窗
w4 = triang(N)'; % 三角窗
w5 = gausswin(N)'; % 高斯窗
sw1 = s .* w1;
sw2 = s .* w2;
sw3 = s .* w3;
sw4 = s .* w4;
sw5 = s .* w5;
%% FFT变换
numfft = 128;
sfft = pow2db(abs(fft(s, numfft)));
sw1fft = pow2db(abs(fft(sw1, numfft)));
sw2fft = pow2db(abs(fft(sw2, numfft)));
sw3fft = pow2db(abs(fft(sw3, numfft)));
sw4fft = pow2db(abs(fft(sw4, numfft)));
sw5fft = pow2db(abs(fft(sw5, numfft)));
sfft_pos = sfft(1:numfft/2);
sw1fft_pos = sw1fft(1:numfft/2);
sw2fft_pos = sw2fft(1:numfft/2);
sw3fft_pos = sw3fft(1:numfft/2);
sw4fft_pos = sw4fft(1:numfft/2);
sw5fft_pos = sw5fft(1:numfft/2);
ff_pos = (0 : numfft/2-1) / numfft * fs;
%% 作图
figure(1);
subplot(2, 3, 1);
plot(s, 'linewidth', 1.5); title('原始信号波形(矩形窗)'); axis('tight');
subplot(2, 3, 2);
plot(w1, 'linewidth', 1.5); title('切比雪夫窗'); axis('tight');
subplot(2, 3, 3);
plot(w2, 'linewidth', 1.5); title('汉明窗'); axis('tight');
subplot(2, 3, 4);
plot(w3, 'linewidth', 1.5); title('海宁窗'); axis('tight');
subplot(2, 3, 5);
plot(w4, 'linewidth', 1.5); title('三角窗'); axis('tight');
subplot(2, 3, 6);
plot(w5, 'linewidth', 1.5); title('高斯窗'); axis('tight');
title('窗函数'); axis('tight');
figure(2);
sp21 = subplot(5, 1, 1);
plot(sw1, 'linewidth', 1.5); title('切比雪夫窗信号波形'); axis('tight');
sp22 = subplot(5, 1, 2);
plot(sw2, 'linewidth', 1.5); title('汉明窗信号波形'); axis('tight');
sp23 = subplot(5, 1, 3);
plot(sw3, 'linewidth', 1.5); title('海宁窗信号波形'); axis('tight');
sp24 = subplot(5, 1, 4);
plot(sw4, 'linewidth', 1.5); title('三角窗信号波形'); axis('tight');
sp25 = subplot(5, 1, 5);
plot(sw5, 'linewidth', 1.5); title('高斯窗信号波形'); axis('tight');
linkaxes([sp21, sp22, sp23, sp24, sp25], 'x');
figure(3);
subplot(2, 1, 1);
plot(w1, 'linewidth', 1.5); hold on;
plot(w2, 'linewidth', 1.5); hold on;
plot(w3, 'linewidth', 1.5); hold on;
plot(w4, 'linewidth', 1.5); hold on;
plot(w5, 'linewidth', 1.5); hold off;
legend('切比雪夫窗', '汉明窗', '海宁窗', '三角窗', '高斯窗');
title('窗函数'); axis('tight');
subplot(2, 1, 2);
plot(ff_pos, sfft_pos, 'linewidth', 1.5); hold on;
plot(ff_pos, sw1fft_pos, 'linewidth', 1.5); hold on;
plot(ff_pos, sw2fft_pos, 'linewidth', 1.5); hold on;
plot(ff_pos, sw3fft_pos, 'linewidth', 1.5); hold on;
plot(ff_pos, sw4fft_pos, 'linewidth', 1.5); hold on;
plot(ff_pos, sw5fft_pos, 'linewidth', 1.5); hold off;
legend('矩形窗信号FFT变换', '切比雪夫窗信号FFT变换', '汉明窗信号FFT变换', '海宁窗信号FFT变换', '三角窗信号FFT变换', '高斯窗信号FFT变换');
title('窗信号FFT变换'); axis('tight');
运行结果:
(参考:matlab中窗函数的使用(一))