FFT变换中的两种分辨率(物理分辨率和计算分辨率)

设时域采样序列为 x [ n ] , 0 ≤ n < N x[n],0\leq n<N x[n],0n<N,则其FFT变换为
X [ k ] = ∑ n = 0 N − 1 x [ n ] e x p ( − j 2 π N k n ) , 0 ≤ n < N , 0 ≤ k < N X[k]=\sum_{n=0}^{N-1}x[n]exp(-j\frac{2\pi}{N}kn), 0\leq n<N, 0\leq k<N X[k]=n=0N1x[n]exp(jN2πkn),0n<N,0k<N
若采样率为 f s f_s fs,则FFT变换后的频率轴刻度为 [ − f s / 2 : f s / N : f s / 2 ] [-f_s/2:f_s/N:f_s/2] [fs/2:fs/N:fs/2]。从中得到两个信息:
(1)受奈奎斯特采样定律的限制,FFT变换最大只能表征 f s / 2 f_s / 2 fs/2频率的信号。当信号频率超过 f s / 2 f_s / 2 fs/2,则会发生频谱混叠。设信号真实频率为 f 0 f_0 f0,则混叠后的频率为 ± ∣ n f s − f 0 ∣ , n = r o u n d ( f 0 / f s ) \pm |nf_s - f_0|,n=round(f_0 / f_s) ±nfsf0n=round(f0/fs)
下图所示场景中, f s = 10000 H z , N = 2000 f_s=10000Hz,N=2000 fs=10000Hz,N=2000,包含两个正弦信号,频率分别为 1000 H z 1000Hz 1000Hz 6000 H z 6000Hz 6000Hz。FFT变换后, 6000 H z 6000Hz 6000Hz信号发生混叠,混叠后频率为4000Hz。
采样率10000Hz,两个单频信号分别为1000Hz和6000Hz, 样点数为2000

图1. 采样率10000Hz,两个单频信号频率分别为1000Hz和6000Hz

