关于涉及频谱分辨率的一些问题以及FFT幅度谱数值矫正问题的梳理

本文纯原创,有不对的地方敬请指正,有不懂的地方可以讨论,搬运请注明来源,谢谢。

一、问题

在研究matlab的FFT函数的时候发现了如下问题:对于信号
y = e j 2 π f 1 t + e j 2 π f 2 t + e j 2 π f 3 t y=e^{j2\pi f_1t}+e^{j2\pi f_2t}+e^{j2\pi f_3t} y=ej2πf1t+ej2πf2t+ej2πf3t
其中 f 1 = 500 H z f_1=500Hz f1=500Hz f 2 = 505 H z f_2=505Hz f2=505Hz f 2 = 1010 H z f_2=1010Hz f2=1010Hz。当我用 F s = 5120 H z F_s=5120Hz Fs=5120Hz的采样率对其进行采样得到512个离散数据点,画出其频谱为:
在这里插入图片描述

问题一:频谱本应该是在500Hz、505Hz和1010Hz三处有峰,但是频谱上却没有显示出505Hz的信号。
问题二:由时域表达式可知,三个不同频点的信号功率一致,都为1。但是幅度谱上却无体现。

二、频谱分辨率、栅栏效应及频谱泄露

在简介栅栏效应之前,我们要分清DTFT、DFT和FFT三者的关系,可以参考我的这篇文章

在这里插入图片描述

我们不妨细看DFT这个步骤,我们在matlab里调用FFT函数就是采用的DFT算法(当FFT点数是2的整数次幂的时候,就可以用快速傅里叶变换)。

2.1频谱分辨率

由上图可知,我们最终得到的时域信号是以采样周期 T = 1 F s T=\frac{1}{Fs} T=Fs1为间隔,频谱中的谱线以 2 π N \frac{2\pi}{N} N2π间隔,转换到数字上则有: Δ f = F s N \Delta f=\frac{Fs}{N} Δf=NFs,在本例中频谱分辨率则是 Δ f = 5120 512 = 10 H z \Delta f=\frac{5120}{512}=10Hz Δf=5125120=10Hz

2.2栅栏效应

我们可以想象,间隔10Hz的谱线,应该是会跳过我们的505Hz这个频点的信号。就好像通过栅栏观察频谱一样,因此叫做栅栏效应。

那么难道我们就观察不到这个频点的信号了吗?如果我们漏掉了505Hz这个频点的信号,那我们500Hz和1010Hz两个频点的信号功率不应该是一致的吗,怎么会幅度不一样呢?

2.3频谱泄露

由上图可知,DFT的最后一个步骤是加窗,将一个无限长的信号截断为有限长的信号。在频域上,就是卷积一个Sa函数。
在这里插入图片描述

Sa函数的特性是能量集中在主瓣,少部分能量分布在旁瓣。这样原本各个频点的冲激信号经过卷积变为了Sa函数,能量也从集中分布在某个频点变为大部分集中,小部分泄露的情况。这就是我们说的频谱泄露。

回归到这个例子中,505Hz频点处的信号能量理应集中分布在505Hz附近的主瓣中,少部分泄露到其他地方去了。

可是505Hz谱线最后由于频谱分辨率的原因并没有被采集到,而500Hz的谱线不仅集中了500Hz信号的能量,还因为离505Hz太近,包含在其主瓣内,分到了505Hz频点信号的能量,因此幅度变得特别大。而1010Hz离得很远,只分到了一点点的能量,所以它的幅度也不是整数。(具体该是多少我们下一章节讨论)

由此可见,如果需要缓解频谱泄露的问题,如何选择一个好的窗函数是很重要的。

2.4如何提高频谱分辨率

如要提高频谱分辨率,还是从公式考虑
Δ f = F s N \Delta f=\frac{Fs}{N} Δf=NFs
要缩小 Δ f \Delta f Δf,采样率 F s Fs Fs一般是不做改动,而是增大 N N N。通常大家会提到**“补零”、“重复数据”和“增加采样点”**三种方法,我们一一讨论

2.4.1补零是否可以提高分辨率?

