9. Transformation de Fourier Discrète
Des mathématiques pour "débruiter" un signal ...
Échauffement
On rappelle
Quelques valeurs remarquables de trigonométrie :
La formule d'Euler :
Le formule de Moivre :
Exercice
Soit .
Calculer .
Exercices de 1 à 3 page 300
Racines de unité
On cherche à résoudre dans l'équation , c'est à dire "trouver les racines de l'unité".
Pour , l'équation possède solutions : et soit et
Pour , l'équation possède solutions : , , et soit , , , .
Cas :
On cherche tel que . En écrivant , il vient . Ainsi il faut pour le réel , et pour avec . Ainsi les solutions sont avec .
Cas général :
Les solutions complexes de l'équation sont les nombres complexes : pour de à . En notant , ces solutions sont les puissances de , de à : . On les appelles les racines nième de l'unité.
Exercice
Déterminer les racines sixièmes de l'unité et les représenter dans le plan complexe.
En remarquant la somme de termes consécutifs d'une suite géométrique, démontrer que si est une racine sixième de l'unité, alors .
Transformée de Fourier Discrète
Définition
Exemple : TFD pour n = 3
La transformée de Fourier Discrète consiste à obtenir à partir d'une séquence de 3 nombres complexes une séquence de 3 nouveaux nombres complexes . On procède de la façon suivante :
On pose , et alors :
Remarque : on a
Exemple corrigé :
Calculer la transformée de Fourier Discrète : TFD(2, 0, 1)
a) Écrire la matrice b) Calculer c) Que retrouve-ton ?




Cas général
Pour , on pose .
Avec
Exercice
Donner la forme algébrique de .
Calculer la
Vérifier par le calcul matriciel
Exercices : À la main : , , , , Avec une calculatrice :
Travaux pratiques
Pour coder du Python en ligne, on utilisera https://repl.it/ Pour effectuer des calculs formels en ligne, on utilisera https://www.xcasenligne.fr/ sous Firefox

TP 1 : Xcas, Python et propriétés de la TFD
La Transformée de Fourier Discrète en PYTHON
Le package cmath permet d'effectuer des calculs avec les nombres complexes. Le nombre complexe est codé par
1j
. Essayez !
from cmath import *
print(1j)
print((1j)**2)
print((2-3j)*(-1+2j))
print(e**(1j*pi/2))
print((sqrt(2)/2+sqrt(2)*1j/2)**2)
2. Recopier et compléter le programme suivant. La procédure TFD doit calculer la Transformée de Fourier Discrète de la séquence .
from cmath import *
def tfd(x): # x est un tableau [a, b, ..., c]
n = len(x) # nombre d'éléments du tableau
X = []
w = exp(2*pi*1j/n)
for i in range(n): # i = 0 à n-1
Xi = 0
for j in range(n):
Xi = Xi +x[j]*...
X.append(...) # Ajoute un élément au tableau X
return X
print(tfd([1,2,3]))
Vérifier en comparant les résultats du programme avec ceux obtenus par Xcas pour différentes séquences comme ici pour TFD(1,2,3) :


Les propriétés de la TDF
Avec Xcas comparer :
4*fft(1,-0.5) et fft(1,-0.5)
fft(1,-1,2)+fft(2,1,-1) et fft(3,0,1)
Comment écrire fft(1,0,0)+2fft(0,1,0)+3fft(0,0,1) en une seule commande fft ? Cette propriété s'appelle linéarité de la TFD.
La formule de Bessel
Pour on a
Nous allons vérifier cette propriété à l'aide de programmes PYTHON. Recopiez ce programme, analysez-le et utilisez-le avec la procédure TFD pour vérifier cette formule pour la séquence [1 ; 2 ; 3 ]. Essayez avec d'autres séquences.
def somme_des_carrés(x):
S = 0
for xi in x:
S = S + abs(xi)**2
return S
print(somme_des_carrés([1,2,3]))
La transformée de Fourier Discrète Inverse
Pour , on peut retrouver à partir de en utilisant la transformée inverse donnée par la formule (avec ) :
Les moins en exposant ont disparu et il est apparu un facteur .
Étudiez ce petit programme. Que permet-il de faire ?
liste1 = [1, 2, 3, 4]
liste2 = [element/2 for element in liste1]
print(liste1)
print(liste2)
En copiant et modifiant le programme tfd, codez le programme tfd_inv et vérifiez qu'il fonctionne bien avec la séquence [1, 2, 3]. Essayez avec d'autres séquences.
def tfd_inv(X):
n = len(X)
x = []
w = ...
for i in range(n):
xi = 0;
for j in range(n):
xi = xi + ...
x.append(xi)
x = [xi/... for xi in x]
return x
print(tfd_inv(tfd([1,2,3])))
TP2 : Débruiter un signal
Comment passer de ça à ça ?

