Richet Coraline Han Xiaofei L3 IUP Informatique 18/12/07

publicité
Richet Coraline
Han Xiaofei
L3 IUP Informatique
18/12/07
Projet
Traitement d'images en C
SOMMAIRE
1
Présentation du projet................................................................................................................... 2
1.1
Outils mis à
disposition ...............................................
2
Mise en œuvre des
fonctions ..................................................
2.1
Fonction de
traitement de type Sobel ..........................
2.1.1
Algorithme
de calcul du Sobel ...................................
2.1.2
Implémentati
on de la fonction de calcul
du Sobel de taille 3 ..................................
2.1.3
Implémentati
on de la fonction de calcul
du Sobel de taille
paramétrable ................................................................................................................................. 6
2.2
Fonction de traitement d’érosion ......................................................................................... 8
2.2.1
Algorithme d’érosion ................................................................................................... 8
2.2.2
Implémentation de la fonction d’érosion ..................................................................... 8
2.3
Fonction de traitement de dilatation................................................................................... 11
2.3.1
Algorithme de dilatation ............................................................................................ 11
2.3.2
Implémentation de la fonction de dilatation .............................................................. 11
1/53
2.4
Fonction de traitement ouverture ....................................................................................... 13
2.4.1
Algorithme d’ouverture.............................................................................................. 13
2.4.2
Implémentation de la fonction d’ouverture ................................................................ 13
2.5
Fonction de traitement fermeture ....................................................................................... 14
2.5.1
Algorithme de fermeture ............................................................................................ 14
2.5.2
Implémentation de la fonction de fermeture .............................................................. 14
2.6
Fonction de traitement de filtrage par moyenne ................................................................ 15
2.6.1
Algorithme de filtrage par moyenne .......................................................................... 15
2.6.2
Implémentation de la fonction de filtrage par moyenne ............................................ 15
2.7
Fonction de traitement de segmentation par région (region-growing) .............................. 17
2.7.1
Algorithme de segmentation d’image par région (region-growing) .......................... 17
2.7.2
Implémentation de la fonction de segmentation d’image par région ......................... 18
2.7.3
Implémentation de la fonction de segmentation d’image par région avec un pixel
d’amorce choisi au hasard .......................................................................................................... 22
3
Difficultés rencontrées ............................................................................................................... 23
4
Conclusion ................................................................................................................................. 24
5
Sources du projet ........................................................................................................................ 25
5.1
Fichier traitement.h : .......................................................................................................... 25
5.2
Fichier traitement.C : ......................................................................................................... 26
5.3
Fichier fifo.h : .................................................................................................................... 47
5.4
Fichier fifo.C : .................................................................................................................... 48
5.5
Fichier prog.C : .................................................................................................................. 52
1 Présentation du projet
Le traitement d'images numériques est l'ensemble des techniques permettant de modifier une image
numérique dans le but de l'améliorer ou d'en extraire des informations.
Une image en niveau de gris est un tableau bidimensionnel (matrice) où chaque élément contient une valeur
entre 0 et 255. Par convention, la valeur zéro représente le noir et la valeur 255 le blanc.
000 008 016 024 032 040 048 056 064 072 080 088 096 104 112 120 128
255 248 240 232 224 216 208 200 192 184 176 168 160 152 144 136
L'objectif du projet est de réaliser différents algorithmes de traitement d'images en langage C tels que :

Sobel : mise en évidence des contours d’une image.

Erosion et dilatation : supprimer les points de contours isolés ou combler les trous dans un contour
d’une image.

1.1
Segmentation en région : partitionner l'image en zones homogènes.
Outils mis à disposition
Afin de pouvoir mettre en œuvre ces algorithmes de traitement d’images, des outils ont été mis à
disposition :

Un dossier IncludeLibImage comprenant :
-
Un fichier d’entête image.h définissant une structure de type image et des prototypes de
fonctions (allocation /libération mémoire d’une image, affichage d’une image avec
l’application xv …).
2/53
-
Un fichier d’entête xAffichage.h nécessaire à la création d’une fenêtre
permettant
d’effectuer des modifications dynamiques en utilisant des touches de clavier.
-
Un fichier
d’entête
LoadSaveImages.h
contenant
des
prototypes
de fonctions
d’enregistrement et de chargement d’images.

Un dossier « XV » contenant les sources compilées du logiciel de traitement d’images XV.

Un dossier srcImage contenant les sources des fichiers cités ci-dessus.

Un dossier ExempleTraitement :
-
Un fichier traitement.h qui contiendra les prototypes des fonctions de traitement d’images à
implémenter dans le cadre du projet.
-
Un fichier traitement.C qui contiendra les implémentations des fonctions décrites dans le
fichier traitement.h.
-
Un fichier prog.C qui est le programme principal où sont appelées les fonctions de
traitement d’images et utilisant le logiciel xv.
-
Un fichier progX.C qui appelle des fonctions de traitement d’images en utilisant la librairie
Xaffichage.
3/53
2 Mise en œuvre des fonctions
2.1
2.1.1
Fonction de traitement de type Sobel
Algorithme de calcul du Sobel
Il consiste à appliquer un masque sur l’image afin de faire apparaître les endroits de l’image où les
différences entre les pixels voisins sont les plus grandes. Ces différences correspondent au contour de
l’image.
Appliquer un masque sur une image consiste à déplacer sur l’image une fenêtre carrée de taille impair et
supérieur à trois, centré à chaque fois sur un pixel (i,j) dont il faut évaluer le gradient.
Pour chaque pixel de l’image, l’application d’un masque consiste à faire la somme pondérée des valeurs des
pixels voisins de ce pixel.
Exemple de somme pondérée :
Ensuite il s’agit de normaliser cette valeur :
Dv= Dv / somme des coefficients positifs
Pour calculer le gradient en un pixel (i,j), il faut à la fois calculer le gradient vertical (avec un masque
vertical) et le gradient horizontal avec un masque horizontal.
Le résultat du gradient pour le pixel (i,j) est alors :
La valeur calculée est ensuite placée dans le pixel (i,j) d’une image appelée image des gradients.
4/53
2.1.2
Implémentation de la fonction de calcul du Sobel de taille 3
Cette fonction est implémentée en langage C dans le fichier traitement.C :
void basicThreeSobelFunction(const Image * in, Image * out)
Cette fonction permet d'effectuer un traitement Sobel sur une image, à partir d'un masque vertical et
horizontal de taille 3*3.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
Pour rappel, la structure de type Image est définie ainsi :
Struct _Image {
int magicNumber ; /* Pour vérifier que on a (pas) alloue de la mémoire */
int nbRow ;
int nbCol ;
octet *ptrZone ; /* Le vrai pointeur sur la zone image */
octet ** zone ; /* Un pointeur qui permet : zone[ligne][colonne] */
};
Typedef struct _Image Image ;
Dans cette fonction, les masques vertical et horizontal de taille 3 ainsi que leurs valeurs respectives sont
codées en dur dans la fonction :
masque vertical maskV
masque horizontal maskH
L’image donné en paramètre Image * out est allouée par la fonction.
La fonction effectue un parcours de tous les pixels (chaque colonne de chaque ligne) de l’image donnée en
paramètre const Image * in. Pour chaque pixel de coordonnées Xpin et Ypin, la fonction prend en compte les
8 pixels voisins entourant ce pixel et effectue le calcul du gradient vertical normalisé en appliquant le
masque vertical ainsi que le calcul du gradient horizontal normalisé en appliquant le masque horizontal.
5/53
Puis la fonction effectue le calcul du gradient de ce pixel à partir des gradients (vertical et horizontal)
calculés précédemment.
Ce gradient calculé est ensuite stocké dans le pixel de coordonnées Xpout et Ypout de l’image donnée en
paramètre Image * out.
Il est important de noter que la fonction n’effectue pas de calcul de gradient pour les pixels contenus dans la
1ère et dernière ligne ainsi que ceux contenus dans la 1ère et dernière colonne de l’image donnée en paramètre
Image * in. En effet, il n’est pas possible d’appliquer un masque sur ces pixels du fait de leurs coordonnées
particulières, par conséquent les gradients originaux de ces pixels sont stockés directement dans les pixels de
coordonnées identiques dans l’image donnée en paramètre Image * out.
Exemples de résultat de la fonction basicThreeSobelFunction:
femme.ras original
2.1.3
femme.ras après un traitement Sobel
lena.ras original
lena.ras après un
traitement SobelImplémentation de la fonction de calcul du Sobel de taille
6/53
paramétrable
Cette fonction est implémentée en langage C dans le fichier traitement.C :
void genericSobelFunction(const Image * in, Image * out, int ** maskV, int ** maskH, int maskSize)
Cette fonction permet d’effectuer un traitement Sobel sur une image à partir d’un masque horizontal, un
masque verticale et une taille de masque donnés en paramètres.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
Le paramètre int ** maskV est un pointeur de pointeurs d’entiers contenant un masque vertical alloué par
l’application faisant appel à cette fonction et dont la taille est donné via le paramètre int maskSize.
Le paramètre int ** maskH est un pointeur de pointeurs d’entiers contenant un masque horizontal alloué par
l’application faisant appel à cette fonction et dont la taille est donné via le paramètre int maskSize.
Le paramètre int maskSize est un entier définissant la taille des masques vertical et horizontal donnés en
paramètres : cette taille doit être impaire et supérieure ou égal à 3.
La fonction effectue d’abord un contrôle sur les paramètres en entrée :
-
La taille du masque doit être impaire : on vérifie cette condition en calculant le modulo de cette
taille. Si le modulo retourne la valeur 1 il s’agit bien d’une taille impaire.
-
La taille du masque doit être supérieure à trois.
-
La taille du masque ne doit pas dépasser celle de l’image d’entrée : cette taille est inférieure au
nombre de colonnes et de lignes de l’image donnée en paramètre const Image * in.
La fonction effectue ensuite le calcul des coefficients de normalisation du masque horizontal en parcourant
les valeurs du masque (de zéro à maskSize) et en faisant l’addition du contenu de chaque case pour les
valeurs supérieures à zéro. Le même traitement est effectué pour le masque vertical.
Ensuite La fonction effectue un parcours de tous les pixels (chaque colonne de chaque ligne) de l’image
donnée en paramètre const Image * in. Pour chaque pixel de coordonnées Xpin et Ypin, la fonction calcul
l’entier distanceMax (en fonction de la taille du masque) permettant de déterminer la distance maximal
entre le pixel du centre et celui le plus éloigné. distanceMax étant la distance limite pour effectuer
l’application du masque du pixel central :
La fonction prend donc en compte les pixels voisins entourant ce pixel en fonction de distanceMax et
effectue le calcul du gradient vertical normalisé en appliquant le masque vertical ainsi que le calcul du
gradient horizontal normalisé en appliquant le masque horizontal. Puis la fonction effectue le calcul du
gradient de ce pixel à partir des gradients (vertical et horizontal) calculés précédemment.
Ce gradient calculé est ensuite stocké dans le pixel de coordonnées Xpout et Ypout de l’image donnée en
7/53
paramètre Image * out.
Il est important de noter que la fonction n’effectue pas de calcul de gradient pour les pixels contenus dans les
lignes inférieures à distanceMax et les dernière lignes supérieures à taille vertical en pixels de l’imagedistanceMax, ainsi que ceux contenus dans les colonnes inférieures à distanceMax et les dernières colonnes
supérieures à taille horizontal en pixels de l’image-distanceMax. En effet, il n’est pas possible d’appliquer
un masque sur ces pixels du fait de leurs coordonnées particulières, par conséquent les gradients originaux de
ces pixels sont stockés directement dans les pixels de coordonnées identiques dans l’image donnée en
paramètre Image * out.
Exemple de résultat de la fonction genericSobelFunction avec un masque classique de taille 3 :
2.2
2.2.1
aquitaine.ras original
traitement sobelFonction de traitement d’érosion
aquitaine.ras après un
Algorithme d’érosion
L’érosion consiste à supprimer les points de contour (valeur 0 (C) noir) ayant au moins un voisin de type non
contour (valeur 255 (NC) blanc). Cet algorithme permet de supprimer les points de contour isolés après avoir
effectué un seuillage de l’image des gradients
2.2.2
Implémentation de la fonction d’érosion
8/53
Cette fonction est implémentée en langage C dans le fichier traitement.C :
void erosionFunction(const Image* in,Image * out)
Cette fonction effectue un traitement d’érosion sur une image.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
L’image donné en paramètre Image * out est allouée par la fonction.
La fonction effectue un parcours de tous les pixels (chaque colonne de chaque ligne) de l’image donnée en
paramètre const Image * in. Pour chaque pixel de coordonnées Xpin et Ypin, la fonction contrôle si ce pixel
est noir (gradient égal à 0) : dans ce cas, la fonction prend en compte les pixels voisins entourant ce pixel. Si
au moins un de ces pixels voisins est blanc (valeur de gradient égal à 255) alors la fonction stocke dans le
pixel de coordonnées Xpout et Ypout du paramètre Image * out un gradient égal à 255 (blanc), sinon la valeur
du gradient du pixel original est stockée.
Il est important de noter que la fonction n’effectue pas de traitement pour les pixels contenus dans la 1ère et
dernière ligne ainsi que ceux contenus dans la 1ère et dernière colonne de l’image donnée en paramètre Image
* in. Les gradients originaux de ces pixels sont stockés directement dans les pixels de coordonnées
identiques dans l’image donnée en paramètre Image * out.
Exemple de résultat de la fontion erosionFunction :
A noter qu’avant le traitement d’érosion, l’image subit un traitement de seuillage qui était déjà implémenté
dans le projet.
9/53
lena.ras original
lena.ras après seuillage + érosion
10/53
2.3
2.3.1

