Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE...

41
Analyse spectrale Application à l’échographie Doppler Projet de TE Du 7 au 11 juin 2004 LANTY Gaëtan LE GALL Julien PIERRE Mathieu

Transcript of Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE...

Page 1: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Analyse spectrale Application à

l’échographie Doppler Projet de TE

Du 7 au 11 juin 2004 LANTY Gaëtan

LE GALL Julien PIERRE Mathieu

Page 2: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Sommaire Introduction 1- Objectifs du TE 2- Principe de l’analyse 3- Structure globale du projet

Traitement informatique du problème I- Représentation informatique des données 1- Type des variables numériques 2- Acquisition des données 3- Stockage des résultats des calculs

II- Analyse du signal 1- Algorithme de FFT 2- Codage de l’algorithme 3- Application à l’analyse temps-fréquence III- Visualisation des résultats par une image 1- Choix du format de représentation 2- Constitution d’un Bitmap 3- La fonction créer_bmp Interface graphique I- Principales caractéristiques de la programmation Windows 1- Windows, un système multitâche 2- Existence des handle 3- Comment programmer sous Windows ?

Page 3: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

II- Constitution d’un programme 1- Initialisation du programme 2- Création d’une fenêtre 3- Gestion des messages 4- Affichage graphique III- Présentation du déroulement de l’application 1- Les différentes fenêtres 2- Sécurité du programme 3- Quelques observations sur le code Traitement des signaux I- Les différentes fonctions de traitement des résultats 1- La fonction prend_log 2- La fonction de normalisation 3- Les fonctions de mise en forme de l’image 4- Les fonctions moyenne et écart_type II- Influence des paramètres fixés par l’utilisateur 1- La forme de la fenêtre : phénomène de "ringing" 2- La largeur de la fenêtre 3- Le décalage III- Application à l’échographie Doppler 1- Analyse des signaux réels 2- Interprétation des résultats Conclusion Annexe : ensemble du code

Page 4: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Introduction. 1- Objectifs du TE.

L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par échographie doppler. Plus précisément, il s’agit de vélocimétrie ultrasonore, utilisée pour le diagnostic des pathologies cardiovasculaires. Celui-ci repose principalement sur l’imagerie des flux sanguins dont les altérations traduisent les répercutions de la sténose, c’est-à-dire le rétrécissement du diamètre artériel dû à une plaque athéromateuse. L’imagerie ultrasonore possède quelques avantages : c’est un outil non-invasif qui est relativement bon marché et léger en terme d’instrumentation. 2- Principe de l’analyse.

Son principe est, de plus, assez simple. Un transducteur ultrasonore émet une onde monochromatique à la fréquence f0 qui se propage dans le milieu à analyser jusqu’aux hématies en mouvement. Une partie de l’onde est rétrodiffusée : chaque hématie, en mouvement, réfléchit une onde monochromatique dont la fréquence est modifiée par le décalage doppler δf, qui est proportionnel à la vitesse longitudinale (c’est à dire la vitesse selon la direction de l’onde ultrasonore) de l’hématie. Un second transducteur capte l’onde réfléchie et délivre un signal électrique, amplifié, démodulé (pour se débarrasser de la porteuse f0), et échantillonné.

Son contenu spectral renseigne sur la vitesse des hématies. Cependant, l’onde captée correspond à la superposition des ondes réfléchies par les hématies, qui ont chacune une vitesse propre. On doit donc s’intéresser au spectre du signal reçu, qui représente la répartition des vitesses dans la zone insonifiée. De plus, les vitesses des hématies varient au cours du cycle cardiaque. Nous avons donc à effectuer une analyse temps-fréquence, c’est-à-dire étudier la variation du spectre du signal au cours du temps. Cette analyse permet donc d’avoir une image de l’évolution des vitesses des hématies au cours du cycle cardiaque. 3- Structure globale du projet.

Le projet se compose essentiellement en deux parties. D’une part, nous avons écrit des fonctions permettant d’analyser le signal, et d’enregistrer les résultats. D’autre part, nous avons travaillé à la réalisation d’une interface graphique Windows, qui rend l’utilisation du programme très agréable. Au niveau du code source, nous avons un fichier .c qui contient la fonction Winmain et les fonctions qui gèrent l’interface graphique. En tête de celui-ci, nous avons inclus les bibliothèques nécessaires et un fichier .h, qui contient les prototypes et le corps des fonctions d’analyses appelées par le Winmain. Pendant la semaine, nous avons d’abord testé nos fonctions d’analyse en mode console, avant de les incorporer, non sans quelques adaptations, à l’interface graphique.

La première partie du rapport présente le traitement informatique de l’analyse du signal. La deuxième partie présente l’interface graphique, ainsi que le cycle de fonctionnement du programme. La troisième partie est consacrée à l’interprétation des résultats des différentes analyses.

Page 5: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Traitement informatique du problème.

La partie principale du projet est l’analyse du signal. Elle nécessite plusieurs opérations, qui définissent les différentes fonctions que nous avons écrites. En voici la liste :

- acquisition du signal à analyser - détermination des paramètres de l’analyse - analyse fenêtrée (en boucle)

- extraction d’une fenêtre (porte ou gaussienne) - calcul de la FFT associée à cette fenêtre - prise du carré du module de la FFT que divise la largeur de la fenêtre - mettre la fréquence nulle au centre de l’image (en option)

- application de diverses transformations au résultat (en option) - statistiques des résultats - enregistrement et visualisation des résultats sous forme d’image bitmap.

I- Représentation informatique des données. 1- Type des variables numériques.

Au cours de ces manipulations, nous travaillons avec divers signaux. Il a donc fallu commencer par faire des choix sur le mode de représentation des données, en fonction des fichiers fournis et de ce que nous en faisons.

Les signaux sont fournis en format Ascii. A chaque ligne, un point du signal est représenté par sa partie réelle et sa partie imaginaire. Nous avons donc créé une structure pour représenter les nombres complexes. Elle contient deux champs, real et imag, qui sont tous deux des double. Nous avons utilisé ce type de nombre rationnel, car les fonctions de la bibliothèque math.h, dont nous avons besoin au cours du calcul de la FFT, l’utilisent.

2- Acquisition des données. L’acquisition des données se fait en deux temps. Lors de la première lecture du fichier

spécifié, nous comptons le nombre de points du signal, afin d’allouer un tableau contenant le signal de la bonne taille. Puis nous remettons le pointeur de fichier au début de celui avec la fonction rewind, et nous remplissons le tableau avec les points du signal. Le code que nous avons écrit est robuste : il ignore les lignes laissées vides, par exemple celles à la fin des fichiers. Nous avons en effet utilisé la fonction fscanf(fichier," %lg %lg " ,…) : la présence des espaces dans la chaîne de format provoque l’ignorance des caractères de séparation.

3- Stockage des résultats des calculs.

La plupart de nos fonctions manipulent des tableaux de nombres, soit des complexes, soit des réels de type double. Ils sont tous alloués dynamiquement à l’intérieur du corps des fonctions chargées de les créer, et ces fonctions retournent des pointeurs sur les tableaux

Page 6: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

créés. D’une manière générale, tous les tableaux sont passés aux fonctions par le passage en argument d’un pointeur sur ces tableaux. Ainsi, pour une plus grande clarté du code, toutes les fonctions sont construites sur le même modèle. Le résultat du calcul de l’analyse temps-fréquence est un tableau à deux dimensions : en fait, il s’agit d’un tableau de pointeurs vers les tableaux monodimensionnels calculés par la FFT de chaque fenêtre. A ce sujet, nous avons d’abord hésité entre deux possibilités. En effet, si nous demandons une analyse sur trop de points, la mémoire est trop petite pour contenir cette matrice de résultat. Nous avions envisagé de stocker successivement les résultats dans un fichier binaire après l’analyse de chaque fenêtre. Mais il nous a ensuite semblé peu pertinent de créer une image de 10 000 pixels de large sur 1024 pixels de haut, valeurs qui correspondent à un décalage de un point entre chaque fenêtre analysée avec les signaux fournis.

II- Analyse du signal. 1- Algorithme de FFT.

Pour étudier le contenu fréquentiel du signal, nous utilisons la transformée de Fourier. Le signal est à temps discret, il est fini dans le temps, et, nous ne pouvons calculer numériquement cette transformée que pour un nombre fini de valeurs de la fréquence, donc nous utilisons la transformée de Fourier discrète. Si (xn)n=0,…,N-1 est le signal à analyser, la transformée discrète est obtenue par

∑−

=

−=1

0

