Comprendre la sortie FFT

87

J'ai besoin d'aide pour comprendre le résultat du calcul DFT / FFT.

Je suis un ingénieur logiciel expérimenté et j'ai besoin d'interpréter certaines lectures d'accéléromètre de smartphone, telles que la recherche des principales fréquences. Malheureusement, j'ai dormi pendant la plupart de mes cours d'EE au collège il y a quinze ans, mais j'ai lu sur DFT et FFT ces derniers jours (en vain, apparemment).

S'il vous plaît, aucune réponse de "allez suivre un cours d'EE". Je prévois en fait de le faire si mon employeur me paie. :)

Alors voici mon problème:

J'ai capturé un signal à 32 Hz. Voici un échantillon d'une seconde de 32 points, que j'ai cartographié dans Excel.

entrez la description de l'image ici

J'ai ensuite reçu du code FFT écrit en Java de l'Université de Columbia (après avoir suivi les suggestions d'un article sur " FFT fiable et rapide en Java ").

La sortie de ce programme est la suivante. Je crois qu'il exécute une FFT en place, donc il réutilise le même tampon pour l'entrée et la sortie.

Before: 

Re: [0.887  1.645  2.005  1.069  1.069  0.69  1.046  1.847  0.808  0.617  0.792  1.384  1.782  0.925  0.751  0.858  0.915  1.006  0.985  0.97  1.075  1.183  1.408  1.575  1.556  1.282  1.06  1.061  1.283  1.701  1.101  0.702  ]

Im: [0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  ]

After: 

Re: [37.054  1.774  -1.075  1.451  -0.653  -0.253  -1.686  -3.602  0.226  0.374  -0.194  -0.312  -1.432  0.429  0.709  -0.085  0.0090  -0.085  0.709  0.429  -1.432  -0.312  -0.194  0.374  0.226  -3.602  -1.686  -0.253  -0.653  1.451  -1.075  1.774  ]

Im: [0.0  1.474  -0.238  -2.026  -0.22  -0.24  -5.009  -1.398  0.416  -1.251  -0.708  -0.713  0.851  1.882  0.379  0.021  0.0  -0.021  -0.379  -1.882  -0.851  0.713  0.708  1.251  -0.416  1.398  5.009  0.24  0.22  2.026  0.238  -1.474  ]

Donc, à ce stade, je ne peux pas faire des têtes ou des queues de la sortie. Je comprends les concepts DFT, tels que la partie réelle étant les amplitudes des ondes cosinus composantes et la partie imaginaire étant les amplitudes des ondes sinusoïdales composantes. Je peux également suivre ce diagramme du grand livre " Le guide du scientifique et de l'ingénieur sur le traitement numérique du signal ": entrez la description de l'image ici

Donc mes questions spécifiques sont:

  1. A partir de la sortie de la FFT, comment trouver les "fréquences les plus fréquentes"? Cela fait partie de mon analyse de mes données d'accéléromètre. Dois-je lire les tableaux réels (cosinus) ou imaginaires (sinus)?

  2. J'ai une entrée de 32 points dans le domaine temporel. La sortie de la FFT ne devrait-elle pas être un tableau de 16 éléments pour les réels et un tableau de 16 éléments pour l'imaginaire? Pourquoi le programme me donne-t-il des sorties de tableau réelles et imaginaires de taille 32?

  3. Lié à la question précédente, comment analyser les index dans les tableaux de sortie? Compte tenu de mon entrée de 32 échantillons échantillonnés à 32 Hz, je crois comprendre qu'une sortie de tableau de 16 éléments devrait avoir son index uniformément réparti jusqu'à la moitié de la fréquence d'échantillonnage (de 32 Hz), donc j'ai raison de comprendre que chaque élément du tableau représente (32 Hz * 1/2) / 16 = 1 Hz?

  4. Pourquoi la sortie FFT a-t-elle des valeurs négatives? Je pensais que les valeurs représentaient les amplitudes d'une sinusoïde. Par exemple, la sortie de Real [3] = -1,075 devrait signifier une amplitude de -1,075 pour une onde cosinus de fréquence 3. Est-ce vrai? Comment une amplitude peut-elle être négative?

stackoverflowuser2010
la source
Qu'aimeriez-vous calculer à partir des lectures de l'accéléromètre: vitesse, distance? Le bruit des lectures de l'accéléromètre suit la distribution gaussienne et je ne vois pas comment l'ajustement d'une onde sinusoïdale y remédierait.
Ali
2
la balise java doit être supprimée car elle est plus générique que dans une langue spécifique
user3791372
En regardant la souce de l'Université de Columbia, ce n'est pas du tout efficace. C'est une implémentation simple et non optimisée de Cooley-Tucky avec des tables de recherche Butterfly, et l'inversion de bits est effectuée manuellement au lieu d'utiliser les fonctions de bibliothèque existantes
Mark Jeronimus
@MarkJeronimus: Pouvez-vous recommander une implémentation FFT efficace en Java? Si je me souviens bien, la raison pour laquelle j'ai choisi le code de l'Université Columbia était que la bibliothèque FFTW était trop complexe pour fonctionner sur un smartphone Android.
stackoverflowuser2010
J'ai trouvé des implémentations `` optimisées '' dispersées, mais il s'agit essentiellement d'un algorithme par taille N, donc si vous avez besoin d'une gamme de tailles, vous avez besoin de toutes ces routines. En pratique, j'ai principalement utilisé les primitives Intel Integrated Performance (oui, de Java, via JNA), mais ce n'est pas gratuit. À la maison, j'utilise essentiellement le même algorithme que vous avez lié, mais écrit à partir de zéro en 2005 à l'aide d'un manuel. C'est juste FFT (Fast Fourier Transform), rien d'aussi «rapide» à ce sujet pour justifier le nom de «Fast FFT».
Mark Jeronimus

Réponses:

85
  1. Vous ne devez ni chercher la partie réelle ou imaginative d'un nombre complexe (ce qu'est votre tableau réel et imaginaire). Au lieu de cela, vous voulez rechercher la magnitude de la fréquence qui est définie comme sqrt (real * real + imag * imag). Ce nombre sera toujours positif. Il ne vous reste plus qu'à rechercher la valeur maximale (ignorez la première entrée de votre tableau. C'est votre décalage CC et ne contient aucune information dépendant de la fréquence).

  2. Vous obtenez 32 sorties réelles et 32 ​​imaginaires parce que vous utilisez une FFT complexe à complexe. N'oubliez pas que vous avez converti vos 32 échantillons en 64 valeurs (ou 32 valeurs complexes) en l'étendant avec zéro partie imaginaire. Il en résulte une sortie FFT symétrique où le résultat de fréquence apparaît deux fois. Une fois prêt à l'emploi dans les sorties 0 à N / 2, et une fois mis en miroir dans les sorties N / 2 à N.Dans votre cas, il est plus simple d'ignorer simplement les sorties N / 2 à N.Vous n'en avez pas besoin, elles sont juste un artefact sur la façon dont vous calculez votre FFT.

  3. La fréquence de l'équation fft-bin est (bin_id * freq / 2) / (N / 2) où freq est votre fréquence d'échantillonnage (c'est-à-dire 32 Hz, et N est la taille de votre FFT). Dans votre cas, cela se simplifie à 1 Hz par bac. Les cases N / 2 à N représentent des fréquences négatives (concept étrange, je sais). Pour votre cas, ils ne contiennent aucune information significative car ils ne sont qu'un miroir des N / 2 premières fréquences.

  4. Vos parties réelles et imaginaires de chaque bac forment un nombre complexe. Ce n'est pas grave si les parties réelles et imaginaires sont négatives alors que la magnitude de la fréquence elle-même est positive (voir ma réponse à la question 1). Je vous suggère de lire sur les nombres complexes. Expliquer comment ils fonctionnent (et pourquoi ils sont utiles) dépasse ce qu'il est possible d'expliquer en une seule question stackoverflow.

Remarque: vous voudrez peut-être aussi lire ce qu'est l'autocorrélation et comment elle est utilisée pour trouver la fréquence fondamentale d'un signal. J'ai le sentiment que c'est ce que tu veux vraiment.

Nils Pipenbrinck
la source
1
Merci. Concernant 1: j'ai vu cette page Matlab qui montre un spectre de fréquences ( mathworks.com/help/techdoc/ref/fft.html ). Sur cette page se trouve un graphique intitulé "Spectre d'amplitude unilatéral de y (t)". Est-ce que cela représente la magnitude de la fréquence comme vous l'avez suggéré, sqrt (real ^ 2 + img ^ 2)? Concernant 3: je n'obtiens toujours pas le résultat de 2Hz par bac. Dans mon cas, N = 32 et freq = 32, non? Donc, il y a N / 2 = 32/2 = 16 bins, et la fréquence la plus élevée (Nyquist) est freq / 2 = 32/2 = 16 Hz, ce qui donne 16 Hz pour 16 bins, ce qui donne 1 Hz par bin?
stackoverflowuser2010
1
Oui, le graphique montre la magnitude du spectre - | Y (f) |. Les barres de valeur absolue indiquent la magnitude. Largeur du bac = fréquence d'échantillonnage / taille FFT. Votre fréquence d'échantillonnage est de 32 hz, votre taille FFT est de 32. Oui, vous avez raison sur la largeur du bac!
Matt Montag
Correction de la fréquence des bacs.
André Chalella
1
Bonne réponse, merci! Désolé que je sois un peu en retard à la fête, mais peut-être pourriez-vous me répondre de quelle unité la magnitude de la fréquence (comme vous l'avez mentionné au point 1) est, en général? Dans mon cas, sur un signal de valeurs d'un accéléromètre (soit m / s ^ 2). Je ne peux pas tout à fait comprendre.
Markus Wüstenberg
Fascinant! Mes barres de fréquence de visualisation musicale sortaient toutes en miroir de gauche à droite; La réponse n ° 2 explique cela !! Fou!!
Ryan S
11

Vous avez déjà de bonnes réponses, mais j'ajouterai simplement que vous devez vraiment appliquer une fonction de fenêtre à vos données de domaine temporel avant la FFT, sinon vous obtiendrez des artefacts désagréables dans votre spectre, en raison d'une fuite spectrale .

Paul R
la source
J'apprécie que beaucoup de temps s'est écoulé depuis cette réponse. Cependant, seriez-vous en mesure de préciser de quel type d'artefacts vous parlez?
MattHusz
1
@MattHusz: le terme général pour l'origine de ces artefacts est «fuite spectrale» - j'ai ajouté un lien vers la réponse maintenant qui explique cela. La meilleure façon pour moi de décrire l'effet est que votre spectre sera "taché" en raison de la fenêtre rectangulaire implicite.
Paul R
6

1) Recherchez les indices dans le tableau réel avec les valeurs les plus élevées, en plus du premier (c'est le composant DC). Vous aurez probablement besoin d'une fréquence d'échantillonnage considérablement supérieure à 32 Hz et d'une taille de fenêtre plus grande pour obtenir des résultats significatifs.

2) La seconde moitié des deux tableaux est le miroir de la première moitié. Par exemple, notez que le dernier élément du tableau réel (1.774) est le même que le deuxième élément (1.774), et le dernier élément du tableau imaginaire (1.474) est le négatif du deuxième élément.

3) La fréquence maximale que vous pouvez capter à une fréquence d'échantillonnage de 32 Hz est de 16 Hz ( limite de Nyquist ), donc chaque pas est de 2 Hz. Comme indiqué précédemment, rappelez-vous que le premier élément est de 0 Hz (c'est-à-dire le décalage CC).