频谱分辨率公式里的 N N N究竟是什么呢?是采样点个数还是FFT点数?首先要分辨频谱密度频谱分辨率两个不同的概念,经常有人对此混淆不清。
频谱密度= F s N f f t \frac{Fs}{N_{fft}} NfftFs N f f t N_{fft} Nfft是FFT点数。
频谱分辨率= F s m i n { N , N f f t } \frac{Fs}{min\{N,N_{fft}\}} min{N,Nfft}Fs N N N是采样点个数。
我们讨论以下三种情况:

采样点个数=FFT点数

易知,当采样点个数与FFT点数相同时,频谱密度=频谱分辨率= F s N f f t \frac{Fs}{N_{fft}} NfftFs= F s N \frac{Fs}{N} NFs

采样点个数>FFT点数

当采样的数据点过多时候,如果做大点数的FFT变换,运算量会很大。一般会选择1024点,16384点这样的点数进行快速傅里叶变换以提高计算效率。
此时频谱密度=频谱分辨率= F s N f f t \frac{Fs}{N_{fft}} NfftFs。但是增加FFT点数可以继续增大频谱分辨率,直到 F s N \frac{Fs}{N} NFs为止,这也可以说是频谱分辨率的上限。

采样点个数< FFT点数

这就是我们常说的补0的情况。在这个例子中,我们用 F s = 5120 H z F_s=5120Hz Fs=5120Hz的采样率对其进行采样得到512个离散数据点,结果没有分出500Hz和505Hz两个频点的信号。那我们在512个数据点后面补512个0,然后做1024点的FFT,这样频谱分辨率会不会变成5Hz,就可以区分出两个相邻频点的信号呢?
在这里插入图片描述

由上图可知,我们仍然无法区分出500Hz和505Hz两个相邻频点的信号,但是我们的谱线明显更平滑了。

其实,从数学的角度出发,我们可以知道,时域补0对应的是频域插值,插值只会让谱线更平滑,而不会引入新的频率分量。从公式的角度出发,增大了FFT的点数,频谱密度增大了,而频谱分辨率没有提升,因此还是无法区分相邻频点。

如果了解DFT和DTFT的关系就更容易理解, 补零越多,就是在DTFT连续的频谱上采样得到更密集的谱线而已。看我上面那个链接,再结合这篇文章可以很透彻的理解

但是补0也不是毫无作用的,此时看频谱的栅栏更密集了,更容易进行观察和分析。通常我们认为补0是无害的,可以适当补0以完成快速傅里叶变换。例如把500个点补到512个点进行FFT。

(题外话,时域插值是否可行)

既然时域补零对应频域插值,那时域插值对应的就是频域的补0,自然也无法引入新的频域分量。这是上采样的工作原理,有兴趣的可以看我这篇文章

2.4.2重复数据是否可以提高频谱分辨率

首先声明,本文不讨论周期信号进行整周期采样的情况。
一般来说我们采样得到的信号都是非周期的,不管是对无限长非周期信号的采样,还是对周期信号的截断采样。
回到我们的例子,我们我们用 F s = 5120 H z F_s=5120Hz Fs=5120Hz的采样率对其进行采样得到512个离散数据点,然后把它重复一遍,拼凑得到1024个数据点进行FFT

可以看出,确实多了一个频率分量,区分出来两个相邻频点的信号了。这是因为重复一遍信号,相当于增加了实际有用信息的采样点个数,因此不仅可以缓解频谱泄露的问题,还可以增大频谱分辨率。此时的频谱分辨率 Δ f = 5120 1024 = 5 H z \Delta f=\frac{5120}{1024}=5Hz Δf=10245120=5Hz

不过这种方法也有缺点,它伪造了一个与实际信号可能并不相符的新的信号出来,这样得到的频谱与我们实际信号的频谱有所区别。只有当我们无法获取更多采样点的时候才考虑这种方法。

2.4.3增加采样点是否可以提高频谱分辨率

