如何在python中提取与fft值相关的频率

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3694918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:17:34  来源:igfitidea点击:

how to extract frequency associated with fft values in python

pythonnumpyfft

提问by ria

I used fftfunction in numpy which resulted in a complex array. How to get the exact frequency values?

fft在 numpy 中使用了函数,这导致了一个复杂的数组。如何获得准确的频率值?

采纳答案by unutbu

np.fft.fftfreqtells you the frequencies associated with the coefficients:

np.fft.fftfreq告诉您与系数相关的频率:

import numpy as np

x = np.array([1,2,1,0,1,2,1,0])
w = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x))

for coef,freq in zip(w,freqs):
    if coef:
        print('{c:>6} * exp(2 pi i t * {f})'.format(c=coef,f=freq))

# (8+0j) * exp(2 pi i t * 0.0)
#    -4j * exp(2 pi i t * 0.25)
#     4j * exp(2 pi i t * -0.25)


The OP asks how to find the frequency in Hertz. I believe the formula is frequency (Hz) = abs(fft_freq * frame_rate).

OP 询问如何以赫兹为单位找到频率。我相信公式是frequency (Hz) = abs(fft_freq * frame_rate).

Here is some code that demonstrates that.

这里有一些代码可以证明这一点。

First, we make a wave file at 440 Hz:

首先,我们制作一个 440 Hz 的波形文件:

import math
import wave
import struct

if __name__ == '__main__':
    # http://stackoverflow.com/questions/3637350/how-to-write-stereo-wav-files-in-python
    # http://www.sonicspot.com/guide/wavefiles.html
    freq = 440.0
    data_size = 40000
    fname = "test.wav"
    frate = 11025.0
    amp = 64000.0
    nchannels = 1
    sampwidth = 2
    framerate = int(frate)
    nframes = data_size
    comptype = "NONE"
    compname = "not compressed"
    data = [math.sin(2 * math.pi * freq * (x / frate))
            for x in range(data_size)]
    wav_file = wave.open(fname, 'w')
    wav_file.setparams(
        (nchannels, sampwidth, framerate, nframes, comptype, compname))
    for v in data:
        wav_file.writeframes(struct.pack('h', int(v * amp / 2)))
    wav_file.close()

This creates the file test.wav. Now we read in the data, FFT it, find the coefficient with maximum power, and find the corresponding fft frequency, and then convert to Hertz:

这将创建文件test.wav。现在我们读入数据,对其进行FFT,找到功率最大的系数,并找到对应的fft频率,然后转换为赫兹:

import wave
import struct
import numpy as np

if __name__ == '__main__':
    data_size = 40000
    fname = "test.wav"
    frate = 11025.0
    wav_file = wave.open(fname, 'r')
    data = wav_file.readframes(data_size)
    wav_file.close()
    data = struct.unpack('{n}h'.format(n=data_size), data)
    data = np.array(data)

    w = np.fft.fft(data)
    freqs = np.fft.fftfreq(len(w))
    print(freqs.min(), freqs.max())
    # (-0.5, 0.499975)

    # Find the peak in the coefficients
    idx = np.argmax(np.abs(w))
    freq = freqs[idx]
    freq_in_hertz = abs(freq * frate)
    print(freq_in_hertz)
    # 439.8975

回答by kennytm

The frequency is just the index of the array. At index n, the frequency is 2πn/ the array's length (radians per unit). Consider:

频率只是数组的索引。在索引n 处,频率为 2 πn/ 阵列的长度(每单位弧度)。考虑:

>>> numpy.fft.fft([1,2,1,0,1,2,1,0])
array([ 8.+0.j,  0.+0.j,  0.-4.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+4.j,
        0.+0.j])

the result has nonzero values at indices 0, 2 and 6. There are 8 elements. This means

结果在索引 0、2 和 6 处具有非零值。有 8 个元素。这意味着

       2πit/8 × 0       2πit/8 × 2       2πit/8 × 6
    8 e           - 4i e           + 4i e