A - Définir un signal, l'échantillonner, le représenter
Un signal sinusoïdal de fréquence est défini par
Pour échantillonner ce signal sur 1 seconde à une fréquence , on prend 1000 abscisses également espacées de l'intervalle , pour lesquelles on récupère les images par le signal .
1. Taper dans la console repl.it la commande linspace(0, 0.999, 1000)
2. La commande
def s(t):
return sin(2*pi*t)
permet de définir un signal de fréquence 1.
Copier-coller le programme ci-dessous et le compléter pour qu'il représente un signal sinusoïdal de fréquence 15 hertz, sur 1 seconde, échantillonné à 1000 Hertz :
(le fichier signal.png contiendra la représentation attendue : l'ouvrir après l'exécution du programme)
import os
os.environ['MPLCONFIGDIR'] = os.getcwd() + "/configs/"
from matplotlib.pyplot import *
from numpy import *
l = ... # Longueur du signal (secondes)
Fe = ... # Freq échantillonage
Te = 1/Fe # Période échantillonage
N = int(l*Fe) # Nombre d'échantillons
# signal à échantillonner
def s(t):
return ...
# variable t sur [0, l-Te] au pas l/N
t = linspace(0, l-Te, N)
''' Signal '''
fig = figure()
plot(t, s(t), label='Signal')
legend(loc='upper center', shadow=True, fontsize='x-small')
title("Signal")
xlabel("Temps")
fig.savefig('signal.png')
B - Transformée de Fourier Discrète d'un signal
En PYTHON, à l'aide du package numpy, on peut calculer la transformée de Fourier discrète d'une séquence : fft.fft([1,2,3])
Essayez dans repl.it en ayant chargé le package numpy :
from numpy import *
Obtenir le spectre des fréquences d'un signal consiste à
échantillonner ce signal
calculer la transformée de Fourier discrète de cet échantillon
représenter la séquence obtenue
Utiliser le programme suivant pour obtenir le spectre des fréquences du signal .
import os
os.environ['MPLCONFIGDIR'] = os.getcwd() + "/configs/"
from matplotlib.pyplot import *
from numpy import *
l = 0.6 # Longueur du signal (secondes)
Fe = 1000.0 # Freq échantillonnage
Te = 1/Fe # Période échantillonnage
N = int(l*Fe) # Nombre d'échantillons
# signal à échantillonner
def s(t):
return sin(2*pi*40*t) + .5*sin(2*pi*90*t+pi/4) + .7*sin(2*pi*120*t-pi/2)
# variable t sur [0, l-Te] au pas l/N
t = linspace(0, l-Te, N)
# On ne garde que la moitié des points (symétrie)
N1 = floor(N/2);
# Fréquences en abscisse
fr = linspace(0, int(N1 -1), int(N1))*Fe/N
''' Spectre du signal '''
y = fft.fft(s(t)) # TFD du signal
fig = figure()
plot(fr[0:int(N1 -1)], abs(y[0:int(N1 -1)]))
title("Spectre des fréquences du signal")
xlabel("Fréquences")
fig.savefig('spectre-signal.png')
Expliquer le spectre des fréquences obtenu :
quelles fréquences contient ce spectre ?
où retrouve-t-on ces fréquences dans le signal ?
comment expliquer les différences d'amplitude d'une fréquence à une autre dans le spectre ?
quel est l'effet sur le spectre des déphasages et dans les composantes du signal ?
C - Bruitage d'un signal
On souhaite maintenant "bruiter" un signal et obtenir un spectre de fréquences comme celui-ci :

