54 votes

comment extraire la fréquence associée aux valeurs fft en python

J'ai utilisé fft dans numpy, ce qui a donné lieu à un tableau complexe. Comment obtenir les valeurs exactes de la fréquence ?

75voto

unutbu Points 222216

np.fft.fftfreq vous indique les fréquences associées aux coefficients :

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)

L'OP demande comment trouver la fréquence en Hertz. Je crois que la formule est frequency (Hz) = abs(fft_freq * frame_rate) .

Voici un code qui le démontre.

Tout d'abord, nous créons un fichier d'ondes à 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()

Cela crée le fichier test.wav . Maintenant nous lisons les données, nous les transformons en FFT, nous trouvons le coefficient avec la puissance maximale, et on trouve la fréquence fft correspondante, puis on convertit en Hertz :

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

49voto

gboffi Points 3681

Fréquences associées aux valeurs DFT (en python)

Par fft Avec la transformée de Fourier rapide, nous comprenons un membre d'une grande famille d'algorithmes qui permettent le rapide calcul de la TFD, Transformée de Fourier Discrète, d'un signal équi-échantillonné.

A DFT convertit une liste de N des nombres complexes à une liste de N les nombres complexes, étant entendu que les deux listes sont périodiques avec la période N .

Nous traitons ici de la numpy mise en œuvre de la fft .

Dans de nombreux cas, vous pensez à

  • un signal x défini dans le domaine temporel de longueur N échantillonné à un intervalle constant dt ,
  • son DFT X (ici spécifiquement X = np.fft.fft(x) ), dont les éléments sont échantillonnés sur l'axe des fréquences avec une fréquence d'échantillonnage dw .

Quelques définitions

  • la période (c'est-à-dire la durée) du signal x , échantillonné à dt con N échantillons est est

    T = dt*N
  • les fréquences fondamentales (en Hz et en rad/s) de X vos DFT sont

    df = 1/T
    dw = 2*pi/T # =df*2*pi
  • la fréquence supérieure est la Nyquist fréquence

    ny = dw*N/2

    (et ce n'est pas dw*N )

Les fréquences associées à un élément particulier dans la TFD

Les fréquences correspondant aux éléments dans X = np.fft.fft(x) pour un indice donné 0<=n<N peut être calculée comme suit :

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

ou en un seul coup de balai

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

si vous préférez considérer les fréquences en Hz, s/w/f/

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

En utilisant ces fréquences

Si vous voulez modifier le signal original x -> y Si l'on applique un opérateur dans le domaine fréquentiel sous la forme d'une fonction de la fréquence uniquement, la méthode consiste à calculer la fonction de la fréquence. w et

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

Présentation de np.fft.fftfreq

Bien sûr. numpy a une fonction de commodité np.fft.fftfreq qui renvoie fréquences sans dimension plutôt que dimensionnels mais c'est aussi simple que

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

Parce que df = 1/T y T = N/sps ( sps étant le nombre d'échantillons par seconde), on peut également écrire

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

7voto

KennyTM Points 232647

La fréquence est simplement l'index du tableau. A l'indice n la fréquence est de 2 n / la longueur du tableau (radians par unité). Considérez :

>>> 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])

le résultat a des valeurs non nulles aux indices 0, 2 et 6. Il y a 8 éléments. Cela signifie que

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X