y ~ ———————————————————————————————————————————————
                          8

回答by gboffi

Frequencies associated with DFT values (in python)

与 DFT 值相关的频率(在 python 中)

By fft, Fast Fourier Transform, we understand a member of a large family of algorithms that enable the fastcomputation of the DFT, Discrete Fourier Transform, of an equisampled signal.

通过fft(快速傅里叶变换),我们了解了一大类算法中的一个成员,这些算法能够快速计算等采样信号的 DFT(离散傅里叶变换)。

A DFTconverts a list of Ncomplex numbers to a list of Ncomplex numbers, with the understanding that both lists are periodic with period N.

一个DFT列表转换ň复数到列表ñ复数,但有一项谅解,这两个名单是周期性的,周期ñ

Here we deal with the numpyimplementation of the fft.

这里我们处理fftnumpy实现。

In many cases, you think of

在很多情况下,你会想到

  • a signal xdefined in the time domain of length N, sampled at a constant interval dt,
  • its DFT X(here specifically X = np.fft.fft(x)), whose elements are sampled on the frequency axis with a sample rate dw.
  • 在长度为N的时域中定义的信号x,以恒定间隔dt采样,
  • 它的 DFT X(这里特别是X = np.fft.fft(x)),其元素在频率轴上以采样率dw采样。

Some definition

一些定义

  • the period (aka duration) of the signal x, sampled at dtwith Nsamples is is

    T = dt*N
    
  • the fundamental frequencies (in Hz and in rad/s) of X, your DFT are

    df = 1/T
    dw = 2*pi/T # =df*2*pi
    
  • the top frequency is the Nyquist frequency

    ny = dw*N/2
    

    (and it's not dw*N)

  • 用样本x采样的信号的周期(又名持续时间)是dtN

    T = dt*N
    
  • 的基本频率(以赫兹和弧度/秒为单位)X,您的 DFT 是

    df = 1/T
    dw = 2*pi/T # =df*2*pi
    
  • 最高频率是奈奎斯特频率

    ny = dw*N/2
    

    (它不是dw*N

The frequencies associated with a particular element in the DFT

与 DFT 中特定元素相关的频率

The frequencies corresponding to the elements in X = np.fft.fft(x)for a given index 0<=n<Ncan be computed as follows:

与给X = np.fft.fft(x)定索引中的元素对应的频率0<=n<N可以计算如下:

def rad_on_s(n, N, dw):
    return dw*n if n<N/2 else dw*(n-N)

or in a single sweep

或在一次扫描中

w = np.array([dw*n if n<N/2 else dw*(n-N) for n in range(N)])

if you prefer to consider frequencies in Hz, s/w/f/

如果您更愿意考虑以 Hz 为单位的频率, s/w/f/

f = np.array([df*n if n<N/2 else df*(n-N) for n in range(N)])

Using those frequencies

使用这些频率

If you want to modify the original signal x-> yapplying an operator in the frequency domain in the form of a function of frequency only, the way to go is computing the w's and

如果您想修改原始信号x->y仅以频率函数的形式在频域中应用运算符,则要走的路是计算w的 和

Y = X*f(w)
y = ifft(Y)

Introducing np.fft.fftfreq

介绍 np.fft.fftfreq

Of course numpyhas a convenience function np.fft.fftfreqthat returns dimensionless frequenciesrather than dimensional onesbut it's as easy as

当然numpy有一个方便的函数np.fft.fftfreq,它返回无量纲的频率而不是有维的频率但它很简单

f = np.fft.fftfreq(N)*N*df
w = np.fft.fftfreq(N)*N*dw

Because df = 1/Tand T = N/sps(spsbeing the number of samples per second) one can also write

因为df = 1/TT = N/spssps每秒样本数)也可以写

f = np.fft.fftfreq(N)*sps