频谱分析之加窗, 补0
某实验的实验数据 (复数) 理论来说是三个频率复振动的叠加 (当然更准确的情 况还有频率附近的分布, 噪音等. 下面忽略这些). 对数据做 fft 之后也能较好 的观察到 3 个峰, 峰的移动和大小随参数的变换和理论定性都符合挺好. 希望 能有一个办法从中较准确地定量提取出峰位置和峰值的信息, 然而由于数据长度 不足会遇到困难: 数据长度不足所以频谱上的分辨率不够高, 有时候对于获取峰 的频率分辨率是够了, 但是当需要知道峰值的时候, 假如峰正好落在频率取样 (\( 2\pi n /T \)) 中间的时候误差会非常大 (似乎叫做栅栏效应). 而拟合方 法对于周期数据的稳定性堪忧, 也没有找到很好通用的处理复数的方法, 傅里叶 级数拟合只能处理倍频并不好用. (这里看的人不多我就吐槽一下吧… 这个数 据处理学姐本来写的程序竟然是把实部和虚部交错排列到一个 MATLAB 数组中, 然后用内置的拟合工具暴力拟合… 程序写得简直不忍直视…)
感谢蔡大师的指点, 得知了一个频谱分析数据预处理的神器: 补0. 直接暴力在
数据结尾补 0 就能提高频谱分辨率. 当然因为峰变宽了实际上并不是真的提高
了频谱分析精度. 理论解释的话这相当于让时域数据变长了但是乘了一个方形调
制窗口, 相当于把单个峰变长了一个 sinc 函数. 由于时域变长了所以对应的频
谱分辨率也变好了. 当然由于 sinc 的主瓣宽度 (这个属于从蔡大师给我的 PPT
上直接抄来, 如果没理解错应该是指 sinc 这一枝的特征宽度, 类似的还有旁瓣
这个概念) 本来无法分辨的两个峰不会变得可以分辨. 频率分辨率高了之后前面
遇到的峰值问题自然就解决了. 实际操作上应该是 补0
- fft
- 归一化
.
值得注意的是 sinc 函数主瓣高度正好是方形窗口和总时间的比, 因而归一化时
恰好可以把 fft 前的数据长度, 也即补0后的长度改为补0前的长度, 就不会改
变峰值高度.
这样做有一个问题是, sinc 会引入旁瓣峰, 使得从频谱上找到所要的峰变麻烦
(似乎叫做频率泄露). 但是对于峰能很好的分离的数据, 在做一步加窗, 以主瓣
变宽为代价减小旁瓣即可. 实质是对于数据做了一个调制使得靠近边缘的数据变
小. 当然这也也会影响等比峰值大小, 需要进一步处理修正. MATLAB 中的窗函
数 (产生后直接和信号.*
再补0即可):
(1)矩形窗(Rectangle Window) 调用格式:w=boxcar(n),根据长度 n 产生一个矩形窗 w。
(2)三角窗(Triangular Window) 调用格式:w=triang(n),根据长度 n 产生一个三角窗 w。
(3)汉宁窗(Hanning Window) 调用格式:w=hanning(n),根据长度 n 产生一个汉宁窗 w。
(4)海明窗(Hamming Window) 调用格式:w=hamming(n),根据长度 n 产生一个海明窗 w。
(5)布拉克曼窗(Blackman Window) 调用格式:w=blackman(n),根据长度 n 产生一个布拉克曼窗 w。
(6)恺撒窗(Kaiser Window) 调用格式:w=kaiser(n,beta),根据长度 n 和影响窗函数旁瓣的 beta 参数产生一个恺撒窗w。