Exploitation d'une transformée de Fourier sur un signal réel

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous !

Avant tout, j'ai longtemps hésité entre poster ici et dans la catégorie programmation, mais je pense que mon problème est plus une incompréhension de phénomènes physiques que de programmation.

Mon problème est le suivant : je ne comprends pas ce que me renvoie la fonction fft du module numpy.fft. En effet, lorsque j'applique le code suivant :

1
2
3
4
5
6
7
8
9
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,100,10000)
y = np.fft.fft(np.sin(50*x))

plt.figure('Tracé des résultats')
plt.plot(x,y)
plt.show()

J'obtiens deux pics, respectivement à environ 7,61 Hz et à environ 92.39. Le premier était prévisible, puisqu'on a :

$$f_0 = \frac{\omega_0}{2\pi}=\frac{50}{2\pi}\approx7,96$$

Et, de ce que j'ai compris, la deuxième est due au phénomène de repliement.

En revanche, en multipliant le nombre de points par 10, je divise par 10 la fréquence de mon premier pic également… Pourquoi donc ?

De ce que je connais : - Ma fréquence d'échantillonnage est bien au moins deux fois supérieure à la fréquence de mon signal (Théorème de Shannon) - L'algorithme de la FFT rajoute de lui-même des valeurs afin d'obtenir un nombre de points égal à une puissance de deux - Le phénomène de repliement explique la possible symétrie apparente

Mais je ne vois pas en quoi ces trois données m'indiquent que ma fréquence se retrouve divisée par 10…

L'objectif étant par la suite de travailler sur des signaux plus complexes, j'aimerais comprendre le fonctionnement précis de la fft :/

Merci d'avance,

BunshinKage

+0 -0

Salut,

Comme le dit Aabu, c'est juste que ce que tu mets sur ton axe des abscisses n'a aucun sens. Tu mets l'espace direct au lieu de mettre l'espace réciproque, donc forcément lorsque tu augmentes la fréquence d’échantillonnage, tu contractes artificiellement le spectre que tu obtiens.

Essaye cela plutôt (voir la documentation) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,100,10000)
y = np.fft.fft(np.sin(50*x))

freq = 100 * np.fft.fftfreq(x.shape[0])

plt.plot(freq, y.real)
plt.show()

Avec ça, déjà tu as bien les fréquences en abscisses, et ensuite tu as tes deux pics à $\pm\dfrac{\omega}{2\pi}$ (et cette fois, c'est pas à 0.3 près à cause d'un malencontreux coup de bol ^^ ).

D'accord, merci pour vos réponses !

Par contre, ce que je ne comprends pas, c'est la différence entre numpy.fft.fft et numpy.fft.fftfreq. Je veux dire, dans mon esprit, l'algorithme de fft renvoie déjà quelque chose qui est fonction des fréquences… Plus exactement, quelle est l'utilité de numpy.fft.fft dans ce cas ?

+0 -0

En fait, une FFT se fait sur une liste de nombre. L'algorithme ne sait pas que ta fonction est sin(x) ou autre. Il voit simplement une liste de nombres, et te renvoie une autre liste de nombres à partir de celle-ci. Il n'y a pas de notion de temps dans une FFT, mais seulement de séquence (une liste). C'est ce que renvoie np.fft.fft.

Il y a cependant moyen de recalculer la fréquence associée à la liste des valeurs de la FFT à partir du signal temporel. C'est ce que fait np.fft.fftfreq. C'est très lié à la fréquence d'échantillonnage du signal.

Pour ce qui est de ta « symétrie apparente » : elle n'est pas apparente. Un spectre qui sort d'une FFT est toujours symétrique. On n'en visualise donc en général que la moitié.

+0 -0

Je veux dire, dans mon esprit, l'algorithme de fft renvoie déjà quelque chose qui est fonction des fréquences…

Oui, et c'est bien pour ça qu'il faut la représenter en fonction des fréquences (qui sont pas forcément temporelles comme le dit Aabu) et non en fonction de l'espace de départ.

+0 -0

Je suis désolé, je comprends le principe, mais… ^^'

Je comprends qu'il est inutile de tracer ce que me renvoie np.fft.fft en fonction du temps, mais comment alors le représenter selon les fréquences ? Comment "réorganiser" le tableau ?

Il me semble que, mais c'est à prendre avec des pincettes, chaque valeur de ce que me renvoie np.fft.fft (disons par exemple la $i$-ème valeur) est l'amplitude de la fréquence $i\times f_e$, avec $f_e$ la fréquence d'échantillonnage c'est bien ça ?

En fait, mon objectif est de reprogrammer un FFT, mais il faudra bien que je la représente en fréquence, c'est pour ça que j'essaye au maximum de définir un lien entre np.fft.fft et np.fft.fftfreq.

+0 -0

Si tu veux reprogrammer une FFT, tu auras plus vite fait de prendre un cours de traitement du signal. Ce n'est pas que c'est impossible de rétroingénierer ça, mais juste que partir de la définition de la transformée de Fourier discrète d'un signal échantillonné est plus… direct.

Il doit y avoir des choses sur Wikipedia ou ailleurs.

Je ne suis pas dans l'optique "Réinventons la FFT" mais plutôt "Je veux le coder par moi-même" en fait :p

Qu'est-ce que tu entends par "partir de la définition de la transformée de Fourier discrète d'un signal" ? Il est plus simple de représenter en fréquence après un algorithme de TFD ? Ils ne sont pas équivalents du point de vue des résultats ?

Je comprends qu'il est inutile de tracer ce que me renvoie np.fft.fft en fonction du temps, mais comment alors le représenter selon les fréquences ?

Ben ça, c'est ce que j'ai montré dans mon premier message…

Qu'est-ce que tu entends par "partir de la définition de la transformée de Fourier discrète d'un signal" ? Il est plus simple de représenter en fréquence après un algorithme de TFD ? Ils ne sont pas équivalents du point de vue des résultats ?

Une FFT, fondamentalement c'est une TFD. D'un point de vue mathématique c'est (presque) strictement équivalent (je dis presque parce que l'algèbre des nombres flottants utilisés par un ordinateur est un peu particulière).

+0 -0

Je comprends qu'il est inutile de tracer ce que me renvoie np.fft.fft en fonction du temps, mais comment alors le représenter selon les fréquences ?

Ben ça, c'est ce que j'ai montré dans mon premier message…

Oh, Mea culpa, j'avais mal vu :/ Je croyais que tu traçais ce que te renvoyais np.fft.fftfreq, donc j'avais mal compris aussi son fonctionnement ^^'

Merci beaucoup à vous deux !

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte