样本数量对 FFT 是否重要,以及如何使特定频率可见?

信息处理 fft 频率 频域
2021-12-22 03:59:02

如果我有一个具有 740 个样本的信号,采样频率为 1000 Hz,并且我采用长度为 1024 的 FFT,我现在得到的频率是 0、fs/1024、2*fs/1000、...、511* fs/1024? 我的意思是,我是否正确理解:频率分辨率不取决于我拥有的样本数量,仅取决于 FFT 长度和采样频率。如果我有 1480 个样本,分辨率还是一样吗?这让我很头疼。

接下来,假设我的信号在 26 Hz 处有一个有趣的频率(严格来说是一个频率)。如何让它在频谱中正确显示(我的频率箱间隔 1000/1024 = 0.9766 Hz,所以我处于死胡同吗?)。

3个回答

“信息内容”与样本数量有关。FFT 的长度只是对由样本数表示的频谱频率曲线进行插值。如果 FFT 结果 bin 没有完全以某个所需频率为中心,您可以使用高质量(Sinc 内核等)插值器从最近的 bin 对其进行插值,因为 FFT bin 具有大于- 零带宽(默认矩形或其他窗口的变换形状)。使用更长的零填充 FFT 可以为您提供更多的插值点,从而获得更密集的点图,但没有比实际样本数量提供的更好的光谱分离分辨率。

这是约翰 BG jgb2012@sky.com

1.- 举个例子

N1=740;

fs=1e3;dt=1/fs  % time reference
t=[0:dt:N1*dt];

A=1    % signal
f0=26
s0=A*cos(2*pi*f0*t);

n0=wgn(N1+1,1,-36,'complex')'; % -6dBmW noise

n0=wgn(N1+1,1,-16,'complex')';  % 24dBm noise

s=s0+real(n0);

figure(1);plot(t,s);grid on   

-6dBm(W) 噪声和 24dBm(W) 噪声

Nfft=2^10;
S=fft(s,Nfft)

figure(2);
Sabs=abs(S);
Sang=angle(S);
subplot(2,1,1);plot(Sabs);grid on;title('|S|')
subplot(2,1,2);plot(Sang);grid on;title('angle(S)')

FFT 绝对值和角度,放大检测到的音调

关于你的第二个问题

如何让它在频谱中正确显示?

将 FFT 中的 bin 位置转换为 Hz 的方法如下:

f0_measure=28/(Nffs/2)*fs/2  

=
  27.3437

FFT bin 28 上的峰值相当于频率 27.3437 Hz。

添加的噪声很复杂,因此会影响相位和幅度。

频率测量的误差为

abs(f0-f0_measure)

 =
  1.343750000000000

2.- 让 MATLAB 找到峰值,而不是手动将标记放在峰值上并获取 bin #28:

nmax=find(Sabs==max(Sabs))
nmax=nmax(1)   % remove the FFT mirror

在将 FFT bin 转换为频率的上述表达式中,将 28 替换为 nmax。

3.- 现在是第一个问题的第一部分

频率分辨率不取决于我拥有的样本数量,仅取决于 FFT 长度和采样频率?

如果为相同数量的输入时间样本增加 FFT 箱的数量,是的,FFT 看起来是一样的,但这并不意味着频率测量是正确的。

f0=.75*fs

现在有别名,采样频率不够快,没有注意到采样低于奈奎斯特极限,然后发生这种情况,重复上述

别名发生 f0=.75*fs

现在

f0_measure=257/(1024/2)*fs/2 
f0_measure =
     2.509765625000000e+02

峰值应该在 26Hz 左右,但你看到的是 250.9Hz

第一个问题的第二部分

如果我有 1480 个样本,分辨率还是一样吗?

不,如果你增加时间样本的数量,通过这种理解,对于相同的信号,不是更长的观察窗口,而是相同观察窗口内的更多样本,因此更高的采样频率 fs,那么如果你也增加 FFT 的数量bins,那么您可以提高频率分辨率,请参见以下示例。

让我们举一个 2 音的例子,一个在 26Hz,你提到的感兴趣的频率,另一个在 28Hz,第一个的半幅度:

N1=740;

fs=1e3;dt=1/fs  % time reference
t=[0:dt:N1*dt];

A=1    

f01=26
f02=28

s01=A*cos(2*pi*f01*t);
s02=A*cos(2*pi*f02*t+pi/2);

n0=wgn(N1+1,1,-16,'complex')';  % 24dBm

s=s01+s02+real(n0);

figure(1);plot(t,s);grid on   

重复上述 FFT 行,

Nfft=2^10;
S=fft(s,Nfft);

figure(2);
Sabs=abs(S);
Sang=angle(S);
subplot(2,1,1);plot(Sabs);grid on;title('|S|')
subplot(2,1,2);plot(Sang);grid on;title('angle(S)')

在此处输入图像描述

可以看出频率分辨率不够

但重要的是,请注意仅将垃圾箱的数量从 2^10 增加到 2^20

Nfft=2^20;
S=fft(s,Nfft);

figure(2);
Sabs=abs(S);
Sang=angle(S);
subplot(2,1,1);plot(Sabs);grid on;title('|S|')
subplot(2,1,2);plot(Sang);grid on;title('angle(S)')

在此处输入图像描述

它确实以某种方式提高了频率分辨率,而无需额外增加输入时间样本的数量:

目前尚不清楚是否有 2 个或更多音调,但与 2^10 个 bin FFT 相比,很明显它有一些需要改进的东西,在相同数量的 FFT bin 数量较少时会被忽略输入时间样本。

越接近 MATLAB 默认的矩阵大小上限,

  Nfft=2^26;
  ..

  Nfft=2^28;
  ..

超过一定数量的 FFT 箱,在具有相同输入时间样本数量的 FFT 重叠之后,没有显着改善

   for k=1:1:5
        N2=N1*2^(k-1)
        t=[0:dt:N2*dt];
        s01=A*cos(2*pi*f01*t);
        s02=A*cos(2*pi*f02*t+pi/2);
        n0=wgn(N2+1,1,-16,'complex')';  % 24dBm
        s=s01+s02+real(n0);

        Nfft=2^10;
        S=fft(s,Nfft)

        Sabs=abs(S);
        Sang=angle(S);

        figure(5);plot(Sabs);grid on;title('|S|')
        hold all
    end

axis( 1.0e+02 *[   0.041474654377880   0.649769585253456    0    4.440962099125365])

在此处输入图像描述

并且要计算的 FFT 样本量越大,获得每个 FFT 所需的时间就越长。

结果仍然略好于使用较少数量的 FFT 箱,但现在解析的 2 个音调的幅度仍然不准确,因为我们知道它们没有相等的幅度,但它显示好像它们是一样的。

因此,是的,对于相同的时间输入信号量增加 FFT 箱的数量,可以在一定程度上提高频率分辨率。

结论:

但最好的办法是同时增加两者:时间样本的数量和 FFT 箱的数量:

for k=1:1:5
    N2=N1*2^(k-1)
    t=[0:dt:N2*dt];
    s01=A*cos(2*pi*f01*t);
    s02=A*cos(2*pi*f02*t+pi/2);
    n0=wgn(N2+1,1,-16,'complex')';  % 24dBm
    s=s01+s02+real(n0);

    Nfft=2^(10+k-1);
    S=fft(s,Nfft)

    Sabs=abs(S);
    Sang=angle(S);

    figure(6);plot(Sabs);grid on;title('|S|')
    hold all
end

axis=(  1.0e+03 *[ 0.271758436944937   0.815275310834813    0  5.952380952380953])

在此处输入图像描述

对于问题的发起者,如果您觉得这个答案有用,您会考虑将我的答案标记为已接受的答案吗?

对于任何读者,如果您觉得这个答案有用,请考虑点击点赞投票链接

提前感谢您的时间和关注

约翰·BG

jgb2012@sky.com

关于您的第一个问题,您的频率粒度只是 $\frac{f_s}{N}$,其中 $f_s$ 是以 Hz 为单位的采样频率,$N$ 是 FFT 的长度。(请记住,您总是希望 FFT 长度至少等于您的数据记录长度)。

接下来,假设我的信号在 26 Hz 处有一个有趣的频率(严格来说是一个频率)。如何让它在频谱中正确显示(我的频率箱间隔 1000/1024 = 0.9766 Hz,所以我处于死胡同吗?)。

您可以简单地对信号进行零填充,这将产生平滑傅立叶变换估计的效果。它不会在工程意义上给你更好的分辨率,但可以说它会给你更好的“视觉分辨率”,这样你就可以更好地确定一个峰值。