(2)频谱中相邻两点间的频率间隔为 Δ f = f s / N \Delta f=f_s/N Δf=fs/N,显然采样率 f s f_s fs越小,时域序列样点数 N N N越大, Δ f \Delta f Δf就越小。
基于上面的结论,我们很容易想到,若在原始采样序列 x [ n ] x[n] x[n]后面补上一串0,再进行FFT变换,那就通过增加时域样点数 N N N达到减小FFT频谱的频率分辨率 Δ f \Delta f Δf的目的。那是不是意味着,单纯的补零操作就可以让FFT变换具备分辨频率差异任意小的信号的能力?显然,这是违背直觉的,因为补零本质上并没有增加任何有用信息,自然无法提升FFT对信号的分辨能力。那补零操作的本质是什么?它与FFT对信号分辨能力的关系又是什么?
其实这边涉及到两个分辨率的概念:(1)是FFT变换频谱中相邻两点之间的频率间隔,通常称为计算分辨率。补零影响的就是计算分辨率,它与信号分辨能力无关;(2)是FFT对信号的分辨能力,通常称为物理分辨率,它只与时域采样序列的有效时长有关。下面对这两种分辨率进行详细说明。
1. 计算分辨率
从上面的分析可知,计算分辨率 Δ f = f s / N \Delta f=f_s/N Δf=fs/N,因此任何降低采样率或增加时域序列点数的操作都能提高计算分辨率。补零就是最常见的操作。下面推导补零前后信号频谱的关系。
设原始时域序列为 x [ n ] , 0 ≤ n < N x[n],0\leq n<N x[n],0n<N,它的FFT变换为
X [ k ] = ∑ n = 0 N − 1 x [ n ] e x p ( − j 2 π N k n ) , 0 ≤ n < N , 0 ≤ k < N X[k]=\sum_{n=0}^{N-1}x[n]exp(-j\frac{2\pi}{N}kn), 0\leq n<N, 0\leq k<N X[k]=n=0N1x[n]exp(jN2πkn),0n<N,0k<N
x [ n ] x[n] x[n]后面补0使序列总点数增加至 M M M,则补零后的序列为
x ′ [ n ] = { x [ n ] , 0 ≤ n < N 0 , N ≤ n < M x'[n]= \left\{\begin{matrix} x[n],0\leq n<N \\ 0,N\leq n<M \end{matrix}\right. x[n]={x[n],0n<N0,Nn<M
补零后序列的FFT变换为
X ′ [ k ] = ∑ n = 0 M − 1 x ′ [ n ] e x p ( − j 2 π M k n ) = ∑ n = 0 N − 1 x [ n ] e x p ( − j 2 π M k n ) = ∑ n = 0 N − 1 [ 1 N ∑ l = 0 N − 1 X [ l ] e x p ( j 2 π N l n ) ] e x p ( − j 2 π M k n ) = 1 N ∑ l = 0 N − 1 X [ l ] ∑ n = 0 N − 1 e x p ( − j 2 π M k n ) e x p ( j 2 π N l n ) = 1 N ∑ l = 0 N − 1 X [ l ] Θ ( k , l ) X'[k]=\sum_{n=0}^{M-1}x'[n]exp(-j\frac{2\pi}{M}kn)=\sum_{n=0}^{N-1}x[n]exp(-j\frac{2\pi}{M}kn)\\=\sum_{n=0}^{N-1}[\frac{1}{N}\sum_{l=0}^{N-1}X[l]exp(j\frac{2\pi}{N}ln)]exp(-j\frac{2\pi}{M}kn)\\=\frac{1}{N}\sum_{l=0}^{N-1}X[l]\sum_{n=0}^{N-1}exp(-j\frac{2\pi}{M}kn)exp(j\frac{2\pi}{N}ln)\\=\frac{1}{N}\sum_{l=0}^{N-1}X[l]\Theta(k,l) X[k]=n=0M1x[n]exp(jM2πkn)=n=0N1x[n]exp(jM2πkn)=n=0N1[N1l=0N1X[l]exp(jN2πln)]exp(jM2πkn)=N1l=0N1X[l]n=0N1exp(jM2πkn)exp(jN2πln)=N1l=0N1X[l]Θ(k,l)
其中
Θ ( k , l ) = ∑ n = 0 N − 1 e x p ( − j 2 π M k n ) e x p ( j 2 π N l n ) = ∑ n = 0 N − 1 e x p ( j 2 π ( l N − k M ) n ) = e x p ( j ( N − 1 ) π ( l N − k M ) ) s i n ( N π ( l N − k M ) ) s i n ( π ( l N − k M ) ) \Theta(k,l)=\sum_{n=0}^{N-1}exp(-j\frac{2\pi}{M}kn)exp(j\frac{2\pi}{N}ln)=\sum_{n=0}^{N-1}exp(j2\pi (\frac{l}{N}-\frac{k}{M})n)\\=exp(j(N-1)\pi(\frac{l}{N}-\frac{k}{M}))\frac{sin(N\pi(\frac{l}{N}-\frac{k}{M}))}{sin(\pi(\frac{l}{N}-\frac{k}{M}))} Θ(k,l)=n=0N1exp(jM2πkn)exp(jN2πln)=n=0N1exp(j2π(NlMk)n)=exp(j(N1)π(NlMk))sin(π(NlMk))sin(Nπ(NlMk))
l N − k M = 0 \frac{l}{N}-\frac{k}{M}=0 NlMk=0时, Θ ( k , l ) = N \Theta(k,l)=N Θ(k,l)=N,其他情况, Θ ( k , l ) \Theta(k,l) Θ(k,l)急剧减小,所以 X ′ [ k ] = 1 N ∑ l = 0 N − 1 X [ l ] Θ ( k , l ) ≈ X [ N M k ] X'[k]=\frac{1}{N}\sum_{l=0}^{N-1}X[l]\Theta(k,l)\approx X[\frac{N}{M}k] X[k]=N1l=0N1X[l]Θ(k,l)X[MNk]
基于上面的分析,可知补零后的频谱是原始频谱的插值。由于插值是基于已有信息进行操作的,所以若补零前的信号频谱不足以支撑两个信号的分辨,则补零后的频谱同样无法分辨这两个信号。
虽然补零并不能提高FFT对信号的分辨能力,但它具有以下用处:
a) 改变FFT变换的点数,提高FFT变换的计算效率。最常见的用法是将FFT变换的点数补零至 2 N 2^N 2N,此时可用蝶形算法保证FFT变换的效率;
b) 使信号频谱更加精细和平滑,降低栅栏效应;
c) 补零至特定点数凸显特定频率的信号。FFT变换只能表征频率为 f s / N f_s/N fs/N整数倍的信号,若原始信号频率不在这些频率点上则可通过补零使其落在FFT可表征的频率点上。
需要注意的是:补零仅仅增加了信号长度,但没有增加信号功率,相同功率平均到更多频点上,会使得频谱的功率谱密度降低。因此若用补零后的频谱来计算某一频率范围内的信号功率时,需要进行信号功率谱密度的补偿。

2. 物理分辨率

物理分辨率表征FFT变换对不同频率信号的分辨能力,它仅与有效信号时长有关。具体地,设信号时长为 T T T,则物理分辨率为 Δ f = 1 / T \Delta f=1/T Δf=1/T。信号时长可用采样点数和采样间隔的乘积得到,即 T = N / f s T=N/f_s T=N/fs,所以 Δ f = f s / N \Delta f=f_s / N Δf=fs/N。这个表达式与上述计算分辨率表达式的形式一致,差别在于物理分辨率表达式中 N N N表示有效信号的采样点数,不包括补零长度。
下面分别从时域和频率两个角度理解物理分辨率的表达式:
(1) 时域和频域本质上是从两种不同角度去看待一个信号,在这两个域上信号所包含的信息量是相等的。因此不论是从时域还是频域角度去理解信号的分辨能力都应得到相同的结论。下面以两个单频信号为例,从时域的角度理物理分辨率。设两个单频信号的频率分别为 f 0 f_0 f0 f 1 f_1 f1,对应的信号周期分别为 T 0 = 1 / f 0 , T 1 = 1 / f 1 T_0=1/f_0,T_1=1/f_1 T0=1/f0,T1=1/f1。显然,若两个信号的初始位置是对齐的,则经过 Δ T = 1 / ( ∣ f 0 − f 1 ∣ ) \Delta T=1/(|f_0-f_1|) ΔT=1/(f0f1)时间后,两个信号会重新对齐。如下图所示, f 0 = 10 H z , f 1 = 12 H z f_0=10Hz,f_1=12Hz f0=10Hz,f1=12Hz,经过0.5s后两个信号的重新回到初始状态。
图2

图2. 两个正弦信号时域波形

将上述两个信号进行叠加,我们的目标是从叠加后的信号中判断原始两个信号的频率差。根据上面的描述,我们知道叠加信号的周期为 Δ T = 1 / ( ∣ f 0 − f 1 ∣ ) \Delta T=1/(|f_0-f_1|) ΔT=1/(f0f1)。所以利用周期进行判断的思路显然是可行的,但是这种方法至少需要两个周期的信号长度。下图是图2中两个正弦信号的叠加波形,时长为一个周期 Δ T \Delta T ΔT。以 Δ T / 2 \Delta T /2 ΔT/2为界将信号分为两段,可见这两段信号是共轭对称的,可以利用这个性质计算 Δ T \Delta T ΔT,进而计算两个正弦信号的频差。此时只要求信号长度为 Δ T \Delta T ΔT即可。

在这里插入图片描述

图3. 图2中两个正弦信号的叠加