4) Bien sûr, une amplitude négative est parfaitement logique. Cela signifie simplement que le signal est "retourné" - une FFT standard est basée sur un cosinus, qui a normalement la valeur = 1 à t = 0, donc un signal qui avait la valeur = -1 au temps = 0 aurait une amplitude négative .

duskwuff -inactif-
la source
Merci pour la réponse. (1) Voulez-vous dire que je peux ignorer le tableau imaginaire (sinusoïdal), et si oui, pourquoi? Sûrement la composante sinusoïdale doit être importante? (2) Pourquoi cette mise en miroir se produit-elle? Est-ce juste le résultat de l'algorithme FFT? La plupart des gens ignorent-ils la moitié en miroir? (3) Comment avez-vous calculé les pas de 2Hz? Je comprends la limite de Nyquist de 16 Hz, donc s'il y a 16 éléments de tableau (non en miroir), chaque élément doit être de 16 Hz / 16 = 1 Hz chacun? (4) Pour trouver les fréquences principales, est-ce que je prends simplement la valeur absolue des valeurs d'amplitude dans les tableaux de sortie?
stackoverflowuser2010
Vous ne devriez pas chercher dans le tableau réel la valeur la plus élevée et vous ne pouvez pas ignorer le tableau sinus / I. Au lieu de cela, vous voulez la magnitude du vecteur complexe composite. La mise en miroir se produit parce que la moitié de l'entrée (le tableau I) est entièrement composée de zéros, le résultat a donc la moitié des degrés de liberté. Vous pouvez l'ignorer si vos données sont strictement réelles.
hotpaw2
@duskwuff Merci beaucoup: vous avez donné une réponse à une question que j'allais poster, si je n'avais pas trouvé votre réponse: comment interpréter la SECONDE partie de la FFT. Je veux modifier les données et effectuer l'inverse et je n'ai continué à obtenir que la moitié des résultats, car j'ai modifié les mauvaises données dans cette partie. Merci encore.
Martin
(3), la valeur de step = 2Hz me reste implicite jusqu'à présent. Nous avons 16 bacs, représentés par un tableau de longueur = 16. Nous devons décrire toutes les fréquences de 0 Hz à 16 Hz. Je suppose que chaque bac décrit un morceau de cette gamme, n'est-ce pas?
krafter
@krafter Je pense que c'est divisé par deux car vous ne pouvez pas déduire une fréquence à partir d'une seule valeur (car il n'y a pas de répétition).
JVE999
5

Notez que la «fréquence la plus fréquente» peut être éclaboussée dans plusieurs bacs FFT, même avec une fonction de fenêtre. Vous devrez donc peut-être utiliser une fenêtre plus longue, plusieurs fenêtres ou une interpolation pour mieux estimer la fréquence de tout pic spectral.

hotpaw2
la source