【问题标题】:How to compute frequency of data using FFT?如何使用 FFT 计算数据的频率?
【发布时间】:2011-05-12 15:28:31
【问题描述】:

我想知道数据的频率。我有一点想法可以使用 FFT 来完成,但我不知道该怎么做。一旦我将整个数据传递给 FFT,它就会给我 2 个峰值,但我怎样才能得到频率?

非常感谢。

【问题讨论】:

  • FFT 将为您提供信号正弦分量的频率。如果您想测量真实信号(任何形状)的频率,那么您必须忘记 FFT 并使用样本扫描进行过零或峰值搜索等……很大程度上取决于信号的形状和偏移量。顺便说一句,在 FFT 上你有 2 次偷看,如果输入信号在实域上,一个是第一个的镜像)所以忽略 FFT 的后半部分

标签: algorithm c#-3.0 signal-processing fft


【解决方案1】:

频率 = 速度/波长。

波长是两个峰之间的距离。

【讨论】:

  • 频率域中的两个峰值。
  • 史蒂夫:不完全是。如果您的数据确实是具有单个最大值的周期性数据,那么峰值之间的距离将为您提供准确的 1/f。但是,通常您处理的是半周期数据,而应用于周期数据的标准数学分析不起作用。
  • 我之前评论的意思是,作者在频域得到了两个峰值。这个答案错误地将两个峰值解释为在时域中。
【解决方案2】:

假设x[n] = cos(2*pi*f0*n/fs),其中f0 是正弦波的频率,以赫兹为单位,n=0:N-1fsx 的采样率,以每秒样本为单位。

X = fft(x)xX 的长度均为 N。假设Xn0N-n0 有两个峰值。

那么正弦频率f0 = fs*n0/NHertz。

示例fs = 每秒 8000 个样本,N = 16000 个样本。因此,x 会持续两秒。

假设 X = fft(x) 在 2000 和 14000 (=16000-2000) 处有峰值。因此,f0 = 8000*2000/16000 = 1000 Hz。

【讨论】:

  • 这是正确的。但请注意,由于 fft 设计(蝴蝶网络),fft 算法给出的数据通常会出现偏差。在解释值之前必须先对其进行移位。
【解决方案3】:

如果您正在查看最常用类型的 FFT 的幅度结果,那么实际数据的强正弦频率分量将出现在两个位置,一个在下半部分,再加上它的复共轭镜像上半部分。这两个峰值都代表相同的光谱峰值和相同的频率(对于严格的真实数据)。如果 FFT 结果 bin 编号从 0(零)开始,则 FFT 结果下半部分 bin 表示的正弦分量的频率最有可能。

Frequency_of_Peak = Data_Sample_Rate * Bin_number_of_Peak / Length_of_FFT ;

确保在上述等式中计算出正确的单位(以获取每秒、每两周、每千秒差距等的周期单位)

请注意,除非数据的波长是 FFT 长度的精确整数因数,否则实际峰值将在 bin 之间,从而在多个附近的 FFT 结果 bin 之间分配能量。因此,您可能必须进行插值以更好地估计频率峰值。找到更精确频率估计的常用插值方法是 3 点抛物线和 Sinc 卷积(这与使用零填充的较长 FFT 几乎相同)。