(2) 无限长单频信号的傅里叶变换为理想的冲激函数( δ \delta δ函数),其频谱仅在对应频率位置上非零。然而,我们实际处理的信号是有限长度的,等效于对无限长度的信号加了如下矩形窗
w [ t ] = { 1 , 0 ≤ t < T 0 , o t h e r s w[t]= \left\{\begin{matrix} 1,0\leq t<T \\ 0,others \end{matrix}\right. w[t]={1,0t<T0,others

上述矩形窗函数的频谱为
W ( f ) = ∫ 0 T e x p ( − j 2 π f t ) d t = T e x p ( − j π f T ) s i n c ( π f T ) W(f)=\int_0^T exp(-j2\pi ft)dt=T exp(-j\pi fT)sinc(\pi f T) W(f)=0Texp(j2πft)dt=Texp(fT)sinc(πfT)
显然, ∣ W ( f ) ∣ = T ∣ s i n c ( π f T ) ∣ |W(f)|=T|sinc(\pi f T)| W(f)=Tsinc(πfT),它的示意图如下,在 1 / T 1/T 1/T的整数倍上存在零点。时域加窗等效于频域卷积,所以正弦信号的频谱表现为以其频率为中心的sinc函数形态。当两个正弦信号的频谱主瓣不发生混叠时,可在频域进行区分。
在这里插入图片描述

图4. sinc函数包络示意图,在1/T的整数倍上存在包络零点

3. 仿真验证

如下图所示,仿真生成两个正弦信号,观察在有效样点数不够、有效样点数足够及有效样点数不够但通过补零增加样点数目这三种情况下的频谱,各个参数设置及仿真代码见附录。下图表明,补零并不能提高FFT对信号的分辨能力,只能起到对频谱进行插值和平滑的作用,与前面的理论推导结论相符。
在这里插入图片描述

图5. 仿真不同样点条件下FFT的分辨能力

【附录1】:图1代码

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 使用微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False  # 处理负号显示异常

if __name__ == '__main__':
    f0 = 1000
    f1 = 24000
    fs = 10000
    N = 2000
    t = np.arange(0, N, 1) / fs
    sig = np.sin(2 * np.pi * f0 * t) + np.sin(2 * np.pi * f1 * t)
    plt.figure()
    plt.plot(np.linspace(-fs / 2, fs / 2, N), 20 * np.log10(np.fft.fftshift(np.abs(np.fft.fft(sig)))), 'b.-')
    plt.show()

【附录2】:仿真验证代码


import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 使用微软雅黑字体
plt.rcParams['axes.unicode_minus'] = False  # 处理负号显示异常

if __name__ == '__main__':
    f0 = 200
    f1 = 250
    fs = 100000
    df = f1 - f0
    data_time = 1 / df
    N = int(data_time * fs)
    # ##############样点数不够的情况###############
    t1 = np.arange(0, N // 2, 1) / fs
    sig_1 = np.sin(2 * np.pi * f0 * t1) + np.sin(2 * np.pi * f1 * t1)

    # ###############样点数够的情况###############
    t2 = np.arange(0, 2 * N - 1, 1) / fs
    sig_2 = np.sin(2 * np.pi * f0 * t2) + np.sin(2 * np.pi * f1 * t2)

    # ##############对样点数不够的情况进行补零###############
    sig_3 = np.zeros(10 * N)
    sig_3[0:len(sig_1)] = sig_1

    plt.figure()
    plt.subplot(3, 1, 1)
    plt.plot(np.linspace(-fs / 2, fs / 2, len(sig_1)), 20 * np.log10(np.fft.fftshift(np.abs(np.fft.fft(sig_1)))), 'b.-')
    plt.xlim([-500, 500])
    plt.title('样点数不够')
    plt.subplot(3, 1, 2)
    plt.plot(np.linspace(-fs / 2, fs / 2, len(sig_2)), 20 * np.log10(np.fft.fftshift(np.abs(np.fft.fft(sig_2)))), 'b.-')
    plt.xlim([-500, 500])
    plt.title('样点数足够')
    plt.subplot(3, 1, 3)
    plt.plot(np.linspace(-fs / 2, fs / 2, len(sig_3)), 20 * np.log10(np.fft.fftshift(np.abs(np.fft.fft(sig_3)))), 'b.-')
    plt.xlim([-500, 500])
    plt.title('样点数不够,补零')
    plt.xlabel('Frequency(Hz)')
    plt.show()
 
  • 39
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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~

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值