/2)()(N

n

MnmjenxmX π

pour m=0,…,M-1. Mm est la fréquence

réduite : la fréquence est FeMm où Fe est la fréquence d’échantillonnage su signal.

Dans le cas où M=N, il faut donc effectuer N² multiplications pour calculer cette transformée. Des algorithmes de Transformée de Fourier Rapide (ou FFT pour Fast Fourier Transform) permettent de réduire ce nombre de multiplications. En pratique, nous avons donc utilisé l’algorithme de Cooley-Tuckey, qui réduit le nombre de multiplications à N log2(N). Il impose que N soit une puissance de 2. On pose N=M=2P. On a

∑∑−

=

−−−

=

− ++=1

0

/2/21

0

/2 )12()2()(P

p

PpmjMmjP

p

Ppmj epxepxmX e πππ

On constate qu’on se ramène à deux transformées de Fourier discrète, qui contiennent moitié

moins de points, et qui agissent l’une sur les termes d’indice pair du signal, et l’autre sur les

termes d’indice impair du signal. On a .Des propriétés

permettent de réduire le nombre de calculs : X+(m+P)=X+(m) et X-(m+P)=X-(m).

)()()( /2 mXmXmX e Mmj−

−+ += π

Page 7: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

2- Codage de l’algorithme.

Cet algorithme se présente donc sous forme récursive, et donc nous avons tout naturellement choisi d’utiliser une fonction fft récursive pour le coder. Afin de ne pas saturer la pile, puisque cette fonction va s’appeler un grand nombre de fois, nous avons veillé à ne pas déclarer trop de variables locales. Les tableaux sont ainsi alloués dynamiquement. On peut d’ailleurs noter que cela était de toute façon nécessaire puisque leur taille dépend de la longueur du signal à analyser. Cette fonction prend en argument un pointeur sur le tableau qui contient le signal à transformer et le nombre de points de ce signal, qui doit impérativement être une puissance de 2. Lors de l’appel à cette fonction, un tableau de la taille du nombre de points du signal est alloué dynamiquement : il est destiné à contenir le résultat du calcul et la fonction fft retourne un pointeur sur ce tableau. La fonction sépare les termes pairs et impairs et s’appelle pour calculer les transformées X+ et X-. A partir du résultat de ces calculs, elle applique la formule précédente. Enfin, elle libère la mémoire allouée, et retourne le pointeur sur le tableau de résultat. De plus, pour mettre fin à la récurrence, quand le signal a transformer ne contient qu’un point, le calcul est effectué directement : on a X(0)=x(0). Le nombre π est défini en entête du programme avec une vingtaine de décimale, pour assurer la précision des calculs. Utilisée avec un signal sinusoïdal, cette fonction a produit les résultats attendus. 3- Application à l’analyse temps-fréquence.

Pour réaliser l'analyse temps-fréquence, on sélectionne une partie du signal à l’aide d’une fenêtre et l’on en prend la FFT. On a plusieurs degrés de liberté dans ce découpage : l'utilisateur peut fixer la largeur de chaque fenêtre et le décalage de la fenêtre entre chaque analyse. On commence par calculer le nombre de fenêtres que nous aurons à calculer. Au maximum, nous aurons nb_points/décalage+1 fenêtres (division entière). Il faut ensuite vérifier que la dernière fenêtre ne dépasse pas du signal. Pour ce faire, on décrémente le nombre de fenêtres tant que c'est le cas.

Ensuite, pour chaque fenêtre, on extrait la séquence de points à analyser. L'utilisateur a deux possibilités, dont les influences seront étudiées plus loin : la fenêtre peut être rectangulaire ou bien gaussienne. On complète la séquence de points par des zéros jusqu'à atteindre le nombre de points souhaité pour l'analyse, qui doit être une puissance de 2. Ce « bourrage de zéro » ne modifie pas la transformée à calculer, et est nécessaire dans la mesure où la largeur de fenêtre choisie n’est pas obligatoirement une puissance de deux. L’utilisateur peut fixer la précision qu’il souhaite en fréquence indépendamment de la largeur de fenêtre optimale pour l’analyse. Puis, en option, on peut appliquer la fonction fftshift. III- Visualisation des résultats par une image. 1- Choix du format de représentation.

L’analyse temps-fréquence nous fournit un spectrogramme. Pour afficher celui-ci, qui est à deux dimensions, nous utilisons une image en niveau de gris. Chaque point du calcul correspond à un pixel, et la couleur de celui-ci code le résultat de l’analyse en ce point. Nous avons opté pour une image Bitmap. En effet, ce type d’image est très facile à réaliser puisque le fichier contient directement la couleur de chacun des pixels.

Page 8: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

2- Constitution d’un bitmap.

Une image Bitmap est constituée de trois parties : - une entête, qui contient des informations générales sur l’image, et qui se compose de

l’entête du fichier puis de l’entête du Bitmap - une palette de couleurs (cette palette est parfois optionnelle, mais étant donné que

nous avons choisi 256 couleurs, elle est nécessaire) - les données de l’image.

Voici le détail de l’entête : Adresse (en héxa) Taille (en octets) Contenu

00 2 Caractère B ($42) et M ($4D) 02 4 Taille du fichier (en octets) 06 4 Réservé : toujours à 0 0A 4 Adresse du début des données image 0E 4 Taille de l’entête (en octets) : $40=54 octets 12 4 Largeur de l’image (en pixels) 16 4 Hauteur de l’image (en pixels) 18 2 Nombre de plans utilisés 2A 2 Nombre de bits par pixel 2C 4 Méthode de compression 30 4 Taille des données image (en octets) 34 4 Résolution horizontale (en pixels par mètre) 38 4 Résolution verticale (en pixels par mètre) 3C 4 Nombre de couleurs utilisées 40 4 Nombre de couleurs affichées

Quelques paramètres sont des constantes : le nombre de plan utilisé est fixé à 1, la

méthode de compression est fixée à 0, ce qui indique que nous n’effectuons pas de compression, les résolutions horizontale et verticale sont fixées à 3780 pixels par mètre, et le nombre de couleurs affichées est à zéro, ce qui indique que toutes les couleurs de la palette sont susceptibles d’être affichées.

Les autres paramètres dépendent de notre application. Nous avons optés pour un affichage sur 256 couleurs : il y a donc un octet par pixel. La largeur de l’image est égale au nombre de fenêtres d’analyse et la hauteur de l’image est égale au nombre de points sur lequel nous calculons les FFT.

La palette de couleurs est constituée de blocs de quatre octets, un pour chaque couleur utilisée. Les quatre octets sont le niveau de bleu de la couleur, le niveau de vert de la couleur, le niveau de rouge de la couleur et un octet à zéro. Pour réaliser du gris, ces trois niveaux de couleurs sont choisis égaux. On obtient du blanc quand ces octets sont à 255, et du noir quand ces octets sont à 0. Dans les données image, l’octet représentant chaque point est le numéro de la couleur dans la palette.

Un détail supplémentaire est que chaque ligne de l’image doit comporter un nombre d’octets multiple de quatre. Il faut compléter par des octets à zéro quand la largeur de l’image n’est pas multiple de quatre. La taille des données image est donc égale à la hauteur de l’image multipliée par le plus petit multiple de quatre supérieur ou égal à la largeur de l’image. Pour calculer la taille du fichier, il suffit d’y ajouter la taille de l’entête et la taille de la palette, soit 1078 octets.

Page 9: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

3- La fonction créer_bmp.

Nous avons écrit la fonction creer_bmp qui prend en argument les dimensions de l’image, la matrice de données, et les informations qui permettent d’ouvrir la fenêtre « enregistrer sous », et qui retourne un code d’erreur. Concrètement, pour écrire les données, on utilise la fonction fwrite, et on écrit octet par octet, avec des entiers de type unsigned char. Pour les données de l’entête, représentées sur quatre octets, le premier octet est l’octet de poids faible. Avec des divisions successives par 256, et un transtypage de int en char, on isole chaque octet de ces nombres. On aurait d’ailleurs pu utiliser les opérateurs de décalage(<< et >>) et l’opération modulo 256, pour isoler la représentation en octets de ces données de type int.

On a choisi d’inverser l’ordre naturel de la palette. Ainsi, le code 0 correspond au blanc et le code 255 correspond au noir. On utilise deux fonctions qui calculent la plus grande et la plus petite des données. On leur attribue respectivement les couleurs noir et blanc, et on déduit les autres couleurs par une échelle linéaire.

Page 10: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Interface graphique. I- Principales caractéristiques de la programmation Windows. 1- Windows, un système multitâche.

Windows est un système multitâche. Si cela apporte un gain de confort à l’utilisateur, cela nécessite aussi une approche différente au niveau de la programmation. En effet, on passe d’une programmation séquentielle à une programmation événementielle.

Ainsi, plusieurs programmes sont présents en mémoire en même temps. Cela impose que l’espace mémoire alloué à chacun soit délimité de manière stricte par le système. Sans trop rentrer dans les détails, à un programme correspond un processus. Celui-ci contient ses données, sa pile, l’état des registres, et les différents threads le cas échéant. Le système gère à la fois la répartition de la mémoire (les processus sont, de ce point de vu là, isolés les uns des autres), et du temps machine (ce qui donne l’impression du multitâche).

Aussi, un programme ne peut avoir le contrôle exclusif ni des entrées (clavier, souris) ni des sorties (écran, imprimantes ou autres), ni même de la mémoire. Il est donc nécessaire que le système puisse recevoir ces informations, les traduire sous forme de messages et distribuer ceux-ci à qui de droit. 2- Existence des handle.

Windows représente par des objets chaque ressource (processus, fichier, fenêtre…) qu’il a à gérer. Lorsqu’une application ouvre une ressource, c’est le rôle du gestionnaire d’objets de déterminer l’objet associé ou d’en créer un nouveau, et de fournir un handle vers celui-ci. Chaque processus possède une table d’objets, un handle constituant un identificateur dans cette table.

Le fait que Windows soit multitâche implique qu’il soit capable de gérer des ressources utilisées par différents objets. Chaque objet (processus, thread, fichier, fenêtre…) reçoit un numéro (handle) qui servira à identifier l’objet. Ce n’est pas un pointeur au sens ou ce n’est pas une adresse mémoire, mais cela sert à repérer l’objet. En effet, chaque processus contient une table d’objets repérés par leur handle. 3- Comment programmer sous Windows ?

Microsoft nous fournit une API (Application Programming Interface), c'est-à-dire un ensemble de fonctions qui nous permet de programmer sous Windows. Ce sont elles que nous allons utiliser par la suite.

Page 11: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

II- Constitution d’un programme. 1- Initialisation du programme.

Le main d’un programme console est ici remplacé par int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) On peut détailler les paramètres :