先说结论,这是唯一正确的方法。增加采样点个数相当于加窗的时候加了一个更长的窗,不仅有效缓解了频谱泄露的问题,也大大提升了频谱分辨率。只是很多时候受限于存储条件和计算性能的限制,我们无法采样得到足够多的数据点进行FFT变换。
在这里插入图片描述
回到我们的例子,我们我们用 F s = 5120 H z F_s=5120Hz Fs=5120Hz的采样率对其进行采样得到1024个离散数据点进行FFT,此时的频谱分辨率 Δ f = 5120 1024 = 5 H z \Delta f=\frac{5120}{1024}=5Hz Δf=10245120=5Hz。恰好可以分辨出500Hz和505Hz两个相邻频点信号。

而且此时频谱泄露的问题得到了有效缓解,各个频点的信号的功率没有泄漏到其他频点,所有频点信号的功率一致,幅度谱上都显示1024。

由此我们解决了问题一,那么问题二究竟是怎么回事呢?

三、FFT幅度谱数值矫正问题

我们重新来看我们的信号
y = e j 2 π f 1 t + e j 2 π f 2 t + e j 2 π f 3 t y=e^{j2\pi f_1t}+e^{j2\pi f_2t}+e^{j2\pi f_3t} y=ej2πf1t+ej2πf2t+ej2πf3t
这是由三个平均功率为1的复单音信号合并而成的一个混合信号。
我们对其采样1024点做1024点FFT,以及采样2048点做2048点FFT得到两个频谱。
在这里插入图片描述
我们看幅度,做1024点FFT的三根谱线的幅度都是1024,而做2048点FFT的三根谱线的幅度是2048。由帕萨瓦尔定理我们可知

信号在时域的总能量等于信号在频域的总能量,即信号经傅里叶变换后其总能量保持不变,符合能量守恒定律。

明明他们都是平均功率为1的信号啊,怎么会这样呢?我们还是要从FFT底层入手。

要知道,非周期信号FFT算的是傅里叶变换,周期信号FFT算的是傅里叶级数(因为周期信号傅里叶变换是 δ \delta δ冲激函数,没有意义)
在这里插入图片描述
回到我最开始引用的那篇文章里的这个图,由于非周期无限长的信号没有办法求得离散频谱,因此我们是对其做一个周期延拓得到周期信号,然后求得离散频谱。

对一个周期延拓的信号,求的是其傅里叶级数。而我们本来要求的是非周期信号的傅里叶变换。那么DFS和DFT求得东西是一样的吗?

我们看公式:

离散周期傅里叶级数DFS
x [ n ] = ∑ k = 0 N − 1 a k e j k ( 2 π / N ) n x[n]=\sum\limits_{k=0}^{N-1}a_k e^{jk(2\pi/N)n} x[n]=k=0N1akejk(2π/N)n
a k = 1 N ∑ n = 0 N − 1 x [ n ] e − j k ( 2 π / N ) n a_k = \frac{1}{N} \sum\limits_{n=0}^{N-1} x[n]e^{-jk(2\pi/N)n} ak=N1n=0N1x[n]ejk(2π/N)n
离散傅里叶变换DFT
x [ n ] = 1 N ∑ k = 0 N − 1 X [ k ] e j k ( 2 π / N ) k n x[n]=\frac{1}{N}\sum\limits_{k=0}^{N-1}X[k] e^{jk(2\pi/N)kn} x[n]=N1k=0N1X[k]ejk(2π/N)kn
X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j k ( 2 π / N ) k n X[k] = \sum\limits_{n=0}^{N-1} x[n]e^{-jk(2\pi/N)kn} X[k]=n=0N1x[n]ejk(2π/N)kn

仔细比较就可以发现,DFT算出来的X[k]的幅度是 a k a_k ak的N倍,Matlab中FFT使用的就是这个算法,所以实际的幅值大小要乘以1/N。

回到我们的例子,我们在1024点FFT频谱中得到的幅度是1024,乘以1/N得到1,所以各频点信号的平均功率为1,与时域功率一致,符合帕萨瓦尔定理

但是为什么有的文章说要乘以2/N那?这只是单边谱和双边谱的区别,DFT算出来的是双边谱,换算到单边谱幅度要加倍,注意直流不加倍,仅此而已。