Fonction de traitement de dilatation
Algorithme de dilatation
L’érosion consiste à transformer les points de non contour (valeur 255 (NC) blanc) ayant au moins un voisin
de type contour (valeur 0 (C) noir) Cet algorithme permet de combler les trous dans un contour après avoir
effectué un seuillage de l’image des gradients
2.3.2
Implémentation de la fonction de dilatation
Cette fonction est implémentée en langage C dans le fichier traitement.C :
void dilatationFunction(const Image* in, Image * out)
Cette fonction effectue un traitement de dilatation sur une image.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
L’image donné en paramètre Image * out est allouée par la fonction.
La fonction effectue un parcours de tous les pixels (chaque colonne de chaque ligne) de l’image donnée en
paramètre const Image * in. Pour chaque pixel de coordonnées Xpin et Ypin, la fonction contrôle si ce pixel
est blanc (gradient égal à 255) : dans ce cas, la fonction prend en compte les pixels voisins entourant ce
pixel. Si au moins un de ces pixels voisins est noir (valeur de gradient égal à 0) alors la fonction stocke dans
le pixel de coordonnées Xpout et Ypout du paramètre Image * out un gradient égal à 0 (noir), sinon la valeur
du gradient du pixel original est stockée.
Il est important de noter que la fonction n’effectue pas de traitement pour les pixels contenus dans la 1ère et
dernière ligne ainsi que ceux contenus dans la 1ère et dernière colonne de l’image donnée en paramètre Image
* in. Les gradients originaux de ces pixels sont stockés directement dans les pixels de coordonnées
identiques dans l’image donnée en paramètre Image * out.
11/53
Exemple de résultat de la fontion dilatationFunction :
A noter qu’avant le traitement d’érosion, l’image subit un traitement de seuillage qui était déjà implémenté
dans le projet.
lena.ras original
lena.ras après seuillage + dilatation
12/53
2.4
2.4.1
Fonction de traitement ouverture
Algorithme d’ouverture
Il consiste à effectuer un traitement d’érosion suivi d’un traitement de dilatation sur une image pour
supprimer les petits objets.
2.4.2
Implémentation de la fonction d’ouverture
void ouvertureFunction(const Image* in, Image * out)
Cette fonction effectue un traitement d’ouverture sur une image.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
L’image donné en paramètre Image * out est allouée par la fonction.
Dans cette fonction, on fait appel successivement aux fonctions erosionFunction et dilatationFunction.
Cette fonction créer une image temporaire allouée qui est l’image de sortie de la fonction erosionFunction
et l’image d’entrée de la fonction dilatationFunction. La mémoire allouée de l’image temporaire est
finalement libérée à la fin du traitement.
Exemple de résultat de la fontion ouvertureFunction :
A noter qu’avant le traitement d’érosion, l’image subit un traitement de seuillage qui était déjà implémenté
dans le projet.
lena.ras original
lena.ras après seuillage + ouverture
13/53
2.5
2.5.1
Fonction de traitement fermeture
Algorithme de fermeture
Il consiste à effectuer un traitement de dilatation suivi d’un traitement d’érosion sur une image pour combler
les petits trous, les chenaux étroits et connecter les contours proches.
2.5.2
Implémentation de la fonction de fermeture
void fermetureFunction(const Image* in, Image * out)
Cette fonction effectue un traitement de fermeture sur une image.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
L’image donné en paramètre Image * out est allouée par la fonction.
Dans cette fonction, on fait appel successivement aux fonctions dilatationFunction et erosionFunction.
Cette fonction créer une image temporaire allouée qui est l’image de sortie de la fonction
dilatationFunction et l’image d’entrée de la fonction erosionFunction. La mémoire allouée de l’image
temporaire est finalement libérée à la fin du traitement.
Exemple de résultat de la fontion fermetureFunction :
A noter qu’avant le traitement d’érosion, l’image subit un traitement de seuillage qui était déjà implémenté
dans le projet.
lena.ras original
lena.ras après seuillage + fermeture
14/53
2.6
Fonction de traitement de filtrage par moyenne
2.6.1
Algorithme de filtrage par moyenne
Il consiste à lisser l’image en appliquant sur chaque pixel de cette image un masque ne contenant
que des valeurs à 1 : cet algorithme s’apparente à l’algorithme de Sobel mis à part que les valeurs
d’un unique masque sont toutes à 1.
2.6.2
Implémentation de la fonction de filtrage par moyenne
void filtreMoyenneFunction(const Image* in, Image * out, int maskSize)
Cette fonction effectue un filtrage par moyenne sur une image.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
Le paramètre int maskSize est un entier définissant la taille du masque qui contiendra que des valeurs 1 :
cette taille doit être impaire et supérieure ou égal à 3.
L’image donné en paramètre Image * out est allouée par la fonction.
La fonction effectue d’abord un contrôle sur les paramètres en entrée :
-
La taille du masque doit être impaire : on vérifie cette condition en calculant le modulo de cette
taille. Si le modulo retourne la valeur 1 il s’agit bien d’une taille impaire.
-
La taille du masque doit être supérieure à trois.
-
La taille du masque ne doit pas dépasser celle de l’image d’entrée : cette taille est inférieure au
nombre de colonnes et de lignes de l’image donnée en paramètre const Image * in.
La fonction créé un masque de taille maskSize*maskSize ne contenant que des valeurs 1.
La fonction effectue ensuite le calcul des coefficients de normalisation du masque.
Ensuite La fonction effectue un parcours de tous les pixels (chaque colonne de chaque ligne) de l’image
donnée en paramètre const Image * in. Pour chaque pixel de coordonnées Xpin et Ypin, la fonction calcul
l’entier distanceMax (en fonction de la taille du masque) permettant de déterminer la distance maximal
entre le pixel du centre et celui le plus éloigné. distanceMax étant la distance limite pour effectuer
l’application du masque du pixel central :
La fonction prend donc en compte les pixels voisins entourant ce pixel en fonction de distanceMax et
effectue le calcul du gradient normalisé en appliquant le masque créé.
Ce gradient calculé est ensuite stocké dans le pixel de coordonnées Xpout et Ypout de l’image donnée en
paramètre Image * out.
Il est important de noter que la fonction n’effectue pas de calcul de gradient pour les pixels contenus dans les
lignes inférieures à distanceMax et les dernière lignes supérieures à taille vertical en pixels de l’image15/53
distanceMax, ainsi que ceux contenus dans les colonnes inférieures à distanceMax et les dernières colonnes
supérieures à taille horizontal en pixels de l’image-distanceMax. En effet, il n’est pas possible d’appliquer
un masque sur ces pixels du fait de leurs coordonnées particulières, par conséquent les gradients originaux de
ces pixels sont stockés directement dans les pixels de coordonnées identiques dans l’image donnée en
paramètre Image * out.
Exemple de résultat de la fontion filtreMoyenneFunction :
lena.ras original
lena.ras après filtreMoyenneFunction
16/53
2.7
2.7.1
Fonction de traitement de segmentation par région (region-growing)
Algorithme de segmentation d’image par région (region-growing)
Il permet de partitionner l’image en zone homogènes selon un critère déterminé: couleur, niveau de gris.
On part d’un point amorce (seed) et on l’étend en ajoutant les points de la frontière qui satisfont le critère
d’homogénéité
Le point amorce peut être choisi soit par un humain, soit de manière automatique en évitant les zones de fort
contraste (gradient important) => méthode par amorce.
amorce
croissance
région finale
Détail de l’algorithme :
On définit une zone R qui contient la région à extraire.
Initialement, R contient l’amorce.
On utilise une file FIFO (First In, First Out) S qui contient les points frontière
Initialement, S contient le voisinage de l’amorce.
On retire p dans S
si p est homogène avec R,
on ajoute p à R et on ajoute à S les points du voisinage de p qui ne sont pas dans R et qui ne
sont pas incompatibles.
sinon,
on marque p comme incompatible.
On recommence tant que S n’est pas vide
17/53
2.7.2
Implémentation de la fonction de segmentation d’image par région
void segmentationRegionGrowing(const Image *in,Image *out, int xPixelSeed, int yPixelSeed,
int seuil)
Cette fonction effectue une segmentation d’image par région.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
Le paramètre int xPixelSeed est un entier indiquant la position en abscisse de l’amorce.
Le paramètre int yPixelSeed est un entier indiquant la position en ordonnée de l’amorce.
Le paramètre int seuil est un entier indiquant un seuil de différence de gradient maximal à ne pas dépasser
pour qu’un pixel puisse être inclus dans une région.
L’image donné en paramètre Image * out est allouée par la fonction.
Dans le cadre de cette fonction, une structure Pixel a été définie dans le fichier traitement.h afin de pouvoir
stocker pour un pixel donné ses coordonnées et son gradient :
typedef struct Pixel
{
Int x,
Int y,
Int gradient ;
} Pixel ;
Ensuite, il a fallu définir un composant supplémentaire pour la gestion d’une pile de type FIFO (first in first
out) : les fichiers fifo.h et fifo.C.
Le fichier fifo.h contient les prototypes de fonctions permettant la mise en œuvre d’une pile de type FIFO
(first in first out) contenant pour chaque élément une structure de type Pixel. Le fichier fifo.c implémente en
C les fonctions définies dans fifo.h.
Une structure est définie dans fifo.h permettant de stocker les éléments d’une pile fifo :
typedef struct fifo
{
Pixel * pixel ;
Struct fifo * suivant ;
}fifo ;
18/53
Les fonctions suivantes ont été implémentées :
-
fifo ** initFifo(fifo ** pile, int size) : cette fonction initialise et alloue (taille donnée en paramètre)
la mémoire nécessaire pour une pile de type fifo. Elle renvoie un pointeur de pointeur de structure de
type fifo.
-
void pushIntoFifo(fifo ** pile, Pixel * p) : cette fonction ajoute un élément à la pile. Cet élément
ajouté contient un pointeur sur une copie de la structure Pixel qui était pointé par le paramètre Pixel
* p.
-
int isAlreadyInFifo(fifo ** pile, Pixel * p) : cette fonction recherche un élément dans la pile Fifo,
le critère de recherche étant le pixel pointé par le paramètre Pixel * p. Si la fonction trouve cet
élément alors elle retourne 1 sinon 0.
-
Pixel * fifoPop(fifo ** pile, Pixel * buffer) : cette fonction retire le premier élément de la pile Fifo.
La fonction retourne un pointeur sur la copie d’une structure de type Pixel qui était pointée dans le
contenu de l’élément supprimé.
-
void fifoClear(fifo ** pile) : cette fonction supprime tous les éléments de la pile fifo.
-
int sizeOfFifo(fifo ** pile) : cette fonction retourne le nombre d’éléments de la pile fifo.
La fonction segmentationRegionGrowing contrôle en premier lieu si les coordonnées de l’amorce données
en paramètres ne dépassent pas l’image.
Ensuite la fonction effectue une phase d’initialisation : elle alloue un pointeur de structure de type Pixel qui
permettra de stocker les pixels appartenant à la région : Pixel * region. Le premier élément pointé par à la
région est une structure de type Pixel contenant les coordonnées du pixel amorce ainsi que son gradient à
partir de l’image donnée en paramètre const Image * in. La fonction alloue un pointeur de structure de type
Pixel qui permettra de stocker les pixels dits « incompatibles » : Pixel * incompatibles. La fonction initialise
une pile de type FIFO et y stocke (via la fonction pushIntoFifo) les 8 pixels voisins qui entourent le pixel
amorce.
Ensuite la fonction effectue une boucle jusqu’à ce que la taille de la pile FIFO soit nulle et à chaque itération
effectue les traitements suivants :
-
elle récupère un pixel de la pile FIFO (via la fonction fifoPop).
-
Elle calcule le gradient moyen de la région et regarde si la valeur absolue de la soustraction du
gradient un pixel récupéré et du gradient moyen est inférieur ou non au seuil.
-
Si cette valeur calculée est supérieur au seuil, alors le pixel est ajouté à la liste des incompatibles via
le pointeur Pixel * incompatibles en ayant vérifié au préalable que ce pixel n’était pas déjà présent
parmi les incompatibles (on évite ainsi les doublons inutiles).
-
Si cette valeur calculée est inférieur au seuil, alors le pixel est ajouté à la région via le pointeur Pixel
* region. Puis, la fonction récupère les 8 pixels voisins entourant le pixel : les pixels n’appartenant
ni à la région, ni aux incompatibles et n’étant pas déjà stockés dans la pile FIFO (testés via la
fonction isAlreadyInFifo) sont alors stockés dans la pile FIFO (via la fonction pushIntoFifo).
19/53
Une fois toutes les itérations nécessaires effectuées, le pointeur Pixel * region permet alors d’accéder à tous
les pixels de la région étendue (growing-region).
La fonction effectue alors une dans une première passe une copie de tous les pixels de l’image donnée en
paramètre const Image * in vers l’image donnée en paramètre Image * out.
Puis dans une seconde passe, elle récupère toutes les coordonnées des pixels de la région via le pointeur
Pixel * region et met la valeur du gradient à 255 (blanc) (c’est un choix totalement arbitraire) pour tous
les pixels de coordonnées similaires de l’image donnée en paramètre Image * out. Au final, la fonction vide
la pile FIFO et libère les pointeurs Pixel * region et Pixel * incompatibles.
Ainsi, il apparait sur l’image traitée une zone blanche qui correspond à la zone de segmentation calculée.
Bien évidemment, le choix de colorer en blanc la zone de segmentation est arbitraire car à partir du moment
où l’on connait les coordonnées des pixels de la région tous les types de traitement de ces pixels sont
possibles (on pourrait par exemple lisser la totalité de l’image par la fonction filtre par moyenne sauf la
partie segmentée qui pourrait rester non lissée de manière à mieux la faire ressortir).
20/53
Exemple de résultat de la fontion segmentationRegionGrowing :
A noter qu’avant le traitement de segmentation, l’image subit un traitement de filtre par moyenne.
La taille de l’image d’origine est de 256 pixel * 256 pixels :
femme.ras original
L’exemple suivant est le résultat d’une segmentation avec comme paramètres un pixel amorce en x = 220,
y = 100 avec un seuil à 60 :
Un autre exemple avec comme paramètres un pixel amorce en x = 1, y = 1 avec un seuil à 20 :
21/53
2.7.3
Implémentation de la fonction de segmentation d’image par région avec un pixel
d’amorce choisi au hasard
void segmentationRegionGrowingRandomSeed(const Image *in,Image *out, int seuil)
Cette
fonction
effectue
une
segmentation
d’image
par
région
identique
à
la
fonction
segmentationRegionGrowing, mis à part que c’est la fonction qui détermine les coordonnées du pixel
d’amorce au hasard.
Le paramètre const Image * in est un pointeur de type Image alloué par l’application faisant appel a cette
fonction.
Le paramètre Image * out est un pointeur de structure de type Image (non alloué) qui permettra de stocker
l’image qui sera traitée.
Le paramètre int seuil est un entier indiquant un seuil de différence de gradient maximal à ne pas dépasser
pour qu’un pixel puisse être inclus dans une région.
La fonction détermine au hasard, via la fonction rand() de la librairie stdlib.h une coordonnée x inférieur à
la largeur en pixels de l’image const Image * in et une coordonnée y inférieur à la longueur en pixels de
l’image const Image * in.
Une
fois
ces
deux
coordonnées
déterminées,
la
fonction
fait
appel
à
la
fonction
segmentationRegionGrowing de base avec en paramètres les coordonnées du pixel d’amorce calculés
précédemment.
22/53
3 Difficultés rencontrées
La première difficulté du projet a été de s’apercevoir que la compilation du projet d’origine (sans les
fonctionnalités implémentées expliquées précédemment) nécessitait l’installation de la librairie x11-dev sous
linux. En effet, il est important de ne pas faire l’amalgame entre la libraire x11 qui était déjà installée par
défaut sur notre machine de développement (linux ubuntu 6.0.6) et la librairie x11-dev qui est une API
offrant les fonctions nécessaires au développement d’application graphique et sur laquelle s’appuie les
différents programmes du projet.
Ensuite, la seconde difficulté principale a été l’écriture de la fonction
Sobel générique :
genericSobelFunction. Cette dernière se veut la plus générique possible car c’est à l’application utilisant
cette fonction de donner en paramètres les masques horizontal et vertical ainsi que la taille de ces masques.
Cette généricité entrainait une plus grande complexité que la fonction basicThreeSobelFunction (où les
masques sont codés en dur) : elle nécessitait des contrôles supplémentaires des pixels de bordure d’image à
ne pas traiter en fonction de la taille des masques vertical et horizontal. Cette dernière difficulté résolue nous
a permis de bien appréhender la fonction filtreMoyenneFunction dont le paramètre int maskSize entrainait
une complexité similaire.
Enfin, la difficulté principale fut avant tout l’implémentation de la fonction segmentationRegionGrowing.
En effet, il était d’abord nécessaire de bien comprendre l’algorithme de segmentation « region-growing »
avant de pouvoir le coder.
Ensuite nous avons été contraints, afin de suivre rigoureusement l’algorithme, de créer une structure de type
Pixel permettant le stockage des coordonnées d’un pixel et son gradient, mais surtout de coder un nouveau
module proposant des fonctions de manipulation d’une pile de type FIFO (first in first out).
Une fois ce module développé, nous avons pu coder l’algorithme de segmentation dans les meilleures
conditions, en prenant soin de maitriser correctement les allocations et libérations mémoire des pointeurs de
structures Pixel (pour les pixels appartenant à la région et les pixels incompatibles) et de la pile FIFO. Par
rapport à l’algorithme initial, nous avons essayé d’optimiser le code en effectuant des contrôles
supplémentaires afin de ne pas stocker de doublons dans la pile FIFO et de ne pas ajouter de doublons
inutiles dans la liste des pixels incompatibles.
23/53
4 Conclusion
Ce projet fut une expérience motivante pour appréhender les problématiques de base inhérentes aux
traitements d’images. Il nous a permis de conforter nos connaissances en termes de codage C, tout en
intégrant une dimension « plus ludique » à la programmation : il était motivant de pouvoir observer
graphiquement et concrètement les résultats de nos fonctions implémentées et d’imaginer des applications
possibles à ce type de traitements d’images.
Même si nous n’avons pas abordé ce sujet dans ce rapport, il est très intéressant pour une même
fonctionnalité de segmentation d’image de voir les nombreuses approches possibles pour la mettre en
œuvre. En effet, la segmentation par « region-growing » est l’approche la plus facile et la plus intuitive, mais
c’est aussi celle qui nécessite les temps de traitements les plus longs et donc au demeurant la moins efficace.
Il existe ainsi d’autres approches plus optimisées de cette fonctionnalité à travers les algorithmes dits de Split
& Merge, de CSC, de Contours actifs et même à travers une approche probabiliste (algorithme de
« condensation »).
Le traitement d’image est une discipline à part entière nécessitant à la fois de bonnes connaissances en
mathématiques et une bonne maitrise de la programmation et de l’optimisation d’algorithmes. Elle se veut
concrète puisqu’applicable dans de nombreux domaines scientifiques et industrielles…par exemple, il n’est
pas étonnant de s’apercevoir que l’algorithme de segmentation est directement appliqué pour l’analyse de
séquences d’images IRM en médecine. A travers cette découverte des bases du traitement d’images, c’est un
domaine nouveau et vaste qui s’est ouvert à nous.
24/53
5 Sources du projet
5.1
Fichier traitement.h :
#ifndef SEUILLAGE_H
#define SEUILLAGE_H
#include "image.h"
extern void seuillage(const Image * in, Image * out, octet seuil);
extern void seuillageRVB(const ImageRVB * in, ImageRVB * out, octet seuil);
extern void basicThreeSobelFunction(const Image * in,Image * out);
extern void genericSobelFunction(const Image * in,Image * out,int ** maskV,int **
maskH,int maskSize);
extern void erosionFunction(const Image* in,Image * out);
extern void dilatationFunction(const Image* in,Image * out);
extern void ouvertureFunction(const Image* in,Image * out);
extern void fermetureFunction(const Image* in,Image * out);
extern void filtreMoyenneFunction(const Image* in,Image * out,int maskSize);
extern void segmentationRegionGrowing(const Image * in,Image * out, int xPixelSeed,int
yPixelSeed,int seuil);
extern void segmentationRegionGrowingRandomSeed(const Image * in,Image * out,int seuil);
typedef struct Pixel
{
int x;
int y;
int gradient;
} Pixel;
#endif /* SEUILLAGE_H */
25/53
5.2
Fichier traitement.C :
#include
#include
#include
#include
#include
#include
#include
#include
"image.h"
"traitement.h"
<math.h>
<malloc.h>
<stdio.h>
"fifo.h"
<stdlib.h>
"time.h"
#define C 0
#define NC 255
void seuillage(const Image * in, Image * out, octet seuil)
{
int l = 0, c = 0;
int nbRowI = in->nbRow, nbColI = in->nbCol;
mallocImage(out,nbRowI,nbColI); // Si necessaire
for(l=0;l<nbRowI;l++)
{
for(c=0;c<nbColI;c++)
{
out->zone[l][c] = (in->zone[l][c]>seuil) ? C : NC;
// original : out->zone[l][c] = (in->zone[l][c]>seuil) ? C : NC; ??
}
}
}
void seuillageRVB(const ImageRVB * in, ImageRVB * out, octet seuil)
{
int nbRowI = in->nbRow, nbColI = in->nbCol;
mallocImageRVB(out,nbRowI,nbColI);
seuillage(&in->R,&out->R,seuil);
seuillage(&in->V,&out->V,seuil);
seuillage(&in->B,&out->B,seuil);
}
//--------------------------------------------------------------------------------------------------// Fonction : basicThreeSobelFunction(const Image * in, Image * out)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
26/53
// Cette fonction effectue un traitement "sobel" sur une image, Ã partir d'un mask vertical et horizontal
// de taille 3*3.
//
// Le mask vertical est en dur dans la fonction :
// maskV : -1 0 1
//
-2 0 2
//
-1 0 1
//
// Le mask horizontal est en dur dans la fonction :
// maskH : 1 2 1
//
0 0 0
//
-1 -2 -1
//--------------------------------------------------------------------------------------------------void basicThreeSobelFunction(const Image * in,Image * out)
{
//recuperation du nombre de ligne de l'image in
int nbRowI = in->nbRow;
//recuperation du nombre de colonnes de l'image in
int nbColI = in->nbCol;
//initialisation du mask vertical
int maskV[3][3];
maskV[0][0]=-1;
maskV[0][1]= 0;
maskV[0][2]= 1;
maskV[1][0]=-2;
maskV[1][1]= 0;
maskV[1][2]= 2;
maskV[2][0]=-1;
maskV[2][1]= 0;
maskV[2][2]= 1;
int sommeCoefsPosMaskV=4; //somme des coefficients positifs
//initialisation du mask horizontal
int maskH[3][3];
maskH[0][0]=1;
maskH[0][1]= 2;
maskH[0][2]= 1;
maskH[1][0]=0;
maskH[1][1]= 0;
maskH[1][2]= 0;
maskH[2][0]=-1;
maskH[2][1]= -2;
maskH[2][2]=-1;
int sommeCoefsPosMaskH=4; //somme des coefficients positifs
//reservation memoire pour l image de sortie qui va etre generee
mallocImage(out,nbRowI,nbColI);
out->nbRow=nbRowI;
out->nbCol=nbColI;
27/53
//on va parcourir toutes les lignes et colonnes de l'image
int cptLine=0; //compteur de ligne
int cptCol=0; //compteur de colonne
for(cptLine=0;cptLine<nbRowI;cptLine++)
{
//parcours des colonnes
for(cptCol=0;cptCol<nbColI;cptCol++)
{
//on ne traite pas la 1ere ni la derniere ligne,et la 1ere ni la derniere colonne
//car les points appartenant a ces lignes et colonnes ne peuvent pas etre encadres par un mask
if((cptLine!=0 && cptLine<nbRowI-1)&&(cptCol!=0 && cptCol<nbColI-1))
{
int pixelMatrice[3][3];
pixelMatrice[0][0]=in->zone[cptLine-1][cptCol-1];
pixelMatrice[0][1]=in->zone[cptLine-1][cptCol];
pixelMatrice[0][2]=in->zone[cptLine-1][cptCol+1];
pixelMatrice[1][0]=in->zone[cptLine][cptCol-1];
pixelMatrice[1][1]=in->zone[cptLine][cptCol];
pixelMatrice[1][2]=in->zone[cptLine][cptCol+1];
pixelMatrice[2][0]=in->zone[cptLine+1][cptCol-1];
pixelMatrice[2][1]=in->zone[cptLine+1][cptCol];
pixelMatrice[2][2]=in->zone[cptLine+1][cptCol+1];
//calcul gradient vertical du point
int dv=(maskV[0][0]*pixelMatrice[0][0]
+maskV[0][1]*pixelMatrice[0][1]
+maskV[0][2]*pixelMatrice[0][2]
+maskV[1][0]*pixelMatrice[1][0]
+maskV[1][1]*pixelMatrice[1][1]
+maskV[1][2]*pixelMatrice[1][2]
+maskV[2][0]*pixelMatrice[2][0]
+maskV[2][1]*pixelMatrice[2][1]
+maskV[2][2]*pixelMatrice[2][2])/sommeCoefsPosMaskV;
//calcul gradient horizontal du point
int dh=(maskH[0][0]*pixelMatrice[0][0]
+maskH[0][1]*pixelMatrice[0][1]
+maskH[0][2]*pixelMatrice[0][2]
+maskH[1][0]*pixelMatrice[1][0]
+maskH[1][1]*pixelMatrice[1][1]
+maskH[1][2]*pixelMatrice[1][2]
+maskH[2][0]*pixelMatrice[2][0]
+maskH[2][1]*pixelMatrice[2][1]
+maskH[2][2]*pixelMatrice[2][2])/sommeCoefsPosMaskH;
// calcul du gradient
int gradient=int (sqrt(dv*dv+dh*dh));
out->zone[cptLine][cptCol]=gradient;
}
else
28/53
{
//copie dans l image out des valeurs des pixels originaux
out->zone[cptLine][cptCol]=in->zone[cptLine][cptCol];
}
}
}
//out->ptrZone=in->zone[0]; ????
}
//-------------------------------------------------------------------------------------------------------// Fonction : genericSobelFunction(const Image * in, Image * out,int ** maskV,int ** maskH,int maskSize)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
int ** maskV : un pointeur de pointeurs d entiers qui contient un mask vertical
//
alloue par l application appellant cette fonction et de taille
//
maskSize*maskSize.
//
int ** maskH : un pointeur de pointeurs d entiers qui contient un mask horizontal
//
alloue par l application appellant cette fonction et de taille
//
maskSize*maskSize.
//
int maskSize : taille des masks donnes en parametres : cette taille doit etre impair
//
et superieur ou egal a 3.
//
// Cette fonction effectue un sobel sur une image, Ã partir d'un mask vertical et horizontal
// donnes en parametres.
//-------------------------------------------------------------------------------------------------------void genericSobelFunction(const Image * in,Image * out,int ** maskV,int ** maskH,int maskSize)
{
//contrôle si maskSize est impair et superieur ou egal a 3
//et que le mask n est pas plus grand que l image
int ctlModMask=(int)fmod(maskSize,2);
if(ctlModMask==1 && maskSize>=3 && maskSize<in->nbRow && maskSize<in->nbCol)
{
//recuperation du nombre de ligne de l'image in
int nbRowI = in->nbRow;
//recuperation du nombre de colonnes de l'image in
int nbColI = in->nbCol;
//calcul de la somme des coefficients de maskV
int sommeCoefsPosMaskV=0;
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
29/53
if(maskV[i][j]>0)
{
sommeCoefsPosMaskV=sommeCoefsPosMaskV+maskV[i][j];
}
}
}
//calcul de la somme des coefficients de maskH
int sommeCoefsPosMaskH=0;
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
if(maskH[i][j]>0)
{
sommeCoefsPosMaskH=sommeCoefsPosMaskH+maskH[i][j];
}
}
}
//reservation memoire pour l image de sortie qui va etre generee
mallocImage(out,nbRowI,nbColI);
out->nbRow=nbRowI;
out->nbCol=nbColI;
//on va parcourir toutes les lignes et colonnes de l'image
int cptLine=0; //compteur de ligne
int cptCol=0; //compteur de colonne
for(cptLine=0;cptLine<nbRowI;cptLine++)
{
//parcours des colonnes
for(cptCol=0;cptCol<nbColI;cptCol++)
{
int distanceMax=(maskSize-1)/2; //distance max entre le pixel du centre et celui le plus eloigne
if((cptLine>distanceMax && cptLine<nbRowI-distanceMax)&&(cptCol>distanceMax && cptCol<nbColI-distanceMax))
{
//int pixelMatrice[maskSize][maskSize];
int ** pixelMatrice=(int **)malloc(sizeof(int*)*maskSize);
for(int cptAlloc=0;cptAlloc<maskSize;cptAlloc++)
{
int * tmp=(int*)malloc(sizeof(int)*maskSize);
*(pixelMatrice+cptAlloc)=tmp;
}
int distanceMax=(maskSize-1)/2; //distance max entre le pixel du centre et celui le plus eloigne
for(int i=0;i<maskSize;i++)
{
30/53
for(int j=0;j<maskSize;j++)
{
pixelMatrice[i][j]=in->zone[cptLine+i-distanceMax][cptCol+j-distanceMax];
}
}
//calcul gradient vertical du point
int dv=0;
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
dv=dv+maskV[i][j]*pixelMatrice[i][j];
}
}
dv=dv/sommeCoefsPosMaskV;
//calcul gradient horizontal du point
int dh=0;
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
dh=dh+maskH[i][j]*pixelMatrice[i][j];
}
}
dh=dh/sommeCoefsPosMaskH;
//desallocation de pixelMatrice
for(int cptAlloc=0;cptAlloc<maskSize;cptAlloc++)
{
free(*(pixelMatrice+cptAlloc));
}
free(pixelMatrice);
// calcul du gradient
int gradient=int (sqrt(dv*dv+dh*dh));
out->zone[cptLine][cptCol]=gradient;
}
else
{
//copie dans l image out des valeurs des pixels originaux
out->zone[cptLine][cptCol]=in->zone[cptLine][cptCol];
}
}
}
}
}
31/53
//-------------------------------------------------------------------------------------------------------// Fonction : erosionFunction(const Image * in, Image * out)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l'application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
// Cette fonction effectue un traitement d "erosion" sur une image.
//--------------------------------------------------------------------------------------------------------void erosionFunction(const Image* in,Image * out)
{
//recuperation du nombre de ligne de l'image in
int nbRowI = in->nbRow;
//recuperation du nombre de colonnes de l'image in
int nbColI = in->nbCol;
//reservation memoire pour l image de sortie qui va etre generee
mallocImage(out,nbRowI,nbColI);
out->nbRow=nbRowI;
out->nbCol=nbColI;
int cptLine=0; //compteur de ligne
int cptCol=0; //compteur de colonne
for(cptLine=0;cptLine<nbRowI;cptLine++)
{
//parcours des colonnes
for(cptCol=0;cptCol<nbColI;cptCol++)
{
//on ne traite pas la 1ere ni la derniere ligne,et la 1ere ni la derniere colonne
if((cptLine!=0 && cptLine<nbRowI-1)&&(cptCol!=0 && cptCol<nbColI-1))
{
//si le pixel est noir
int valeurPixel=in->zone[cptLine][cptCol];
if(valeurPixel==C)
{
// 0 1 2
// 3 p 4
// 5 6 7
int p0=in->zone[cptLine-1][cptCol-1];
int p1=in->zone[cptLine-1][cptCol];
int p2=in->zone[cptLine-1][cptCol+1];
int p3=in->zone[cptLine][cptCol-1];
int p4=in->zone[cptLine][cptCol+1];
int p5=in->zone[cptLine+1][cptCol-1];
int p6=in->zone[cptLine+1][cptCol];
int p7=in->zone[cptLine+1][cptCol+1];
if(p0==NC || p1==NC || p2==NC || p3==NC || p4==NC ||
p5==NC || p6==NC ||p7==NC)
{
32/53
//un pixel dans son entourage direct est blanc
//alors le pixel p devient blanc
valeurPixel=NC;
}
}
out->zone[cptLine][cptCol]=valeurPixel;
}
else
{
//copie dans l image out des valeurs des pixels originaux
out->zone[cptLine][cptCol]=in->zone[cptLine][cptCol];
}
}
}
}
//-------------------------------------------------------------------------------------------------------// Fonction : dilatationFunction(const Image * in, Image * out)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l'application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
// Cette fonction effectue un traitement de "dilatation" sur une image.
//--------------------------------------------------------------------------------------------------------void dilatationFunction(const Image* in,Image * out)
{
//recuperation du nombre de ligne de l'image in
int nbRowI = in->nbRow;
//recuperation du nombre de colonnes de l'image in
int nbColI = in->nbCol;
//reservation memoire pour l image de sortie qui va etre generee
mallocImage(out,nbRowI,nbColI);
out->nbRow=nbRowI;
out->nbCol=nbColI;
int cptLine=0; //compteur de ligne
int cptCol=0; //compteur de colonne
for(cptLine=0;cptLine<nbRowI;cptLine++)
{
//parcours des colonnes
for(cptCol=0;cptCol<nbColI;cptCol++)
{
//on ne traite pas la 1ere ni la derniere ligne,et la 1ere ni la derniere colonne
if((cptLine!=0 && cptLine<nbRowI-1)&&(cptCol!=0 && cptCol<nbColI-1))
{
//si le pixel est blanc
33/53
int valeurPixel=in->zone[cptLine][cptCol];
if(valeurPixel==NC)
{
// 0 1 2
// 3 p 4
// 5 6 7
int p0=in->zone[cptLine-1][cptCol-1];
int p1=in->zone[cptLine-1][cptCol];
int p2=in->zone[cptLine-1][cptCol+1];
int p3=in->zone[cptLine][cptCol-1];
int p4=in->zone[cptLine][cptCol+1];
int p5=in->zone[cptLine+1][cptCol-1];
int p6=in->zone[cptLine+1][cptCol];
int p7=in->zone[cptLine+1][cptCol+1];
if(p0==C || p1==C || p2==C || p3==C || p4==C ||
p5==C || p6==C ||p7==C)
{
//un pixel dans son entourage direct est noir
//alors le pixel p devient noir
valeurPixel=C;
}
}
out->zone[cptLine][cptCol]=valeurPixel;
}
else
{
//copie dans l image out des valeurs des pixels originaux
out->zone[cptLine][cptCol]=in->zone[cptLine][cptCol];
}
}
}
}
//-------------------------------------------------------------------------------------------------------// Fonction : ouvertureFunction(const Image * in, Image * out)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
// Cette fonction effectue un traitement d "ouverture" sur une image : il s agit sur une image d appliquer
// 2 traitements successifs sur l image : une erosion suivie d une dilatation.
//--------------------------------------------------------------------------------------------------------void ouvertureFunction(const Image* in,Image * out)
{
Image iTmp;
//une ouverture se fait via 2 traitements successifs : une erosion suivi d une dilatation de l image.
erosionFunction(in,&iTmp);
dilatationFunction(&iTmp,out);
34/53
freeImage(&iTmp);
}
//-------------------------------------------------------------------------------------------------------// Fonction : fermetureFunction(const Image * in, Image * out)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
// Cette fonction effectue un traitement de "fermeture" sur une image : il s agit sur une image d appliquer
// 2 traitements successifs sur l image : une dilatation suivie d une erosion. C est donc le procede
// inverse d une "ouverture".
//--------------------------------------------------------------------------------------------------------void fermetureFunction(const Image* in,Image * out)
{
Image iTmp;
//une fermeture se fait via 2 traitements successifs : une dilatation suivi d une erosion de l image.
dilatationFunction(in,&iTmp);
erosionFunction(&iTmp,out);
freeImage(&iTmp);
}
//---------------------------------------------------------------------------------------------------------// Fonction : filtreMoyenneFunction(const Image * in,Image * out,int maskSize)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
int maskSize : la taille du mask qui servira au filtre par la moyenne, elle doit etre
//
superieur ou egal a 3 et impair.
//
// Cette fonction effectue un filtre dit "de la moyenne" sur une image : il s agit d appliquer un mask
// contenant que des valeurs 1 de taille maskSize sur les pixels de l image.
// exemple pour un mask de taille 3 :
1 1 1
//
1 1 1
//
1 1 1
//---------------------------------------------------------------------------------------------------------void filtreMoyenneFunction(const Image* in,Image * out,int maskSize)
{
//contrôle si maskSize est impair et superieur ou egal a 3
//et que le mask n est pas plus grand que l image
int ctlModMask=(int)fmod(maskSize,2);
if(ctlModMask==1 && maskSize>=3 && maskSize<in->nbRow && maskSize<in->nbCol)
{
//creation d'une matrice de taille maskSize contenant que des 1
int ** mask=(int**)malloc(sizeof(int*)*maskSize);
for(int cpt=0;cpt<maskSize;cpt++)
{
35/53
int * tmp=(int*)malloc(sizeof(int)*maskSize);
*(tmp)=1;
*(tmp+1)=1;
*(tmp+2)=1;
*(mask+cpt)=tmp;
}
//recuperation du nombre de ligne de l'image in
int nbRowI = in->nbRow;
//recuperation du nombre de colonnes de l'image in
int nbColI = in->nbCol;
//calcul de la somme des coefficients de maskV
int sommeCoefsPosMask=0;
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
if(mask[i][j]>0)
{
sommeCoefsPosMask=sommeCoefsPosMask+mask[i][j];
}
}
}
//reservation memoire pour l image de sortie qui va etre generee
mallocImage(out,nbRowI,nbColI);
out->nbRow=nbRowI;
out->nbCol=nbColI;
//on va parcourir toutes les lignes et colonnes de l'image
int cptLine=0; //compteur de ligne
int cptCol=0; //compteur de colonne
for(cptLine=0;cptLine<nbRowI;cptLine++)
{
//parcours des colonnes
for(cptCol=0;cptCol<nbColI;cptCol++)
{
int distanceMax=(maskSize-1)/2; //distance max entre le pixel du centre et celui le plus eloigne
if((cptLine>distanceMax && cptLine<nbRowI-distanceMax)&&(cptCol>distanceMax && cptCol<nbColI-distanceMax))
{
int ** pixelMatrice=(int **)malloc(sizeof(int*)*maskSize);
for(int cptAlloc=0;cptAlloc<maskSize;cptAlloc++)
{
int * tmp=(int*)malloc(sizeof(int)*maskSize);
*(pixelMatrice+cptAlloc)=tmp;
36/53
}
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
pixelMatrice[i][j]=in->zone[cptLine+i-distanceMax][cptCol+j-distanceMax];
}
}
//calcul gradient
int dv=0;
for(int i=0;i<maskSize;i++)
{
for(int j=0;j<maskSize;j++)
{
dv=dv+mask[i][j]*pixelMatrice[i][j];
}
}
dv=dv/sommeCoefsPosMask;
//desallocation de pixelMatrice
for(int cptAlloc=0;cptAlloc<maskSize;cptAlloc++)
{
free(*(pixelMatrice+cptAlloc));
}
free(pixelMatrice);
// calcul du gradient
int gradient=dv;
out->zone[cptLine][cptCol]=gradient;
}
else
{
//copie dans l image out des valeurs des pixels originaux
out->zone[cptLine][cptCol]=in->zone[cptLine][cptCol];
}
}
}
//liberation memoire du mask
for(int cpt=0;cpt<maskSize;cpt++)
{
free(*(mask+cpt));
}
free(mask);
}
37/53
}
//-----------------------------------------------------------------------------------------------------------------// Fonction : segmentationRegionGrowing(const Image * in,Image * out,int xPixelSeed,int yPixelSeed,int seuil)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
int xPixelSeed : coordonnee x du point de depart a partir duquel l algorithme regionGrowing demarre.
//
int yPixelSeed : coordonnee y du point de depart a partir duquel l algorithme regionGrowing demarre.
//
int seuil : pour chaque pixel rencontree, le critere de selection pour l appartenance a la region
//
s appuie sur ce seuil.
//
// Cette fonction effectue une segmentation de l image en utilisant l algorithme "region growing".
//------------------------------------------------------------------------------------------------------------------void segmentationRegionGrowing(const Image * in,Image * out, int xPixelSeed,int yPixelSeed,int seuil)
{
//recuperation du nombre de ligne de l'image in
int nbRowI = in->nbRow;
//recuperation du nombre de colonnes de l'image in
int nbColI = in->nbCol;
if(xPixelSeed<=nbColI && yPixelSeed<=nbRowI)
{
//reservation memoire pour l image de sortie qui va etre generee
mallocImage(out,nbRowI,nbColI);
out->nbRow=nbRowI;
out->nbCol=nbColI;
//--------------------------------------------------------//
//
INITIALISATION
//
// la region contient l amorce (pixelSee)
//
// et la pile fifo contiendra le voisinage de l amorce
//
//--------------------------------------------------------//
//allocation memoire pour des structures de srgPixel pour la region
Pixel *region=(Pixel*)malloc(sizeof(Pixel)*(nbRowI*nbColI));
//allocation memoire pour des structures de srgPixel pour la liste des incompatibles
Pixel *incompatibles=(Pixel*)malloc(sizeof(Pixel)*(nbRowI*nbColI));
int cptPixelsRegion=0;
int cptPixelsIncompatibles=0;
//on inclus le pixelSeed dans la region
region->x=xPixelSeed;
region->y=yPixelSeed;
region->gradient=in->zone[yPixelSeed][xPixelSeed];
cptPixelsRegion++;
38/53
//initialisation de la pile Fifo qui contiendra les pixels voisins (qui n appartiennent pas a la region ni a la liste des
//incompatibles ) d un pixel en analyse.
fifo** pile;
pile=initFifo(pile,nbRowI*nbColI);
//voisinage de l amorce
//contrôle les 8 pixels entourant
// 0 1 2
// 3 p 4
// 5 6 7
Pixel * srgP0=(Pixel*)malloc(sizeof(Pixel));
srgP0->x=xPixelSeed-1;
srgP0->y=yPixelSeed-1;
srgP0->gradient=in->zone[srgP0->y][srgP0->x];
Pixel * srgP1=(Pixel*)malloc(sizeof(Pixel));
srgP1->x=xPixelSeed;
srgP1->y=yPixelSeed-1;
srgP1->gradient=in->zone[srgP1->y][srgP1->x];
Pixel * srgP2=(Pixel*)malloc(sizeof(Pixel));
srgP2->x=xPixelSeed+1;
srgP2->y=yPixelSeed-1;
srgP2->gradient=in->zone[srgP2->y][srgP2->x];
Pixel * srgP3=(Pixel*)malloc(sizeof(Pixel));
srgP3->x=xPixelSeed-1;
srgP3->y=yPixelSeed;
srgP3->gradient=in->zone[srgP3->y][srgP3->x];
Pixel * srgP4=(Pixel*)malloc(sizeof(Pixel));
srgP4->x=xPixelSeed+1;
srgP4->y=yPixelSeed;
srgP4->gradient=in->zone[srgP4->y][srgP4->x];
Pixel * srgP5=(Pixel*)malloc(sizeof(Pixel));
srgP5->x=xPixelSeed-1;
srgP5->y=yPixelSeed+1;
srgP5->gradient=in->zone[srgP5->y][srgP5->x];
Pixel * srgP6=(Pixel*)malloc(sizeof(Pixel));
srgP6->x=xPixelSeed;
srgP6->y=yPixelSeed+1;
srgP6->gradient=in->zone[srgP6->y][srgP6->x];
Pixel * srgP7=(Pixel*)malloc(sizeof(Pixel));
srgP7->x=xPixelSeed+1;
srgP7->y=yPixelSeed+1;
srgP7->gradient=in->zone[srgP7->y][srgP7->x];
39/53
pushIntoFifo(pile,srgP0); //le push effectue une copie local dans la fonction du pixel
pushIntoFifo(pile,srgP1);
pushIntoFifo(pile,srgP2);
pushIntoFifo(pile,srgP3);
pushIntoFifo(pile,srgP4);
pushIntoFifo(pile,srgP5);
pushIntoFifo(pile,srgP6);
pushIntoFifo(pile,srgP7);
free(srgP0);
free(srgP1);
free(srgP2);
free(srgP3);
free(srgP4);
free(srgP5);
free(srgP6);
free(srgP7);
while(sizeOfFifo(pile)!=0)
{
Pixel * pixel=(Pixel*)malloc(sizeof(Pixel));
pixel=fifoPop(pile,pixel); //recuperation du premier pixel de la pile
//calcul du gradient moyen de la region
int gradientSomme=0;
int regionCpt=0;
while(regionCpt<cptPixelsRegion)
{
Pixel* tmp=region+regionCpt;
gradientSomme=gradientSomme+tmp->gradient;
regionCpt++;
}
int gradientMoyen=(int)gradientSomme/cptPixelsRegion; //gradient moyen de la region
int absGradient=(int)fabs(pixel->gradient-gradientMoyen);
//on regarde si la condition pour appartenir a la region est valide
if(absGradient<seuil)
{
//on ajoute pixel a la region
Pixel * tmp=region+cptPixelsRegion;
tmp->x=pixel->x;
tmp->y=pixel->y;
tmp->gradient=gradientMoyen;
cptPixelsRegion++;
//recuperation des points du voisinage de p
if(pixel->x-1>=0 && pixel->x+1<nbColI && pixel->y-1>=0 && pixel->y+1<nbRowI)
{
Pixel * srgP0=(Pixel*)malloc(sizeof(Pixel));
40/53
srgP0->x=pixel->x-1;
srgP0->y=pixel->y-1;
srgP0->gradient=in->zone[srgP0->y][srgP0->x];
Pixel * srgP1=(Pixel*)malloc(sizeof(Pixel));
srgP1->x=pixel->x;
srgP1->y=pixel->y-1;
srgP1->gradient=in->zone[srgP1->y][srgP1->x];
Pixel * srgP2=(Pixel*)malloc(sizeof(Pixel));
srgP2->x=pixel->x+1;
srgP2->y=pixel->y-1;
srgP2->gradient=in->zone[srgP2->y][srgP2->x];
Pixel * srgP3=(Pixel*)malloc(sizeof(Pixel));
srgP3->x=pixel->x-1;
srgP3->y=pixel->y;
srgP3->gradient=in->zone[srgP3->y][srgP3->x];
Pixel * srgP4=(Pixel*)malloc(sizeof(Pixel));
srgP4->x=pixel->x+1;
srgP4->y=pixel->y;
srgP4->gradient=in->zone[srgP4->y][srgP4->x];
Pixel * srgP5=(Pixel*)malloc(sizeof(Pixel));
srgP5->x=pixel->x-1;
srgP5->y=pixel->y+1;
srgP5->gradient=in->zone[srgP5->y][srgP5->x];
Pixel * srgP6=(Pixel*)malloc(sizeof(Pixel));
srgP6->x=pixel->x;
srgP6->y=pixel->y+1;
srgP6->gradient=in->zone[srgP6->y][srgP6->x];
Pixel * srgP7=(Pixel*)malloc(sizeof(Pixel));
srgP7->x=pixel->x+1;
srgP7->y=pixel->y+1;
srgP7->gradient=in->zone[srgP7->y][srgP7->x];
//on va tester pour tous ses pixels si ils n appartiennent pas
// a la region ou a la liste des incompatibles
int
int
int
int
int
int
int
int
flagNonAutorisePushFifo_srgP0=0;
flagNonAutorisePushFifo_srgP1=0;
flagNonAutorisePushFifo_srgP2=0;
flagNonAutorisePushFifo_srgP3=0;
flagNonAutorisePushFifo_srgP4=0;
flagNonAutorisePushFifo_srgP5=0;
flagNonAutorisePushFifo_srgP6=0;
flagNonAutorisePushFifo_srgP7=0;
//test pour chaque pixel si il appartient pas deja a la region
41/53
int cptRegion=0;
while(cptRegion<cptPixelsRegion)
{
Pixel * tmp=region+cptRegion;
if((tmp->x==srgP0->x)&&(tmp->y==srgP0->y))
{
flagNonAutorisePushFifo_srgP0=1;
}
else if((tmp->x==srgP1->x)&&(tmp->y==srgP1->y))
{
flagNonAutorisePushFifo_srgP1=1;
}
else if((tmp->x==srgP2->x)&&(tmp->y==srgP2->y))
{
flagNonAutorisePushFifo_srgP2=1;
}
else if((tmp->x==srgP3->x)&&(tmp->y==srgP3->y))
{
flagNonAutorisePushFifo_srgP3=1;
}
else if((tmp->x==srgP4->x)&&(tmp->y==srgP4->y))
{
flagNonAutorisePushFifo_srgP4=1;
}
else if((tmp->x==srgP5->x)&&(tmp->y==srgP5->y))
{
flagNonAutorisePushFifo_srgP5=1;
}
else if((tmp->x==srgP6->x)&&(tmp->y==srgP6->y))
{
flagNonAutorisePushFifo_srgP6=1;
}
else if((tmp->x==srgP7->x)&&(tmp->y==srgP7->y))
{
flagNonAutorisePushFifo_srgP7=1;
}
cptRegion++;
}
//test pour chaque pixel si il appartient pas deja a la liste des incompatibles
int cptIncompatibles=0;
while(cptIncompatibles<cptPixelsIncompatibles)
{
Pixel * tmp=incompatibles+cptIncompatibles;
if((tmp->x==srgP0->x)&&(tmp->y==srgP0->y))
{
flagNonAutorisePushFifo_srgP0=1;
}
if((tmp->x==srgP1->x)&&(tmp->y==srgP1->y))
{
42/53
flagNonAutorisePushFifo_srgP1=1;
}
if((tmp->x==srgP2->x)&&(tmp->y==srgP2->y))
{
flagNonAutorisePushFifo_srgP2=1;
}
if((tmp->x==srgP3->x)&&(tmp->y==srgP3->y))
{
flagNonAutorisePushFifo_srgP3=1;
}
if((tmp->x==srgP4->x)&&(tmp->y==srgP4->y))
{
flagNonAutorisePushFifo_srgP4=1;
}
if((tmp->x==srgP5->x)&&(tmp->y==srgP5->y))
{
flagNonAutorisePushFifo_srgP5=1;
}
if((tmp->x==srgP6->x)&&(tmp->y==srgP6->y))
{
flagNonAutorisePushFifo_srgP6=1;
}
if((tmp->x==srgP7->x)&&(tmp->y==srgP7->y))
{
flagNonAutorisePushFifo_srgP7=1;
}
cptIncompatibles++;
}
//ok maintenant on push dans fifo les pixel dont les flags sont restes a zero
//et en s assurant qu ils ne sont pas deja dans la pile
if(flagNonAutorisePushFifo_srgP0==0 && isAlreadyInFifo(pile,srgP0)==0)
{
pushIntoFifo(pile,srgP0);
}
if(flagNonAutorisePushFifo_srgP1==0 && isAlreadyInFifo(pile,srgP1)==0)
{
pushIntoFifo(pile,srgP1);
}
if(flagNonAutorisePushFifo_srgP2==0 && isAlreadyInFifo(pile,srgP2)==0)
{
pushIntoFifo(pile,srgP2);
}
if(flagNonAutorisePushFifo_srgP3==0 && isAlreadyInFifo(pile,srgP3)==0)
{
pushIntoFifo(pile,srgP3);
}
if(flagNonAutorisePushFifo_srgP4==0 && isAlreadyInFifo(pile,srgP4)==0)
{
pushIntoFifo(pile,srgP4);
}
43/53
if(flagNonAutorisePushFifo_srgP5==0 && isAlreadyInFifo(pile,srgP5)==0)
{
pushIntoFifo(pile,srgP5);
}
if(flagNonAutorisePushFifo_srgP6==0 && isAlreadyInFifo(pile,srgP6)==0)
{
pushIntoFifo(pile,srgP6);
}
if(flagNonAutorisePushFifo_srgP7==0 && isAlreadyInFifo(pile,srgP7)==0)
{
pushIntoFifo(pile,srgP7);
}
free(srgP0);
free(srgP1);
free(srgP2);
free(srgP3);
free(srgP4);
free(srgP5);
free(srgP6);
free(srgP7);
}
}
else
{
//on ajoute le pixel parmis la liste des incompatibles
//mais on verifie d abord que ce pixel n appartient pas deja a cette liste
int cptInc=0;
int doublonIncompatibles=0;
while(cptInc<cptPixelsIncompatibles)
{
Pixel * tmp=incompatibles+cptInc;
if((pixel->x==tmp->x)&&(pixel->y==tmp->y))
{
doublonIncompatibles=1;
break;
}
cptInc++;
}
if(doublonIncompatibles==0)
{
Pixel * tmp=incompatibles+cptPixelsIncompatibles;
tmp->x=pixel->x;
tmp->y=pixel->y;
tmp->gradient=pixel->gradient;
cptPixelsIncompatibles++;
}
}
free(pixel);
}
44/53
//on effectue la copie des pixels de in vers out
int cptLine=0; //compteur de ligne
int cptCol=0; //compteur de colonne
for(cptLine=0;cptLine<nbRowI;cptLine++)
{
//parcours des colonnes
for(cptCol=0;cptCol<nbColI;cptCol++)
{
//copie dans l image out des valeurs des pixels originaux
out->zone[cptLine][cptCol]=in->zone[cptLine][cptCol];
}
}
//maintenant tous les pixels qui nous interessent sont dans region
int cptParcoursRegion=0;
while(cptParcoursRegion<cptPixelsRegion)
{
Pixel * tmp=region+cptParcoursRegion;
out->zone[tmp->y][tmp->x]=255;
cptParcoursRegion++;
}
//clear de la pile
fifoClear(pile);
//penser a faire desallocation de region et incompatibles
free(region);
free(incompatibles);
}
}
//-----------------------------------------------------------------------------------------------------------------// Fonction : segmentationRegionGrowingRandomSeed(const Image * in,Image * out,int seuil)
//
// Parametres : const Image * in : un pointeur de structure de type Image alloue par l application
//
faisant appel a cette fonction.
//
Image * out : un pointeur de structure de type Image (non alloue) qui permettra
//
de stocker l image qui sera calculee par la fonction.
//
int seuil : pour chaque pixel rencontree, le critere de selection pour l appartenance a la region
//
s appuie sur ce seuil.
//
// Cette fonction effectue une segmentation de l image en utilisant l algorithme "region growing" : les coordonnees
// du pixel d amorce (seed) sont choisies au hasard par la fonction.
//------------------------------------------------------------------------------------------------------------------void segmentationRegionGrowingRandomSeed(const Image * in,Image * out,int seuil)
{
int xSeed;
srand((unsigned)time(NULL)); //initialise srand
xSeed=(unsigned int)rand();
xSeed=(xSeed%in->nbCol);
45/53
int ySeed;
ySeed=(unsigned int)rand();
ySeed=(ySeed%in->nbRow);
segmentationRegionGrowing(in,out,xSeed,ySeed,seuil);
}
46/53
5.3
Fichier fifo.h :
#include "traitement.h"
typedef struct fifo
{
Pixel * pixel;
struct fifo *suivant;
}fifo;
extern
extern
extern
extern
extern
extern
fifo** initFifo(fifo** pile,int size);
void pushIntoFifo(fifo ** pile,Pixel * p);
Pixel* fifoPop(fifo** pile,Pixel * buffer);
void fifoClear(fifo** pile);
int sizeOfFifo(fifo** pile);
int isAlreadyInFifo(fifo** pile,Pixel *p);
47/53
5.4
Fichier fifo.C :
#include
#include
#include
#include
"fifo.h"
"traitement.h"
<malloc.h>
<stdio.h>
//---------------------------------------------------------------------------------// - Fonction : fifo ** initFifo(fifo ** pile,int size)
//
// - Parametres : fifo** pile : un pointeur de pointeur de structure de type fifo
//
non alloue.
//
int size : une taille qui servira a allouer la memoire necessaire
//
a la pile fifo.
//
// Cette fonction initialise et alloue la memoire necessaire pour une pile fifo.
// Elle retourne un pointeur de pointeur de structure de type fifo.
//---------------------------------------------------------------------------------fifo** initFifo(fifo** pile,int size)
{
pile=(fifo**)malloc(sizeof(fifo*)*size); //fifo pour les frontieres
*pile=NULL;
return pile;
}
//------------------------------------------------------------------------------------// - Fonction : void pushIntoFifo(fifo ** pile,Pixel * p)
//
// - Parametres : fifo ** pile : un pointeur de pointeur de structure de type fifo mais
//
alloue (via la fonction initFifo()).
//
Pixel * p : un pointeur de structure de type Pixel qui sera copie et
//
ajoute dans un element de la pile.
//
// Cette fonction ajoute un element dans la pile fifo.
//-------------------------------------------------------------------------------------void pushIntoFifo(fifo ** pile,Pixel * p)
{
fifo * p_nouveau=(fifo*)malloc(sizeof(fifo));
if(p_nouveau!=NULL)
{
p_nouveau->suivant=NULL;
//copie du pixel
Pixel* tmp=(Pixel*)malloc(sizeof(Pixel));
tmp->x=p->x;
tmp->y=p->y;
tmp->gradient=p->gradient;
48/53
p_nouveau->pixel=tmp;
if(*pile==NULL)
{
*pile=p_nouveau;
}
else
{
fifo * p_tmp=*pile;
while(p_tmp->suivant!=NULL)
{
p_tmp=p_tmp->suivant;
}
p_tmp->suivant=p_nouveau;
}
}
}
//------------------------------------------------------------------------------------// - Fonction : void isAlreadyInFifo(fifo ** pile,Pixel * p)
//
// - Parametres : fifo ** pile : un pointeur de pointeur de structure de type fifo mais
//
alloue (via la fonction initFifo()).
//
Pixel * p : un pointeur de structure de type Pixel.
//
// Cette fonction recherche un element dans la pile fifo, le critère de recherche
// etant le pixel pointe par le parametre Pixel * p. Si la fonction trouve cet
// element alors elle retourne 1 sinon 0.
//-------------------------------------------------------------------------------------int isAlreadyInFifo(fifo ** pile,Pixel * p)
{
int found=0;
fifo* p_tmp=*pile;
int cpt=0;
while(p_tmp->suivant!=NULL)
{
Pixel * tmp=p_tmp->pixel;
if((tmp->x==p->x) &&(tmp->y==p->y))
{
found=1;
break;
}
else
{
p_tmp=p_tmp->suivant;
cpt++;
}
}
49/53
return found;
}
//---------------------------------------------------------------------------------------// - Fonction : Pixel* fifoPop(fifo ** pile,Pixel * buffer)
//
// - Parametres : fifo ** pile : un pointeur de pointeur de structure de type fifo mais
//
alloue (via la fonction initFifo()).
//
Pixel * buffer : un pointeur de structure de type Pixel alloue par
//
l'application appellant cette fonction qui servira
//
a stocker une copie dy pixel qui était dans l'element
//
supprime.
//
// Cette fonction retire le premier element de la pile fifo.
// La fonction retourne un pointeur sur la copie d une structure de type Pixel qui etait
// pointee dans le contenu de l element supprime.
//---------------------------------------------------------------------------------------Pixel* fifoPop(fifo** pile,Pixel * buffer)
{
if(pile!=NULL)
{
fifo* p_tmp=(*pile)->suivant;
Pixel * tmp=(*pile)->pixel;
if(buffer!=NULL)
{
//on effectue une copie dans buffer
buffer->x=tmp->x;
buffer->y=tmp->y;
buffer->gradient=tmp->gradient;
}
//liberation du pixel pour l element de la fifo
//free(*pile)->pixel;
free(tmp);
free(*pile);
*pile=NULL;
*pile=p_tmp;
if(buffer!=NULL)
{
return buffer;
}
else
{
return NULL;
}
}
return NULL;
}
50/53
//---------------------------------------------------------------------------------// - Fonction : void fifoClear(fifo** pile)
//
// - Parametres : fifo ** pile : un pointeur de pointeur de structure de type fifo
//
mais alloue (via la fonction initFifo()).
//
// Cette fonction supprime tous les elements de la pile fifo.
//---------------------------------------------------------------------------------void fifoClear(fifo** pile)
{
while(*pile!=NULL)
{
fifoPop(pile,NULL);
}
}
//---------------------------------------------------------------------------------// - Fonction : int sizeOfFifo(fifo ** pile)
//
// - Parametres : fifo ** pile : un pointeur de pointeur de structure de type fifo
//
mais alloue (via la fonction initFifo()).
//
// Cette fonction retourne le nombre d'elements presents dans la pile fifo.
//----------------------------------------------------------------------------------int sizeOfFifo(fifo** pile)
{
int cpt=0;
fifo * p_tmp=*pile;
while(p_tmp->suivant!=NULL)
{
p_tmp=p_tmp->suivant;
cpt++;
}
return cpt;
}
51/53
5.5
Fichier prog.C :
/* prog.C */
#include <stdio.h>
#include "image.h"
#include <malloc.h>
#include "traitement.h"
int main(void)
{
Image i0;
Image iSeuillage;
Image iSobel;
Image iErosion;
Image iDilatation;
Image iOuverture;
Image iFermeture;
Image iMoyenne;
Image iSegmentation;
Image iSegmentationRandom;
loadImage(&i0,"../Images/femme.ras");
//seuillage(&i0,&iSeuillage,30);
//basicThreeSobelFunction(&i0,&i2);
int ** maskV=(int**)malloc(sizeof(int*)*3);
for(int i=0;i<3;i++)
{
int * tmp=(int*)malloc(sizeof(int)*3);
*(maskV+i)=tmp;
}
maskV[0][0]=-1;
maskV[0][1]= 0;
maskV[0][2]= 1;
maskV[1][0]=-2;
maskV[1][1]= 0;
maskV[1][2]= 2;
maskV[2][0]=-1;
maskV[2][1]= 0;
maskV[2][2]= 1;
//initialisation du mask horizontal
int ** maskH=(int**)malloc(sizeof(int*)*3);
for(int i=0;i<3;i++)
{
int * tmp=(int*)malloc(sizeof(int)*3);
*(maskH+i)=tmp;
}
maskH[0][0]=1;
maskH[0][1]= 2;
maskH[0][2]= 1;
maskH[1][0]=0;
maskH[1][1]= 0;
maskH[1][2]= 0;
maskH[2][0]=-1;
maskH[2][1]= -2;
maskH[2][2]=-1;
genericSobelFunction(&i0,&iSobel,maskV,maskH,3);
seuillage(&iSobel,&iSeuillage,30);
erosionFunction(&iSeuillage,&iErosion);
dilatationFunction(&iSeuillage,&iDilatation);
ouvertureFunction(&iSeuillage,&iOuverture);
fermetureFunction(&iSeuillage,&iFermeture);
filtreMoyenneFunction(&i0,&iMoyenne,3);
segmentationRegionGrowing(&iMoyenne,&iSegmentation,1,1,20);
segmentationRegionGrowingRandomSeed(&iMoyenne,&iSegmentationRandom,10);
52/53
//affichage des images
displayImage("../Images/femme.ras");
saveImage(&iSeuillage,"../Resultats/seuil.ras");
displayImage("../Resultats/seuil.ras");
saveImage(&iSobel,"../Resultats/sobel.ras");
displayImage("../Resultats/sobel.ras");
saveImage(&iErosion,"../Resultats/erosion.ras");
displayImage("../Resultats/erosion.ras");
saveImage(&iDilatation,"../Resultats/dilatation.ras");
displayImage("../Resultats/dilatation.ras");
saveImage(&iOuverture,"../Resultats/ouverture.ras");
displayImage("../Resultats/ouverture.ras");
saveImage(&iFermeture,"../Resultats/fermeture.ras");
displayImage("../Resultats/fermeture.ras");
saveImage(&iMoyenne,"../Resultats/moyenne.ras");
displayImage("../Resultats/moyenne.ras");
saveImage(&iSegmentation,"../Resultats/segmentation.ras");
displayImage("../Resultats/segmentation.ras");
saveImage(&iSegmentationRandom,"../Resultats/segmentationRandom.ras");
displayImage("../Resultats/segmentationRandom.ras");
freeImage(&i0);
freeImage(&iSeuillage);
freeImage(&iSobel);
freeImage(&iErosion);
freeImage(&iDilatation);
freeImage(&iOuverture);
freeImage(&iFermeture);
freeImage(&iMoyenne);
freeImage(&iSegmentation);
freeImage(&iSegmentationRandom);
return 0;
}
53/53
Téléchargement