• HINSTANCE hInstance : le handle de l’instance de notre programme. Comme on l’a expliqué plus haut, il sert à identifier le programme parmi les autres applications qui tournent en même temps.

• HINSTANCE hPrevInstance : était utilisé par les précédentes versions de Windows, gardé par soucis de compatibilité ascendante.

• LPSTR lpCmdLine : contient un pointeur vers les paramètres passés par la ligne de commande. On ne s’en servira pas.

• int nCmdShow : indique comment le programme doit être affiché au démarrage, on ne s’en servira pas. En fait, le lancement d’un programme Windows n’est pas chose aisée, mais cela est

entièrement géré par le système et transparent pour le programmeur. On remarque toutefois que notre programme est en quelque sorte considéré comme un objet « comme les autres » en ce sens qu’il possède un handle. 2- Création d’une fenêtre.

Les informations nécessaires à la création d’une fenêtre sont contenues dans la structure (bien que le terme « classe » soit ici plus approprié) WNDCLASS. Après avoir initialisé chacun des membres de celle-ci, il nous faut enregistrer notre fenêtre, en appelant la fonction RegisterClass.

Ensuite seulement, on peut créer à proprement parler la fenêtre, en appelant la fonction CreateWindow. Celle-ci nous renvoie un handle vers la fenêtre. 3- Gestion des messages.

Lors de chaque évènement, Windows génère un message qui est placé dans une pile « pour tout le système ». Ensuite, chaque message est aiguillé vers la pile (FIFO) de l’application correspondante. Dans une application typique, les messages sont lus en utilisant GetMessage, et aiguillés éventuellement vers le fenêtre adéquate par DispatchMessage. Ces deux instructions sont placées dans une boucle infinie dans le WinMain, et constituent la « boucle de Messages ».

Certains messages sont directement envoyés par Windows à la fenêtre adéquate, et d’autres ne respectent pas le FIFO.

De plus, les messages ne sont pas exclusivement un moyen de communiquer entre Windows et l’application : deux fenêtres peuvent les utiliser pour se passer des données.

Si l’on observe les membres de la structure WNDCLASS, on constate la présence de WNDPROC lpfnWndProc, un pointeur vers une fonction. Celle-ci a pour rôle de traiter les messages adressés à cette fenêtre, et sera appelée par DispatchMessage. Une boite de dialogue fonctionne de manière similaire.

Page 12: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

En fait, notre programme ne comporte pas explicitement de boucle de traitement de messages. En effet, la « fenêtre principale » est une boite de dialogue modale. Or Windows crée lui-même la boucle de message correspondant à celle-ci. Ainsi, lorsque l’on quitte la boite de dialogue principale, on quitte aussi le programme, de manière harmonieuse.

4- Affichage graphique.

Windows nous fourni, avec le GDI, un moyen d’afficher des graphiques dans la zone active d’une fenêtre. L’information sur la zone d’affichage est contenue dans une structure PAINTSTRUCT. Pour pouvoir manipuler une zone ou dessiner, on a besoin d’un handle, dit cette fois-ci « de contexte de périphérique ». Celui-ci est obtenu en faisant appel à la fonction BeginPaint. Celle-ci prépare la fenêtre à afficher une image, remplit notre structure avec les informations adéquates et renvoie un handle. On obtient un handle vers notre Bitmap (HBITMAP). Le GDI nous offre la fonction LoadImage. On obtient ensuite un handle vers une zone mémoire compatible avec l’affichage avec CreateCompatibleDC. Celle-ci sert à stocker les données en vue de les afficher. La fonction SelectObject permet de charger le Bitmap dans la surface mémoire. Ensuite, BitBlt permet de transférer le Bitmap vers la zone d’affichage. On effectue cela dès lors que Windows nous demande de redessiner la fenêtre (WM_PAINT ). III- Présentation du déroulement de l’application. 1- Les différentes fenêtres.

On a une fenêtre principale « Doppler », qui s’affiche lors du lancement de l’application. Elle permet de choisir une fonction. Elle est gérée par BOOL CALLBACK DialogProc(). Le programme vérifie si l’utilisateur ne fait pas une opération qui risquerait de générer une erreur (analyser un signal sans l’avoir préalablement chargé, par exemple), et affiche un message d’erreur adéquat le cas échéant.

Les chargements/enregistrements de fichiers sont gérés par les boites de dialogue classiques de Windows. Lorsque aucun signal n’est chargé, l’utilisateur ne peut qu’en charger un, toutes les autres possibilités menant à des messages d’erreur.

Le nom du fichier signal courant est affiché dans un contrôle EDIT bloqué.

Page 13: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

L’utilisateur peut alors demander à calculer la FFT, une boite de dialogue « Paramètres de l’analyse » gérée par BOOL CALLBACK DialogProc2() permettant de préciser les paramètres de l’analyse temps-fréquence, qui sont initialisés à des valeurs par défaut. Ensuite, on peut sauvegarder le fichier BMP correspondant à l’analyse temps-fréquence, puis l’afficher dans une fenêtre prévue à cet effet. 2- Sécurité du programme.

Dans les cycles de fonctionnement sont prévus des séquences d’erreur. Toutes les allocations dynamiques et toutes les ouvertures de fichier sont testées, et les fonctions qui en contiennent peuvent retourner un code d’erreur en cas d’échec. Ce code est généralement un pointeur à NULL ou bien un entier à 1. Ces codes déclenchent l’affichage de messages d’erreur et remettent l’exécution du programme à un endroit adéquat. 3- Quelques observations sur le code.

Le code actuel concernant l’interface graphique n’est pas encore tout à fait satisfaisant. En effet, le manque de connaissance sur les messages et la façon dont les fonctions de gestion des fenêtres et des boîtes de dialogue peuvent renvoyer des valeurs nous ont contraint à utiliser des variables globales, sans doute plus que de raison.

Nous n’avons pas encore pu incorporer à l’interface graphique toutes les options proposées pour l’analyse du signal. A ce stade, le bénéfice apporté par l’interface graphique n’est pas flagrant. Cependant, avec l’ensemble des options proposées, la facilité d’utilisation serait accrue, et la programmation événementielle serait tout à fait justifiée. L’utilisateur pourrait ainsi plus facilement choisir l’ordre d’exécution des différentes tâches du programme.

Enfin, quelques points restent à améliorer : la sauvegarde nécessaire de l’image sur le disque dur puis sa relecture pour l’affichage n’est clairement pas une démarche optimale.

Page 14: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Traitement des signaux.

Dans ce qui précède, nous nous sommes attachés à la rédaction d’un programme permettant une analyse temps-fréquence de signaux. Celui-ci génère un tableau de dimension deux nommé result. Cette analyse est fonction de paramètres (décalage entre deux fenêtres successives, largeur des fenêtres,…, etc.) fixés par l’utilisateur. Pour comprendre l’influence de ces paramètres et vérifier le bon fonctionnement du programme, nous avons décidé de générer des signaux connus (sinusoïde, chirp,…, etc.) et de les analyser avec ce programme. Les résultats obtenus ont permis de valider le fonctionnement du programme et nous ont conduit à concevoir des fonctions annexes de traitement des résultats. I- Les différentes fonctions de traitement des résultats.

1- La fonction prend_log.

Nous nous sommes aperçus que, parfois, l’intensité du maximum des résultats ne rendait pas possible la visualisation correcte du reste de l’image. Nous avons donc conçus une fonction, nommée prend_log , permettant de prendre le logarithme de chaque élément du tableau result . Elle prend naturellement un pointeur sur un tableau à deux dimensions et deux entiers spécifiant sa taille comme argument.

Pour valider cette fonction, nous avons appliqué le programme deux fois à un signal exponentiel complexe de fréquence 440 Hz. Lors de la première exécution, nous n’avons pas intégré la fonction prend_log au programme et nous avons obtenu l’image suivante :

Fréquence

Temps Image1