在进行谱分析的过程中我们其实一般不会注意到幅度具体的值,只会关注该点有无信号以及信号强度相对大小,但是若能够了解其幅度变换关系,相信更有利于大家的分析!

  • 19
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
MATLAB中使用FFT频谱分析时频率分辨率问题-频率分辨率.rar MATLAB中使用FFT频谱分析时频率分辨率问题 最近做FFT时,使用的采样频率和信号长度的取舍一直没有搞清楚,后来在论坛上发了一个贴子《总结一下使用FFT和维纳-辛钦定理求解PSD问题》(讨论见https://www.ilovematlab.cn/thread-27150-1-1.html,特别感谢会员songzy41,他的问题给了我很大启示),跟帖中给了我不少启示,并且让我对“频率分辨率”这个概念有了更深入的理解。再次一并感谢论坛的高手们。 频率分辨率,顾名思义,就是将信号中两个靠的很近的频谱分开的能力。 信号x长度为Ts,通过傅氏变换后得到X,其频率分辨率为Δf=1/T(Hz),若经过采样后,假设采样频率为fs=1/Ts,而进行频谱分析时要将这个无穷长的序列使用窗函数截断处理,假设使用矩形窗,我们知道,矩形窗的频谱为sinc函数,主瓣宽度可以定义为2*pi/M,M为窗宽,那么,时域相乘相当于频域卷积,频域内,这一窗函数能够分辨出的最近频率肯定不可能小于2*pi/M了,也就是如果数据长度不能满足2*pi/M<|w2-w1|(w2,w1为两个靠的很近的频率),那么在频谱分析时,频谱上将不能分辨出这两个,由于w2-w1=2*pi/fs=2*pi*Δf/fs也就是2*pi/M<2*piΔf/fs,得到Δf的限制为fs/M,这就是窗函数宽度的最小选择,就是说,根据Shannon采样定理确定了采样频率后,要根据靠的最近的峰来确定最小的采样长度,这样,所作出来的频谱才能分辨出那两个峰,也就是拥有了相应的频率分辨率。 几个例子: 考虑双正弦信号:x = sin sin;根据Shannon采样定理,采样频率要大于截止频率的两倍,这里选采样频率为80,那么,我们可以看到,Δf为0.2Hz,那么,最小的数据长度为0.2/80=400,但是对正弦信号的频谱分析经验告诉我们,在截断时截断时的数据要包含整周期,并且后面不宜补零以避免频谱泄露(这一点见胡广书《数字信号处理导论》,清华大学出版社),那么,我们要选择至少980个点,才能保含到一个整周期,另外,FFT的经验告诉我们作分析时最好选择2的整数次幂,我们选择靠的最近的1024点。分析结束。 [CODE] Fs = 80; n = 0:1/Fs:1023*1/Fs; x = sin sin; N = length; figure; X = fftshift); plot*Fs/N,abs*2/N); grid on; axis; 这是按照我们的分析进行的编程和图形 zheng.jpg 可以看出这两个峰很好的被分辨开来,9.8Hz不在线上,所以幅值不为1,以下是一些对比: [CODE] Fs = 80; n = 0:1/Fs:1023*1/Fs; x = sin sin; N = length; X = fftshift); figure; subplot plot*Fs/N,abs*2/N); grid on; axis; title; n = 0:1/Fs:979*1/Fs; x = sin sin; N = length; X = fftshift); subplot plot*Fs/N,abs*2/N); grid on; axis; title; n = 0:1/Fs:399*1/Fs; x = sin sin; N = length; X = fftshift); figure; subplot plot*Fs/N,abs*2/N); grid on; axis; title; Fs = 20; n = 0:1/Fs:1024*1/Fs; x = sin sin; N = length; X = fftshift); subplot plot*Fs/N,abs*2/N); grid on; axis; title; 结果如下: 1024.jpg 400.jpg 这是我在做FFT以及论坛中的问题时所得到的一点启发,不当之处还请大家指正。OO~ 频率分辨率.rar 为了方便大家,我将doc版报告和m文件一起上传,和帖子内容一样。OO~
### 回答1: 基于MATLAB的FFT频谱内频率和幅度校正算法可以采用如下步骤进行: 1. 导入原始信号并进行FFT变换,得到频谱。可以使用MATLAB中的fft函数来进行FFT变换操作。 2. 分析频谱图,查找频谱中的峰值点。可以使用MATLAB中的findpeaks函数来查找峰值点。 3. 对于每一个峰值点,计算其实际对应的频率值。频率值可以通过FFT变换结果中的索引值与采样率进行换算得到。 4. 对每一个峰值点进行幅度校正幅度校正可以通过将峰值点的幅度值乘以一个校正系数来实现。 5. 根据校正后的频率和幅度值,重新绘制频谱图。可以使用MATLAB中的plot函数来进行频谱图的绘制。 6. 如果需要,可以对频谱图进行进一步的处理,比如平滑或者滤波等。 7. 最后,保存校正后的频谱图或者数据,以便后续分析或应用。 总结起来,基于MATLAB的FFT频谱内频率和幅度校正算法主要包括FFT变换、查找峰值点、计算频率值、幅度校正和绘制频谱图等步骤。通过这些步骤,可以实现对频谱图中频率和幅度校正和调整。 ### 回答2: 基于Matlab的FFT频谱内频率和幅度校正算法可以通过以下步骤来实施: 1. 提取频谱数据:首先,将需要校正的信号采集并进行FFT变换,得到频谱数据。在Matlab中,可以使用fft函数来实现此操作。 2. 去除直流分量:由于信号的直流分量通常对频谱分析没有实际用处,因此我们可以将频谱中的直流分量去除。这可以通过将频谱的第一个元素设置为零来实现。 3. 求取频率向量:根据采样率和信号长度,计算频率向量,用于表示频谱的X轴信息。可以使用linspace函数在频率范围内创建等间距的数据点。 4. 幅度校正:根据实际需求,进行幅度校正操作。例如,如果需要将整个频谱幅度放大或缩小,可以使用乘法因子来调整频谱幅度。 5. 频率校正:如果信号中的频率发生了偏移或失真,可以通过对频率向量进行线性插值的方式来进行频率校正。首先,根据实际频率与理论频率之间的差值,计算出频率校正因子。然后,使用interp1函数对频率向量进行插值,根据频率校正因子进行线性插值。 6. 绘制校正后的频谱图:最后,使用plot函数将校正后的频率向量和幅度数据绘制成频谱图,以便于观察校正的效果。 通过以上步骤,我们可以实现基于Matlab的FFT频谱内频率和幅度校正算法。校正后的频谱图将更准确地反映出原始信号的频率和幅度信息,以满足实际需求。 ### 回答3: 基于MATLAB的FFT频谱内频率和幅度校正算法主要有两个步骤:频率校正幅度校正。 频率校正是为了解决FFT频谱中出现的频率偏移问题。该问题可能由采样率不准确、信号中存在相位偏移或本地振荡器频率不稳定等原因引起。为了解决这个问题,我们可以通过以下步骤进行频率校正: 1. 选择一个已知频率的标准信号(例如一个正弦信号)作为参考。 2. 对标准信号进行FFT处理,获取其频谱。 3. 在待校正信号上进行FFT处理,得到其频谱。 4. 对比待校正信号和标准信号的频谱,计算两者之间的相位差。 5. 对待校正信号的相位进行调整,以校正频率偏移。 幅度校正是为了解决FFT频谱中出现的幅度失真问题幅度失真可能由采样信号动态范围不准确或测量系统非线性等因素引起。为了解决这个问题,可以采取以下步骤进行幅度校正: 1. 选择一个已知幅度的标准信号作为参考。 2. 通过放大或缩小待校正信号的幅度,使其与标准信号的幅度相匹配。 3. 对校正后的信号进行FFT处理,得到频谱。 4. 记录校正倍数,以便将来对其他信号进行同样的幅度校正。 需要注意的是,频率校正幅度校正仅针对特定的频率范围和采样条件进行有效,并且需要参考信号的准确性和稳定性。校正算法的准确性和精度取决于所选择的参考信号和校正方法的合理性。因此,在实际应用中,需要根据具体情况选择适当的方法和参考信号,以获得准确和可靠的校正结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值