Notre signal de départ est le suivant :
La commande random.normal(0, 1, N)
fournit une séquence aléatoire de N nombres distribués selon la loi normale.
Essayez-la dans la console sans oublier le package numpy.
Copier-coller et compléter le programme suivant pour qu'il affiche le spectre du signal bruité. Pour bruiter le signal, on ajoutera cette séquence aléatoire au signal initial.
import os
os.environ['MPLCONFIGDIR'] = os.getcwd() + "/configs/"
from matplotlib.pyplot import *
from numpy import *
l = 0.6 # Longueur du signal (secondes)
Fe = 1000.0 # Freq échantillonnage
Te = 1/Fe # Période échantillonnage
N = int(l*Fe) # Nombre d'échantillons
# signal à échantillonner
def s(t):
return ...
# variable t sur [0, l-Te] au pas l/N
t = linspace(0, l-Te, N)
# On ne garde que la moitié des points (symétrie)
N1 = floor(N/2);
# Fréquences en abscisse
fr = linspace(0, int(N1 -1), int(N1))*Fe/N
''' Spectre du signal bruité '''
fig = figure()
sb = s(t) + ... # bruitage du signal
yb = ... # TFD du signal bruité
plot(fr[0:int(N1 -1)], abs(yb[0:int(N1 -1)]))
title("Spectre des fréquences du signal bruité")
xlabel("Fréquences")
fig.savefig('spectre-signal-bruité.png')
D - Débruitage du signal
Travail préparatoire : copier-coller le code suivant et répondre aux questions :
from numpy import *
# Que fait zeros ?
l1 = zeros(shape= 5)
print('l1')
print(l1)
print()
# random.normal(0, 1, 5) fournit une séquence aléatoire
l2 = random.normal(0, 1, 5)
print('l2')
print(l2)
print()
# Que fait abs ?
l3 = zeros(shape= 5)
for k in range(l3.size):
l3[k] = abs(l2[k])
print('l3')
print(l3)
print()
# Expliquez le résultat
l4 = zeros(shape= 5)
for k in range(l4.size):
l4[k] = (abs(l2[k]) > 0.7)
print('l4')
print(l4)
print()
# Expliquez le résultat
l5 = zeros(shape= 5)
for k in range(l5.size):
l5[k] = l2[k]*(abs(l2[k]) > 0.7)
print('l5')
print(l5)
print()
Le principe du "débruitage" d'un signal, consiste à ne garder que les fréquences du spectre supérieures à un certain seuil (fixé ici à 55). À l'aide des instructions découvertes précédemment, copiez et complétez le programme suivant. Il doit afficher le spectre des fréquences du signal débruité. :
import os
os.environ['MPLCONFIGDIR'] = os.getcwd() + "/configs/"
from ... import *
from ... import *
l = 0.6 # Longueur du signal (secondes)
Fe = 1000.0 # Freq échantillonnage
Te = 1/Fe # Période échantillonnage
N = int(l*Fe) # Nombre d'échantillons
# signal à échantillonner
def s(t):
return sin(2*pi*40*t) + sin(2*pi*90*t+pi/4)
# variable t sur [0, l-Te] au pas l/N
t = linspace(0, l-Te, N)
# On ne garde que la moitié des points (symétrie)
N1 = floor(N/2);
# Fréquences en abscisse
fr = linspace(0, int(N1 -1), int(N1))*Fe/N
# bruitage du signal
sb = s(t) + random.normal(0, 1, N)
# TDF du signal bruité
yb = fft.fft(sb)
''' Spectre du signal débruité '''
fig = figure()
# débruitage
seuil = 55
y_debruite = zeros(shape=(yb.size), dtype=clongdouble)
for k in range(...):
y_debruite[k]=(yb[k])*...
plot(fr[0:int(N1 -1)], abs(y_debruite[0:int(N1 -1)]))
title("Spectre des fréquences du signal débruité")
xlabel("Fréquences")
fig.savefig('spectre-signal-débruité.png')
La commande ifft
permet de calculer la Transformée de Fourier Discrète Inverse. Ajouter ces lignes de code en fin de programme. Exécuter-le plusieurs fois. Que fait-il ?
''' ? '''
s_debruite = real(fft.ifft(y_debruite))
fig2 = figure()
plot(t, s(t), label='Signal pur')
plot(t, s_debruite, ':', label='Signal débruité')
legend(loc='upper center', shadow=True, fontsize='x-small')
title("?")
xlabel("Temps")
fig2.savefig('what-is-it.png')
Last updated
Was this helpful?