【讨论】:

    【解决方案4】:

    您可能正在寻找以下内容:

    当您谈论计算信号的频率时,您可能对分量正弦波不太感兴趣。这就是 FFT 给你的。例如,如果将 sin(2*pi*10x)+sin(2*pi*15x)+sin(2*pi*20x)+sin(2*pi*25x) 相加,您可能想要检测“频率" 为 5(看看这个函数的图表)。然而,这个信号的 FFT 将检测到频率 5 的 0 的幅度。

    您可能更感兴趣的是信号的周期性。也就是说,信号变得最像它自己的时间间隔。所以最有可能你想要的是自相关。查一下。这基本上可以让您衡量信号在移动一定量后与自身的自相似程度。因此,如果您在自相关中找到一个峰值,则表明信号在移动超过该量时与自身匹配良好。它背后有很多很酷的数学,如果您有兴趣,请查看它,但如果您只想让它工作,请这样做:

    1. 使用平滑窗口对信号进行窗口化(余弦即可。窗口应至少是您要检测的最大周期的两倍。大 3 倍会得到更好的结果)。 (如果您感到困惑,请参阅http://zone.ni.com/devzone/cda/tut/p/id/4844)。

    2. 进行 FFT(但是,请确保 FFT 大小是窗口的两倍,后半部分用零填充。如果 FFT 大小只是窗口的大小,您将有效地采用循环自相关,这不是你想要的。见https://en.wikipedia.org/wiki/Discrete_Fourier_transform#Circular_convolution_theorem_and_cross-correlation_theorem

    3. 将 FFT 的所有系数替换为其平方值 (real^2+imag^2)。这有效地采取了自相关。

    4. 参加 iFFT

    5. 在 iFFT 中找到最大的峰值。这是波形的最强周期性。实际上,您可以更聪明地选择哪个峰值,但对于大多数目的而言,这应该足够了。要找到频率,只需取 f=1/T。

    【讨论】:

    • 感谢您在这里的明确回答,查看了很多关于这个主题的信息,这让我更清楚了。
    【解决方案5】:

    如果你有一个频率的信号(例如:

    y = sin(2 pi f t)
    

    与:

    • y 时间信号
    • f 中心频率
    • t 时间

    然后你会得到两个峰值,一个对应于 f 的频率,一个对应于 -f 的频率。

    所以,要得到一个频率,可以丢弃负频率部分。它位于正频率部分之后。此外,数组中的第一个元素是直流偏移,因此频率为 0。(请注意,此偏移通常远大于 0,因此其他频率分量可能会因此而相形见绌。)

    在代码中:(我用python写过,但在c#中应该同样简单):

    import numpy as np
    from pylab import * 
    x = np.random.rand(100) # create 100 random numbers of which we want the fourier transform
    x = x - mean(x) # make sure the average is zero, so we don't get a huge DC offset.
    dt = 0.1 #[s] 1/the sampling rate
    fftx = np.fft.fft(x) # the frequency transformed part
    # now discard anything  that we do not need..
    fftx = fftx[range(int(len(fftx)/2))]
    # now create the frequency axis: it runs from 0 to the sampling rate /2
    freq_fftx = np.linspace(0,2/dt,len(fftx))
    # and plot a power spectrum
    plot(freq_fftx,abs(fftx)**2)
    show()
    

    现在频率位于最大峰值。

    【讨论】:

    • +1 用于减去平均值以驯服 DC 偏移。在我看来,如果您使用采样频率来索引频率而不是采样周期会更清楚。
    • 不错!但是答案中有一个错字:情节线必须是 plot(freq_fftx,abs(fftx)**2)
    • 谢谢!修好了。
    【解决方案6】:

    假设您使用离散傅立叶变换来查看频率,那么您必须小心如何将归一化的频率解释回物理频率(即 Hz)。

    根据FFTW tutorial关于如何计算信号的功率谱:

    #include <rfftw.h>
    ...
    {
         fftw_real in[N], out[N], power_spectrum[N/2+1];
         rfftw_plan p;
         int k;
         ...
         p = rfftw_create_plan(N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE);
         ...
         rfftw_one(p, in, out);
         power_spectrum[0] = out[0]*out[0];  /* DC component */
         for (k = 1; k < (N+1)/2; ++k)  /* (k < N/2 rounded up) */
              power_spectrum[k] = out[k]*out[k] + out[N-k]*out[N-k];
         if (N % 2 == 0) /* N is even */
              power_spectrum[N/2] = out[N/2]*out[N/2];  /* Nyquist freq. */
         ...
         rfftw_destroy_plan(p);
    }
    

    注意它处理的数据长度不是偶数。请特别注意,如果给出了数据长度,FFTW 将为您提供一个对应于奈奎斯特频率(采样率除以 2)的“bin”。否则,您不会得到它(即最后一个 bin 就在 Nyquist 下方)。

    MATLAB example 类似,但他们选择长度为 1000(偶数)作为示例:

    N = length(x);
    xdft = fft(x);
    xdft = xdft(1:N/2+1);
    psdx = (1/(Fs*N)).*abs(xdft).^2;
    psdx(2:end-1) = 2*psdx(2:end-1);
    freq = 0:Fs/length(x):Fs/2;
    

    一般来说,它可以依赖于(DFT 的)实现。您应该以已知频率创建一个测试纯正弦波,然后确保计算得到相同的数字。

    【讨论】:

      猜你喜欢
      • 2021-03-09
      • 1970-01-01
      • 2017-08-11
      • 2014-03-18
      • 2014-12-18
      • 2013-12-06
      • 1970-01-01
      • 2020-05-22
      • 2013-04-10
      相关资源
      最近更新 更多