Page 15: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Lors de la seconde exécution, nous l’avons intégré et nous avons obtenu l’image numéro 2 :

La fenêtre utilisée était une porte, ce qui implique un phénomène de rebonds appelé « ringing ». Alors qu’il n’est pas visible sur l’image 1, ce phénomène peut être observé sur l’image 2. Ceci permet de valider le fonctionnement de la fonction prend_log et de montrer son influence sur l’image obtenue. 2- La fonction normalisation.

La réflexion sur les hématies peut, en plus de modifier le contenu fréquentiel du signal

ultrasonore, modifier son amplitude au cours du temps. Cependant, seul le contenu fréquentiel est important dans cette étude. Supposons qu'à l'instant t1, le signal ait une amplitude donnée et qu'à l'instant t2 son amplitude ait diminué de moitié. Quel sera l'effet de cette diminution sur l'image obtenue ? Les coefficients de la FFT associée à l'instant t2 seront, en moyenne, deux fois moins grands que ceux associés à l'instant t1. L'importance, sur l'image obtenue, de la FFT en t2 en est minimisée par rapport à la FFT en t1.

La fonction normalisation a été conçue pour remédier à ce problème. Pour chaque FFT (c'est à dire pour chaque ligne du tableau result), cette fonction calcule, tout d'abord, la somme des coefficients au carré (rappelons que la fonction fft retourne les coefficients des FFT au carré), puis, remplace chaque élément de la ligne considérée par cet élément divisé par la somme précédemment calculée. La somme des coefficients au carré de chaque FFT est ainsi égale à un. L’énergie de chaque FFT est ainsi ramenée à un pour que chacune d’entre elles ait la même importance sur l’image obtenue. L'information sur la variation d'amplitude au cours du temps est gommée pour faire apparaître clairement la variation du contenu fréquentiel au cours du temps.

Pour valider le fonctionnement de la fonction normalisation, nous avons créé un signal exponentiel complexe à 440 Hz dont l'amplitude passe brutalement de un à deux. Sans la fonction normalisation, l'exécution du programme engendre l'image 3 :

Fréquence

Temps Image2

Page 16: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Lorsqu'elle est intégrée au programme celui-ci génère l'image 4 :

L'image 3 montre que la première partie du signal (faible amplitude) est, en effet, dévalorisée par rapport à la deuxième partie (grande amplitude). Par contre, l'image 4 ne fait apparaître que le contenu fréquentiel du signal : elle est donc identique à l'image 1, conformément à nos attentes.

Fréquence

Temps Image3

Fréquence

Temps Image4

Page 17: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

3- Les fonctions de mise en forme de l'image.

L'image obtenue lors de l'exécution du programme, représente le contenu fréquentiel du signal dans la plage de fréquence comprise entre 0 et la fréquence d'échantillonnage du signal. Or, il est souvent plus commode d'avoir cette représentation comprise entre -Fe/2 et Fe/2 (Fe est la fréquence d'échantillonnage du signal). La fonction fftshift a été conçue pour former cette dernière représentation à partir de la première.

D'autre part, la fréquence d'échantillonnage peut être très supérieure à la fréquence du signal que l'on désire étudier. Dans ce cas, les informations utiles de l'image se trouvent condensées dans une petite région de l'image ce qui rend difficile l'interprétation des résultats. Il faut donc diminuer la fréquence d'échantillonnage pour optimiser l'étalement de l'information sur l'image. La fonction re_echantillonnage permet de sélectionner un point du signal initial tous les n points (n est un nombre entier choisi par l'utilisateur). La fréquence d'échantillonnage est donc divisée par n. 4- Les fonctions moyenne et ecart_type.

Si f0 est la fréquence du signal émis, le signal reçu aura la fréquence f0+δf. Pour

récupérer δf qui est l'information utile, il faut démoduler le signal reçu, c'est à dire le multiplier par une exponentielle complexe de fréquence –f0. Les signaux qui nous ont été fourni par M Giovannelli sont des signaux reçus qui ont été préalablement démodulés. D’autre part, l’hypothèse cadre de ce travail est que le spectre de ces signaux démodulés représente la répartition des vitesses dans la zone insonifiée. Par conséquent, les courbes de la vitesse moyenne des hématies et de leur écart type sont aussi, à un facteur prés, les courbes de la fréquence moyenne et de l’écart type fréquentiel. Il est donc facile, avec cette modélisation, de faire apparaître quantitativement ces deux notions qui sont fondamentales pour établir un diagnostic.

Pour se faire, nous avons conçu trois fonctions: moyenne, ecart_type et export_matlab. La fonction moyenne reçoit comme argument le tableau result et ses dimensions. Elle alloue dynamiquement un tableau de double dont la taille est égale au nombre de FFT calculées. Puis elle calcule le moment d'ordre 1 de chaque FFT, le normalise et le range dans le tableau qu'elle a créé. Enfin, elle retourne un pointeur sur ce tableau. La fonction ecart_type, ressemble à la fonction précédente mais reçoit un argument supplémentaire : un pointeur sur un tableau de double qui doit être le tableau formé par la fonction moyenne. Enfin, la troisième fonction export_matlab permet de créer un script qui peut être exécuté par le logiciel Matlab pour tracer deux courbes : la fréquence moyenne et l'écart type en fonction du temps.

Toutes ces fonctions qui vont nous permettre d'étudier les signaux réels vont dans un premier temps être utiles pour déterminer l'influence de certains paramètres sur l'image obtenue.

II- Influence des paramètres fixés par l'utilisateur. 1- La forme de la fenêtre: phénomène de "ringing".

Lors de l'exécution du programme, l'utilisateur a le choix entre deux formes de fenêtre

différentes: une porte et une fenêtre gaussienne. L'image 2 montre le résultat obtenu lors de

Page 18: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

l'exécution du programme avec la fonction prend_log et avec une fenêtre en forme de porte sur un signal exponentiel de fréquence 440 Hz. Nous avions déjà remarqué le phénomène de "ringing" induit par la porte. L'image 5 montre le résultat obtenu lorsque la porte est remplacée par une fenêtre gaussienne.

On constate, dans ce cas, que le phénomène de "ringing" est beaucoup moins prononcé

que sur l'image 2. La fenêtre gaussienne est de meilleur qualité que la porte au sens où elle introduit moins de discontinuités et donc moins de hautes fréquences. 2- La largeur de la fenêtre.

Que la fenêtre soit une porte ou une gaussienne, sa largeur est un paramètre déterminant dans l'obtention d'une image utilisable. Considérons le même signal exponentiel de l'image 2 et de l'image 5. Lorsque la largeur de la fenêtre est de 16 points, l'écart type fréquentiel est de 44,5 Hz. Cet écart type n'est que de 2,7 Hz lorsque la largeur de la fenêtre est de 256 points. Ceci met en évidence l'inégalité d'Heisenberg. La précision temporelle (largeur de fenêtre petite) apporte l'imprécision fréquentielle, et, inversement, l'imprécision temporelle (largeur de fenêtre grande) apporte la précision fréquentielle.

Toutes ces considérations nous ont permises de sélectionner les valeurs des paramètres nécessaires à l'obtention d'une image utilisable.

3- Le décalage. Le décalage n’est pas un paramètre de première importance dans l’analyse. Cependant, il doit exister une valeur optimale. Un décalage trop grand provoquerait une perte d’information. Il faut en particulier que le décalage soit plus petit que la largeur de fenêtre. Un décalage trop petit induirait un calcul trop long.

Fréquence

Temps Image5

Page 19: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

III- Application à l'échographie Doppler. 1- Analyse des signaux réels.

Dans toute la suite, la fenêtre utilisée est une gaussienne de largeur 64 points et le décalage entre deux fenêtres successives est de 10 points. Le premier signal réel nommé "SigDopAscii" représente une seconde du signal reçu et comprend environ 7000 échantillons: la fréquence d'échantillonnage est donc d'environ 7 kHz. Il s'est avéré qu'avec cette fréquence d'échantillonnage un sous-échantillonnage était inutile. Le programme a donc été exécuté sans la fonction re_echantillonnage. On a obtenu l’image 6 et les courbes suivantes par exécution du script Matlab créé.

Fréquence

Temps Image6

Page 20: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Statistiques de SigDop2

Les trois autres signaux (SigDop1, SigDop2, SigDop3) contenaient environ 29000 échantillons pour une durée d’une seconde. Nous avons donc utilisé la fonction re_echantillonnage pour ne garder qu'un point sur quatre du signal d'origine. D’autre part, la fonction fftshift a du être utilisée pour avoir des images facilement interprétables. Les résultats obtenus pour les signaux SigDop2 et SigDop3 sont présentés ci-après. Le signal SigDop1 n'a pas donné de résultats satisfaisants.

Temps

Fréquence

SigDop2

Page 21: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Statistiques de SigDop3

Fréquence

Temps

SigDop3

Page 22: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

2- Interprétation des résultats.

Tout d'abord, on peut remarquer que la composante continue des signaux reçus et démodulés a été supprimée. Celle-ci correspond à la réflexion du signal ultrasonore sur les parties fixes du corps (peau, paroi artérielle,…). Son amplitude peut être nettement supérieure aux amplitudes des composantes de fréquence non nulle du signal. La composante continue a donc été supprimée pour rendre visible le reste du contenu fréquentiel du signal.

Nous utiliserons les résultats du signal "SigDopAscii", pour donner un exemple d'interprétation succincte d'une échographie Doppler. Entre les échantillons 190 et 400, les hématies ont une vitesse moyenne supérieure au reste du cycle cardiaque, cette période est donc la systole et le reste du cycle est la diastole. On remarque que durant la diastole la répartition des vitesses longitudinales des hématies est hétérogène: l'écoulement du sang durant la systole est turbulent.

L'échographie Doppler est un outil pour diagnostiquer l'obturation partielle de vaisseaux sanguins. Le diagnostic se base sur deux faits: la vitesse moyenne des hématies augmente au niveau d'un rétrécissement et l'écart type de la distribution des vitesses longitudinales des hématies augmente à la sortie d'un rétrécissement. Si, par exemple, l’écart type est supérieur à une valeur fixée arbitrairement, l’existence d’une sténose est alors probable juste en amont de la zone insonifiée. Et si la vitesse moyenne est supérieure à une valeur fixée arbitrairement, l’existence d’une sténose est alors probable dans la zone insonifiée. Toutefois, le médecin établit son diagnostic à l’aide de plusieurs moyens d’investigations.

Page 23: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Conclusion Nous pouvons être satisfait du travail réalisé en TE. En effet, tous les objectifs ont été atteints. Nous avons créé assez rapidement le code de base d’analyse du signal, qui a tout de suite donné des résultats encourageant. En outre, nous avons jugé utile d’introduire un panel de fonctions avancées de traitement du signal, qui permettent une interprétation aisée des résultats. L’analyse des signaux fournis a donc pu être effectuée. D’autre part, nous avons développé une interface graphique pour rendre plus confortable l’utilisation de ce programme. Celle-ci n’est pas achevée, et mérite des améliorations, mais fonctionne correctement, ce qui laisse penser que la compléter ne poserait (ou ne posera) pas de difficultés. Ce programme ne se limite pas à son application à l’échographie Doppler. Il peut être utilisé pour toute analyse temps-fréquence.

Page 24: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

Annexe /*****************************************************************************/ /* */ /* Inclusion des librairies standards */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <windows.h> /*****************************************************************************/ /* */ /* Definition des constantes */ /* */ /*****************************************************************************/ #define GAUSSIENNE 0 #define PORTE 1 #define pi 3.1415926535897932384626433832795028841971693993751058209749445923 /*****************************************************************************/ /* */ /* Structure de nombre complexe */ /* */ /*****************************************************************************/ typedef struct { double real; double imag; } nComplex; /*****************************************************************************/ /* */ /* Variables globales nécessaires à la programmation windows */ /* */ /*****************************************************************************/ HINSTANCE hInst; int NombrePoints=5; int nb_points=0; nComplex *sig=NULL; int nb_fenetre=0; int decalage=10,largeur_fenetre=64,nb_points_en_frequence=1024; UINT EnableFFTShift; int TypeFenetre; double **result; double *moy,*ecart; char NomFichierBMP[256]; char NomFichierSignal[256];

Page 25: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

/*****************************************************************************/ /* */ /* Prototypes des fonctions d'analyse */ /* */ /*****************************************************************************/ nComplex* lecture_entree(int *nb_points,HWND hwndDlg,HINSTANCE hInstance); double ** analyse(int largeur_fenetre,int nb_points_en_frequence,int decalage,int nb_points,nComplex *sig,int nb_fenetre,HWND hwndDlg,HINSTANCE hInst, UNIT EnableFFTShift, int TypeFenetre); nComplex * fft(nComplex *sig,int nb_points); double *module_fft(nComplex *fftsig,int nb_points_en_frequence,int larguer_fenetre); void normalisation(double**result,int nb_points_en_frequence,int nb_fenetre); void prend_log(double**result,int nb_points_en_frequence,int nb_fenetre); nComplex *re_echantillonnage(nComplex *sig,int nb_points,int periode_relative,int *new_nb_points); nComplex * fenetre(nComplex *sig, double *gauss, int largeur_fenetre,HWND hwndDlg,HINSTANCE hInst); double *gaussienne(int largeur_fenetre); void fftshift(nComplex *fftsig, int nb_points_en_frequence); int bourrage_de_zero(nComplex *sig, int largeur_fenetre, nComplex * fenetre_sig, int nb_points_en_frequence); void detruire(nComplex *sig,double **result,int nb_fenetre); int creer_bmp(int nb_fenetre,int nb_points_en_frequence,double ** result,HWND hwndDlg,HINSTANCE hInstance); double minimun(double **result,int nb_points_en_frequence,int nb_fenetre); double maximun(double **result,int nb_points_en_frequence,int nb_fenetre); double *moyenne(double **result,int nb_points_en_frequence,int nb_fenetre); double *ecart_type(double **result, int nb_points_en_frequence, int nb_fenetre,double *moy); int export_matlab(double *signal1, double*signal2, int nb_points_du_signal, int nb_points, int resolution_en_frequence, UNIT EnableFFTShift); /*****************************************************************************/ /* */ /* Libération de la mémoire allouée pour le signal et la matrice */ /* */ /*****************************************************************************/ void detruire(nComplex *sig,double **result,int nb_fenetre) { int compteur; free(sig); if(result!=NULL) { for(compteur=0;compteur<nb_fenetre;compteur++) free(result[compteur]); free(result); } }

Page 26: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

/*****************************************************************************/ /* */ /* Transformée de Fourier rapide (fft) */ /* */ /*****************************************************************************/ nComplex * fft(nComplex *sig,int nb_points) { int i; nComplex *result; //pointeur sur le tableau créé nComplex *fftpair; //pointeur sur la fft des termes impairs nComplex *fftimpair; //pointeur sur la fft des termes impairs nComplex *sigpair; //pointeur sur le tableau des termes pairs nComplex *sigimpair; //pointeur sur le tableau des termes impairs result=(nComplex*)malloc(nb_points*sizeof(nComplex)); if(result==NULL) return NULL; if(nb_points==1) result[0]=sig[0]; //fin de la récurrence else { sigpair=(nComplex*)malloc(nb_points/2*sizeof(nComplex)); if(sigpair==NULL) return NULL; sigimpair=(nComplex*)malloc(nb_points/2*sizeof(nComplex)); if(sigimpair==NULL) return NULL; for(i=0;i<nb_points/2;i++) { sigpair[i]=sig[2*i]; //extraction des termes pairs sigimpair[i]=sig[2*i+1]; //extraction des termes impairs } fftpair=fft(sigpair,nb_points/2); //fft des termes pairs if(fftpair==NULL) return NULL; fftimpair=fft(sigimpair,nb_points/2); //fft des termes impairs if(fftimpair==NULL) return NULL; free(sigpair); free(sigimpair); for(i=0;i<nb_points/2;i++) { result[i].real=fftpair[i].real+cos(-2*pi*i/nb_points)*fftimpair[i].real-sin(-2*pi*i/nb_points)*fftimpair[i].imag; result[i].imag=fftpair[i].imag+cos(-2*pi*i/nb_points)*fftimpair[i].imag+sin(-2*pi*i/nb_points)*fftimpair[i].real; } for(i=nb_points/2;i<nb_points;i++) { result[i].real=fftpair[i-nb_points/2].real+cos(-2*pi*i/nb_points)*fftimpair[i-nb_points/2].real-sin(-2*pi*i/nb_points)*fftimpair[i-nb_points/2].imag; result[i].imag=fftpair[i-nb_points/2].imag+cos(-2*pi*i/nb_points)*fftimpair[i-nb_points/2].imag+sin(-2*pi*i/nb_points)*fftimpair[i-nb_points/2].real; } free(fftpair); free(fftimpair); } return result; }

Page 27: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

/*****************************************************************************/ /* */ /* Bourrage de zéros */ /* */ /*****************************************************************************/ int bourrage_de_zero(nComplex *sig, int largeur_fenetre, nComplex * fenetre_sig, int nb_points_en_frequence) { int i; for(i=0;i<largeur_fenetre;i++) //on recopie le signal d'entrée { fenetre_sig[i]=sig[i]; } for(i=largeur_fenetre;i<nb_points_en_frequence;i++) { fenetre_sig[i].real=0; //on complète par un signal nul fenetre_sig[i].imag=0; //le résultat de la fft n'est pas changé } return 0; } /*****************************************************************************/ /* */ /* Calcul du carré du module de la fft (divisé par le nombre de points) */ /* */ /*****************************************************************************/ double *module_fft(nComplex *fftsig,int nb_points_en_frequence,int largeur_fenetre) { int i; double *result; //allocation d'un nouveau tableau result=(double*)calloc(nb_points_en_frequence,sizeof(double)); if(result==NULL) return NULL; for(i=0;i<nb_points_en_frequence;i++) { result[i]=(fftsig[i].real*fftsig[i].real+fftsig[i].imag*fftsig[i].imag)/largeur_fenetre; } return result; } /*****************************************************************************/ /* */ /* Analyse */ /* */ /*****************************************************************************/ double ** analyse(int largeur_fenetre,int nb_points_en_frequence,int decalage,int nb_points,nComplex *sig,int nb_fenetre,HWND hwndDlg,HINSTANCE hInst, UNIT EnableFFTShift, int TypeFenetre) { int compteur; double **result; nComplex *fenetre_sig; //contient la séquence à analyser (avec les zéros complétés) nComplex *fftsig; //contient le résultat du calcul de la fft

Page 28: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

nComplex *sig_fenetre; //contient le signal mutiplié par une gaussienne double *gauss; /*allocation de la matrice de résultat : un tableau de pointeurs sur les tabeaux de double*/ result=(double**)calloc(nb_fenetre, sizeof(double*)); if(result==NULL) return NULL; fenetre_sig=(nComplex*)malloc(nb_points_en_frequence*sizeof(nComplex)); if(fenetre_sig==NULL) return NULL; gauss=gaussienne(largeur_fenetre); //calcul de la fenetre gaussienne; if(gauss==NULL) return NULL; for(compteur=0;compteur<nb_fenetre;compteur++) { if(TypeFenetre==GAUSSIENNE) //si la fenetre est une gaussienne { //on applique la gaussienne à la séquence, puis on bourre de zéros sig_fenetre=fenetre(sig+compteur*decalage,gauss,largeur_fenetre,hwndDlg,hInst); if(sig_fenetre==NULL) return NULL; bourrage_de_zero(sig_fenetre,largeur_fenetre,fenetre_sig,nb_points_en_frequence); free(sig_fenetre); } else //si la fenetre est une porte { //il suffit de bourrer de zéros bourrage_de_zero(sig+compteur*decalage,largeur_fenetre,fenetre_sig,nb_points_en_frequence); } //calcul de la fft fftsig=fft(fenetre_sig,nb_points_en_frequence); if(fftsig==NULL) return NULL; if(EnableFFTShift==BST_CHECKED) { //en option, application de fftshift fftshift(fftsig,nb_points_en_frequence); } //on place le pointeur sur le tableau résultant dans la matrice result[compteur]=module_fft(fftsig,nb_points_en_frequence,largeur_fenetre); if(result[compteur]==NULL) return NULL; free(fftsig); } free(fenetre_sig); free(gauss); return(result); }

Page 29: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

/*****************************************************************************/ /* */ /* Calcul du plus grand élément de la matrice */ /* */ /*****************************************************************************/ double maximun(double **result,int nb_points_en_frequence,int nb_fenetre) { double max=result[0][0]; int i,j; for(i=0;i<nb_fenetre;i++) for(j=0;j<nb_points_en_frequence;j++) { if(result[i][j]>max) max=result[i][j]; } return(max); } /*****************************************************************************/ /* */ /* Calcul du plus petit élément de la matrice */ /* */ /*****************************************************************************/ double minimun(double **result,int nb_points_en_frequence,int nb_fenetre) { double min=result[0][0]; int i,j; for(i=0;i<nb_fenetre;i++) for(j=0;j<nb_points_en_frequence;j++) { if(result[i][j]<min) min=result[i][j]; } return(min); } /*****************************************************************************/ /* */ /* Normalisation du signal */ /* */ /*****************************************************************************/ void normalisation(double**result,int nb_points_en_frequence,int nb_fenetre) { int i,j; double somme; for(j=0;j<nb_fenetre;j++) { somme=0; for(i=0;i<nb_points_en_frequence;i++) somme+=result[j][i]; //on calcule l'énergie spectrale for(i=0;i<nb_points_en_frequence;i++) result[j][i]=result[j][i]/somme; //on la fixe à 1 } return; }

Page 30: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

/*****************************************************************************/ /* */ /* Prise du logarithme du signal */ /* */ /*****************************************************************************/ void prend_log(double**result,int nb_points_en_frequence,int nb_fenetre) { int i,j; for(j=0;j<nb_fenetre;j++) { for(i=0;i<nb_points_en_frequence;i++) result[j][i]=log(result[j][i]); } return; } /*****************************************************************************/ /* */ /* Ré-échantillonnage du signal */ /* */ /*****************************************************************************/ nComplex *re_echantillonnage(nComplex *sig,int nb_points,int periode_relative,int *new_nb_points) { int compteur; nComplex * new_sig; //on retourne le nombre de points du nouveau signal *new_nb_points=nb_points/periode_relative+1; //calcul du nombre de points //on vérifie qu'on a le bon nombre de points while(periode_relative*(new_nb_points-1)>nb_points) new_nb_points=new_nb_points-1; //allocation du nouveau signal new_sig=(nComplex *)malloc(new_nb_points*sizeof(nComplex)); if(new_sig==NULL) return NULL for(compteur=0;compteur<nb_points;compteur+=periode_relative) { new_sig[compteur/periode_relative]=sig[compteur]; } return(new_sig); } /*****************************************************************************/ /* */ /* Création d'une gaussienne */ /* */ /*****************************************************************************/ double *gaussienne(int largeur_fenetre) { double* gauss; int compteur; gauss=(double*)malloc(largeur_fenetre*sizeof(double)); if(gauss==NULL) return NULL; for(compteur=0;compteur<largeur_fenetre;compteur++) { gauss[compteur]=exp(-10*2*(compteur-largeur_fenetre/2)*(compteur-largeur_fenetre/2)/(double)(largeur_fenetre*largeur_fenetre)); } return gauss; }

Page 31: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

/*****************************************************************************/ /* */ /* Application d'une fenetre à un signal (utilisé pour la gaussienne) */ /* */ /*****************************************************************************/ nComplex * fenetre(nComplex *sig, double *gauss, int largeur_fenetre,HWND hwndDlg,HINSTANCE hInst) { int i; nComplex * sig_fenetre; //contient le résultat de la multiplication du signal par la gaussienne sig_fenetre=(nComplex *)malloc(largeur_fenetre*sizeof(nComplex)); if(sig_fenetre==NULL) return NULL; for(i=0; i<largeur_fenetre;i++) { sig_fenetre[i].real=sig[i].real*gauss[i]; sig_fenetre[i].imag=sig[i].imag*gauss[i]; } return sig_fenetre; } /*****************************************************************************/ /* */ /* fftshift (inversion de la première et de la seconde partie du tableau) */ /* */ /*****************************************************************************/ void fftshift(nComplex *fftsig, int nb_points_en_frequence) { int i; nComplex temp; for(i=0;i<nb_points_en_frequence/2;i++) { temp=fftsig[i]; fftsig[i]=fftsig[i+nb_points_en_frequence/2]; fftsig[i+nb_points_en_frequence/2]=temp; } return; } /*****************************************************************************/ /* */ /* Calcul de la courbe de fréquence moyenne */ /* */ /*****************************************************************************/ double *moyenne(double **result,int nb_points_en_frequence,int nb_fenetre) { int i,j; double somme,somme1; double *moy; moy=(double *)malloc(nb_fenetre*sizeof(double)); //allocation des points de la courbe if(moy==NULL) return NULL; for(i=0;i<nb_fenetre;i++) //un point pour chaque colonne de l'image { somme=0,somme1=0; for(j=0;j<nb_points_en_frequence;j++) { somme+=j*result[i][j];

Page 32: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

somme1+=result[i][j]; } moy[i]=somme/somme1; //pondération par le résultat de l'analyse } return(moy); } /*****************************************************************************/ /* */ /* Calcul de la courbe d'écart type fréquentiel */ /* */ /*****************************************************************************/ double *ecart_type(double **result,int nb_points_en_frequence,int nb_fenetre, double *moy) { int i,j; double somme,somme1; double *ecart; ecart=(double *)calloc(nb_fenetre,sizeof(double)); //allocation des points de la courbe if(ecart==NULL) return NULL; for(i=0;i<nb_fenetre;i++) { somme=0,somme1=0; for(j=0;j<nb_points_en_frequence;j++) { somme+=(j-moy[i])*(j-moy[i])*result[i][j]; somme1+=result[i][j]; } ecart[i]=sqrt(somme/somme1); //l'écart type est la racine carrée de la variance } return(ecart); } /*****************************************************************************/ /* */ /* Création d'un script matlab pour le tracé */ /* */ /*****************************************************************************/ int export_matlab(double *signal1, double*signal2, int nb_points_du_signal, int nb_points, int resolution_en_frequence, UNIT EnableFFTShift) { FILE *file; int i; file=fopen("signal.m","w"); if(file==NULL) return 1; //écriture d'un script pour tracer deux courbes sous matlab fprintf(file,"sig1=["); if(EnableFFTShift==BST_CHECKED) { for(i=0;i<nb_points_du_signal-1;i++) { fprintf(file,"%lg ",nb_points/nb_points_en_frequence*(signal1[i]-nb_points_en_frequence/2)); if(i%20==1) fprintf(file,"...\n"); }

Page 33: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

fprintf(file,"%lg ];\n",nb_points/nb_points_en_frequence*(signal1[nb_points_du_signal-1]-nb_points_en_frequence/2)); } else { for(i=0;i<nb_points_du_signal-1;i++) { fprintf(file,"%lg ",nb_points/nb_points_en_frequence*signal1[i]); if(i%20==1) fprintf(file,"...\n"); } fprintf(file,"%lg ];\n",nb_points/nb_points_en_frequence*signal1[nb_points_du_signal-1]); } fprintf(file,"sig2=["); for(i=0;i<nb_points_du_signal-1;i++) { fprintf(file,"%lg ",nb_points/nb_points_en_frequence*(signal2[i])); if(i%20==1) fprintf(file,"...\n"); } fprintf(file,"%lg ];\n",nb_points/nb_points_en_frequence*(signal2[nb_points_du_signal-1])); fprintf(file,"subplot(211),\nplot(sig1),\ntitle('Courbe des frequences moyennes'),\nxlabel('Numero des points'),\nylabel('Frequence (Hz)')\n,"); fprintf(file,"subplot(212),\nplot(sig2),\ntitle('Courbe des ecarts types'),\nxlabel('Numero des points'),\nylabel('Ecart type frequentiel (Hz)')\n,"); fclose(file); return 0; } /*****************************************************************************/ /* */ /* Lecture du signal d'entrée */ /* */ /*****************************************************************************/ nComplex* lecture_entree(int *nb_points,HWND hwndDlg,HINSTANCE hInstance) { FILE *fpt; //pointeur sur le fichier int compteur,SansSouci=1; OPENFILENAME FichierDonnees; double a,b; nComplex *sig=NULL; *nb_points=0; //on veut mettre à jour le nombre de points //La fenetre "Choisissez le signal à analyser" permet de sélectionner le nom du fichier à lire FichierDonnees.lStructSize=sizeof(OPENFILENAME); FichierDonnees.hwndOwner=hwndDlg; FichierDonnees.hInstance=hInstance; FichierDonnees.lpstrFilter="Fichiers *.*"; FichierDonnees.lpstrCustomFilter=NULL; FichierDonnees.nMaxCustFilter=0; FichierDonnees.nFilterIndex=0; FichierDonnees.lpstrFile=NomFichierSignal; FichierDonnees.nMaxFile=256; FichierDonnees.lpstrFileTitle=NULL; FichierDonnees.nMaxFileTitle=0; FichierDonnees.lpstrInitialDir=NULL;

Page 34: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

FichierDonnees.lpstrTitle="Choisissez le signal à analyser."; FichierDonnees.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST; FichierDonnees.nFileOffset=0; FichierDonnees.nFileExtension=0; FichierDonnees.lpstrDefExt=NULL; FichierDonnees.lCustData=0; FichierDonnees.lpfnHook=NULL; FichierDonnees.lpTemplateName=NULL; SansSouci=GetOpenFileName(&FichierDonnees); if(SansSouci) { fpt=fopen(NomFichierSignal,"r"); if(fpt==NULL) MessageBox(hwndDlg,"On a un problème d'ouverture.","Probleme Ouverture de Fichier",MB_OK|MB_ICONERROR); else { while(feof(fpt)==0) //on compte d'abord le nombre de points { fscanf(fpt," %lg %lg ",&a,&b); //espace -> si ligne vide fin du fichier -> ignore (*nb_points)++; } //on alloue un tableau de la bonne taille sig=(nComplex *)malloc((*nb_points)*sizeof(nComplex)); if(sig==NULL) { MessageBox(hwndDlg,"On a un souci d'allocation memoire.","Probleme Allocation dynamique",MB_OK|MB_ICONERROR); return NULL; } rewind(fpt); //on revient au début du fichier for(compteur=0;compteur<*nb_points;compteur++) //on remplit le tableau { fscanf(fpt," %lg %lg ",&(sig[compteur].real),&(sig[compteur].imag)); } fclose(fpt); } } else { MessageBox(hwndDlg,"On a un souci de GetOpenFileName","Probleme Ouverture de Fichier",MB_OK|MB_ICONERROR); return NULL; } return sig; } /*****************************************************************************/ /* */ /* Création du bitmap à partir de la matrice */ /* */ /*****************************************************************************/ int creer_bmp(int nb_fenetre,int nb_points_en_frequence,double ** result,HWND hwndDlg,HINSTANCE hInstance) { unsigned char c[4]; unsigned char couleur=0;

Page 35: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

int largeur_corrigee; double max,min; FILE *fichier; int i,j; OPENFILENAME FichierDonnees; unsigned char entete[]={0x42,0X4D,0,0,0,0,0,0,0,0,0x36,0x04,0,0,0x28,0,0,0,0,0,0,0,0,0,0,0,0x01,0,0x08,0,0,0,0,0,0,0,0,0,0xC4,0x0E,0,0,0xC4,0x0E,0,0,0,0x01,0,0,0,0,0,0}; //La fenetre "Enregistrer un BMP" permet de choisir le nom et l'emplacement du fichier à créer NomFichierBMP[0] = 0; FichierDonnees.lStructSize=sizeof(OPENFILENAME); FichierDonnees.hwndOwner=hwndDlg; FichierDonnees.hInstance=hInstance; FichierDonnees.lpstrFilter=NULL; FichierDonnees.lpstrCustomFilter=NULL; FichierDonnees.nMaxCustFilter=0; FichierDonnees.nFilterIndex=0; FichierDonnees.lpstrFile=NomFichierBMP; FichierDonnees.nMaxFile=256; FichierDonnees.lpstrFileTitle=NULL; FichierDonnees.nMaxFileTitle=0; FichierDonnees.lpstrInitialDir=NULL; FichierDonnees.lpstrTitle="Enregistrer un BMP"; FichierDonnees.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST; FichierDonnees.nFileOffset=0; FichierDonnees.nFileExtension=0; FichierDonnees.lpstrDefExt=NULL; FichierDonnees.lCustData=0; FichierDonnees.lpfnHook=NULL; FichierDonnees.lpTemplateName=NULL; GetSaveFileName(&FichierDonnees); //La largeur corridgée est le plus petit multiple de quatre supérieur ou égal à la largeur de l'image largeur_corrigee=nb_fenetre%4==0?nb_fenetre:nb_fenetre+4-nb_fenetre%4; //taille du fichier entete[2]=(unsigned char)(54+1024+nb_points_en_frequence*largeur_corrigee); entete[3]=(unsigned char)((54+1024+nb_points_en_frequence*largeur_corrigee)/256); entete[4]=(unsigned char)((54+1024+nb_points_en_frequence*largeur_corrigee)/(256*256)); entete[5]=(unsigned char)((54+1024+nb_points_en_frequence*largeur_corrigee)/(256*256*256)); //largeur de l'image entete[18]=(unsigned char)(nb_fenetre); entete[19]=(unsigned char)((nb_fenetre)/256); entete[20]=(unsigned char)((nb_fenetre)/(256*256)); entete[21]=(unsigned char)((nb_fenetre)/(256*256*256)); //hauteur de l'image entete[22]=(unsigned char)(nb_points_en_frequence); entete[23]=(unsigned char)((nb_points_en_frequence)/256); entete[24]=(unsigned char)((nb_points_en_frequence)/(256*256)); entete[25]=(unsigned char)((nb_points_en_frequence)/(256*256*256));

Page 36: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

//taille des données image entete[34]=(unsigned char)(nb_points_en_frequence*largeur_corrigee); entete[35]=(unsigned char)((nb_points_en_frequence*largeur_corrigee)/256); entete[36]=(unsigned char)((nb_points_en_frequence*largeur_corrigee)/(256*256)); entete[37]=(unsigned char)((nb_points_en_frequence*largeur_corrigee)/(256*256*256)); if((fichier=fopen(NomFichierBMP,"wb"))==NULL) { MessageBox(NULL,"On a un pb d'ouverture du BMP","FFT",MB_OK|MB_ICONERROR); return 1; } else { fwrite((void *)entete,1,54,fichier); //écriture de l'entête c[3]=0; for(i=0;i<256;i++) { c[0]=c[1]=c[2]=255-i; fwrite((void*)c,1,4,fichier); //écriture de la palette par blocs de quatre octets } max=maximun(result,nb_points_en_frequence,nb_fenetre); min=minimun(result,nb_points_en_frequence,nb_fenetre); for(i=0;i<nb_points_en_frequence;i++) { for(j=0;j<largeur_corrigee;j++) { if(j>nb_fenetre) couleur=0; //on doit compléter les lignes par des octets à zéros else //calcul de la couleur : le max est en noir, le min est en blanc couleur=(unsigned char)(255*(result[j][i]-min)/(max-min)); fwrite((void *)&couleur,1,1,fichier); //on écrit un pixel } } fclose(fichier); return 0; } } /*****************************************************************************/ /* */ /* Fichier .c principal */ /* */ /*****************************************************************************/ #include "fonctions.h" #include "resource.h" #include "EntreesSorties.h" #include "FFTandCo.h"

Page 37: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

//HWND hwndAffichage; BOOL CALLBACK DialogProc2(HWND hwndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) //La boite de dialogue de choix des paramètres de l'analyse temps-fréquence { BOOL Succes1,Succes2,Succes3; switch(Msg){ case WM_INITDIALOG: // A faire lors de l'initialisation de la boite de dialogue { SetDlgItemInt(hwndDlg,IDC_EDIT1,10,FALSE); //Mettre les EDITBOX aux valeurs par défaut SetDlgItemInt(hwndDlg,IDC_EDIT2,1024,FALSE); SetDlgItemInt(hwndDlg,IDC_EDIT3,64,FALSE); CheckDlgButton(hwndDlg,IDC_CHECK1,TRUE); //On choisit une FFT Shift par défaut CheckDlgButton(hwndDlg,IDC_RADIO1,FALSE);//On choisit une porte par défaut return 0; break; } case WM_DESTROY: //croix "fermer" { EndDialog(hwndDlg,0); return TRUE; break; } case WM_COMMAND: { switch(LOWORD(wParam)) { case IDOK: // L'utilisateur a appuyé sur OK { // Réglage des paramètres de l'analyse decalage=GetDlgItemInt(hwndDlg,IDC_EDIT1,&Succes1,FALSE); // On donne aux variables correspondantes les valeurs des EDITBOX nb_points_en_frequence=GetDlgItemInt(hwndDlg,IDC_EDIT2,&Succes2,FALSE); largeur_fenetre=GetDlgItemInt(hwndDlg,IDC_EDIT3,&Succes3,FALSE); //réglages des 3 paramètres numériques EnableFFTShift=IsDlgButtonChecked(hwndDlg,IDC_CHECK1); // choix de fftshift ou non if(IsDlgButtonChecked(hwndDlg,IDC_RADIO1)) TypeFenetre=GAUSSIENNE; else TypeFenetre=PORTE; //choix du type de fenêtre (par défaut une porte) EndDialog(hwndDlg,0);//On ferme la boite de dialogue return TRUE; break; } } default:

Page 38: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

{ return FALSE; break; } } } } LRESULT CALLBACK ProcedureFenetreAffichage(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) // La fenetre d'affichage du bitmap { BITMAP bm; //contient l'image HBITMAP hbitmap; //contient un handle vers l'image HDC hdcMemory;// un handle vers une zone mémoire HDC hdc;// le handle vers la zone de dessin PAINTSTRUCT ps; // la zone de dessin switch(Message) { case WM_DESTROY: /* PostQuitMessage(0);*/ break; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); //On initialise ps et on obtient un handle vers la zone de dessin hbitmap=(HBITMAP)LoadImage(NULL,NomFichierBMP,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); //on obtient un handle vers le bitmap hdcMemory=CreateCompatibleDC(NULL);// on crée une zone mémoire pour le stocker SelectObject(hdcMemory,hbitmap);//Copie le BMP dans la mémoire GetObject(hbitmap,sizeof(bm),&bm); //Donne les infos sur l'objet BMP BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcMemory,0,0,SRCCOPY);//Dessine à l'écran Endpaint(hwnd,&ps);//On a fini de dessiner } return DefWindowProc(hwnd,Message,wParam,lParam); } BOOL CALLBACK DialogProc(HWND hwndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) // La fenetre Principale { HWND hFenetreAffichage; WNDCLASS FenetreAffichage; /*la fenetre principale*/ char szClassName[ ] = "DopplerProject"; switch(Msg){ case WM_CLOSE: //croix "fermer" { if(sig!=NULL) detruire(sig,result,nb_fenetre); //à la fin on détruit la mémoire allouée

Page 39: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

EndDialog(hwndDlg,0); return TRUE; break; } case WM_COMMAND: { switch(LOWORD(wParam)){ case IDC_CHARGER: //charger un signal { sig=lecture_entree(&nb_points,hwndDlg,hInst);//lecture du fichier de signal if(sig==NULL) return TRUE; nb_fenetre=nb_points/decalage+1;//calcul du nombre de fenêtres while((nb_fenetre-1)*decalage+largeur_fenetre>nb_points) nb_fenetre=nb_fenetre-1; SetDlgItemText(hwndDlg,IDC_EDIT1,NomFichierSignal);//affiche le nom du fichier lu dans la case prévue à cet effet return TRUE; break; } case IDC_EXPORTER: //créer l'image { if(result==NULL) //au cas où on n'a pas encore fait d'analyse { MessageBox(hwndDlg,"On n'a pas calculé les FFT","FFT",MB_OK); return TRUE; } //création de l'image if(creer_bmp(nb_fenetre,nb_points_en_frequence,result,hwndDlg,hInst)==1) return TRUE; MessageBox(hwndDlg,"On a cree le BMP !","FFT",MB_OK); return TRUE; break; } case IDC_AFFICHER: //afficher l'image à l'écran { if(NomFichierBMP[0]==0) //au cas où on n'a pas encore créé le bmp ou fait l'analyse { MessageBox(NULL,"On n'a pas calculé la FFT/Ou Exporté en BMP","Erreur",MB_OK); return 1; } FenetreAffichage.style = CS_VREDRAW|CS_HREDRAW; /*Pas de style particulier...*/ FenetreAffichage.lpfnWndProc = ProcedureFenetreAffichage; FenetreAffichage.lpszClassName = szClassName; /*Le nom affiché*/

Page 40: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

FenetreAffichage.lpszMenuName = NULL; /*Aucun Menu*/ FenetreAffichage.cbClsExtra = 0; /*Nombre d'octets rajoutés à la fin de la structure ???*/ FenetreAffichage.cbWndExtra = 0;/*Nombre d'octets rajoutés après l'instance de notre fenetre ???*/ FenetreAffichage.hIcon = 0; /* Aucune Icone*/ FenetreAffichage.hCursor = LoadCursor(NULL, IDC_ARROW); /*Curseur Par défaut*/ FenetreAffichage.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH); /*Fond gris*/ FenetreAffichage.hInstance = hInst; /*handle sur l'instance de notre application, donné par WinMain*/ if(!RegisterClass(&FenetreAffichage)) /* Enregistrement de la fenetre*/ { MessageBox(NULL,"Erreur lors de l'enregistrement de la classe fenetre principale","Erreur",MB_OK); return 1; } /* Création a proprement parler de la fenetre*/ hFenetreAffichage = CreateWindow(szClassName, /*Pointeur sur le nom de la classe à laquelle appartient la fenetre, chaine de caractere nous ayant permis de designer notre nouvelle classe précédemment*/ "Doppler Project", /*Chaine de caractères lu en faut de la fenetre*/ WS_OVERLAPPEDWINDOW, /*Fenetre du type POPUP*/ 0, /*Position initiale par défaut en x de la fenetre dans l'écran*/ 0, /*Position initiale par défaut en y de la fenetre dans l'écran*/ 600, /*Largeur (par défaut)*/ 800, /*Hauteur (par défaut)*/ hwndDlg, /*Handle vers la fenetre du parent*/ NULL, /*Handle vers un menu*/ hInst, /*Handle sur l'instance de l'application*/ NULL); /*pointeur vers des données pouvant etre transmises lors de l'initialisation de la fenetre*/ if(!hFenetreAffichage) { MessageBox(NULL,"Erreur lors de la création de la fenetre principale","Erreur",MB_OK); return 1; } ShowWindow(hFenetreAffichage,SW_NORMAL); /*Affiche la fenetre à l'écran*/ UpdateWindow(hFenetreAffichage);

Page 41: Rapport TE analyse spectrale - Crans · Introduction. 1- Objectifs du TE. L’objectif de ce TE d’informatique est d’appliquer une analyse spectrale à des signaux obtenus par

return TRUE; break; } case IDC_FFT: //lancer l'analyse { if(sig==NULL) //au cas où on n'a pas encore chargé de signal { MessageBox(hwndDlg,"Pas de signal à traiter !","FFT",MB_OK); return TRUE; } else { DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG2),NULL,DialogProc2); result=analyse(largeur_fenetre,nb_points_en_frequence,decalage,nb_points,sig,nb_fenetre,hwndDlg,hInst); if(result==NULL) return TRUE; normalisation(result,nb_points_en_frequence,nb_fenetre); MessageBox(hwndDlg,"On a analyse...","FFT",MB_OK); return TRUE; break; } } case IDC_QUITTER: //bouton quitter { if(sig!=NULL) detruire(sig,result,nb_fenetre); //à la fin on détruit la mémoire allouée EndDialog(hwndDlg,0); return TRUE; break; } case IDC_APROPOS: //bouton "à propos" { MessageBox(hwndDlg,"Doppler\n Mat-Ju-Gaetan","A Propos",MB_OK); return TRUE; break; } } default:{ return FALSE; break; } } } } //le Winmain, qui lance la fenêtre principale int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPreviousInstance, LPSTR lpCmdLine, int nShowCmd) { hInst=hInstance; NomFichierBMP[0]=0; NomFichierSignal[0] = 0; DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc); }