Alexandre Alapetite & Pierre Cohade   25/03/2003

BE de traitement d'image "Aphelinux"

Sommaire

Quitter

Introduction

Le projet consiste à développer des opérateurs de traitement d'images en C, en utilisant la bibliothèque Limace pour les entrées-sorties. Les opérateurs devront être regroupés dans une bibliothèque et les étudiants pourront alors s'échanger leurs travaux, chaque groupe faisant une série d'opérateurs différents.

Sommaire

Opérateurs

Voici les différents opérateurs qu'il nous a été donnée d'implémenter, plus quelques uns par lesquels nous avons commencé, afin de prendre contact avec la bibliothèque Limace.

Sommaire

Opérateurs élémentaires divers

ImgClearBorder(Image im)
Met à 0 les bords de l'Image im (binaire ou niveaux de gris)
ImgEqual(Image im1, Image im2)
Retourne vrai si im1 et im2 (binaires ou niveaux de gris) sont deux Image identiques, faut sinon
ImgNot(Image im)
Inverse logique (non logique) de cette image
ImgBitNot(Image im)
Inverse binaire (non binaire) de cette image
ImgAnd(Image im1, Image im2)
Et logique de cette image avec la seconde
ImgBitAnd(Image im1, Image im2)
Et binaire de cette image avec la seconde
ImgOr(Image im1, Image im2)
Ou logique de cette image avec la seconde
ImgBitOr(Image im1, Image im2)
Ou binaire de cette image avec la seconde
Sommaire

Opérateurs plus complexes

ImgCountObjects(Image im)
Compte le nombre d'objets présents dans l'image im (binaire ou niveau de gris)
ImgLabelliseObjects(Image im1, Matrix mt1)
Labellise les différents objets présents dans l'image im1 (binaire ou niveau de gris)

Si nous avions eu un peu plus de temps, nous aurions traité l'opérateur "érodée ultime" pour lequel il est nécessaire de compter le nombre d'objets présents. Voici donc un opérateur permettant de compter le nombre d'objets d'une image binaire ou en niveaux de gris. (Un objet est un ensemble connexe de pixels supérieurs à 0). La programmation de cet opérateur est efficace, en une seule passe, itératif (sans récursivité sur les pixels voisins) utilisant le masque antérieur de chaque pixel.
L'opérateur permettant de labelliser les objets étant un algorithme très similaire à celui pour compter, nous l'avons aussi implémenté.

Sommaire

Épaississement

ImgFillConcav(Image im)
Remplit les concavités
ImgThicken(Image im)
Opérateur d'épaississement sur l'image im

Le résultat d'un épaississement est une image où toutes les formes ont été propagées dans toutes les directions.

Remplir les concavités

On procède d'abord à un remplissage des concavités, par un masque   1 X X
1 • 1
1 1 X

avec rotation du masque dans les 8 positions possibles où les pixels qui satisfont le masque sont mis à 1.
En effet, la méthode d'épaississement accentue les concavités, si elles ne sont pas traitées, comme on peut le voir sur ces échantillons.

originalépaississement sans traiter les concavitésépaississement en traitant les concavités
image d'origine6 itérations
d'épaississement sans
traiter les concavités
6 itérations d'épaississement
en remplissant les concavités
de taille 1 à chaque itération

Le traitement est efficace, mais visiblement, le traitement de concavités de taille supérieures à 1 pourrait être utile, selon le choix de l'utilisateur.
Dans ce but, notre opérateur de remplissage de concavités peut être appelé séparément.

L'épaississement proprement dit

L'épaississement se fait par un masque   1 1 1
X • X
0 0 0

avec rotation du masque dans les 8 positions possibles où les pixels qui satisfont le masque sont mis à 0.
Il y a huit parcours de l'image (un par masque), car il n'a pas été possible d'appliquer les différents masques en parallèle.

Sommaire

Amincissement

ImgThin(Image im)
Opérateur d'amincissement sur l'image im
L'amincissement, lui, peut être appliqué directement, sans se soucier des concavités par un masque   1 1 1
X • X
0 0 0

avec rotation du masque dans les 8 positions possibles où les pixels qui satisfont le masque sont mis à 1. C'est l'inverse de l'épaississement. Là aussi, il y a huit parcours de l'image (un par masque), car il n'a pas été possible d'appliquer les différents masques en parallèle.

originalamincissement
image d'origine6 itérations
d'amincissement

On voit que cet opérateur crée des extrémités. C'est une différence avec l'érosion, car l'amincissement ne rogne pas les extrémités.

Sommaire

Squelette par amincissement

Il y a plusieurs définitions correspondant au squelette. Mais il nous a semblé important que notre squelette conserve les formes connexes, car c'est une propriété du squelette fréquemment utilisée. Notons que Aphelion ne conserve pas cette propriété, comme vu en TP.
Notre squelettisation fonctionne par amincissements successifs jusqu'à stabilité.

originalsquelette
image d'originesquelettisation

On voit ici l'importance que l'amincissement ne supprime pas les extrémités.
Cette méthode est relativement efficace pour des formes minces, mais requiert un grand nombre d'itérations sur des formes épaisses (½ diamètre).

Sommaire

Gestion de script

Nos opérateurs sont regroupés dans une bibliothèque, mais afin de pouvoir les tester, nous avons fait un programme capable d'interpréter un script, et d'appeler les opérateurs correspondants.
L'appel se fait très facilement.
ex: D:\aphelinux>aphelie script.txt
Et voici un exemple de script :

//ma première variable
Image image1
//ma deuxième variable
Image im2
image1.loadFromFile("pcb.pbm") //charge l'image de ce nom
image1.ImgCountObjects() //je compte le nombre d'objets de image1
image1.saveToFile("pcb2.pbm") //sauve l'image
im2.loadFromFile("pcb2.pbm")
image1.ImgEqual("im2")
image1.ImgNot()
image1.ImgEqual("im2")
image1.free() //libère la mémoire allouée à image1
im2.ImgThinSkeleton() //applique la squelettisation sur l'image im2
im2.saveToFile("testSkeleton.pbm")
im2.free()

L'interpréteur de script a été écrit en Lex & Yacc puis intégré au programme principal. Le choix de ces outils a été fait dans le but de pouvoir enrichir le moteur de script facilement a d'autres fonctions, et a d'autres fonctionnalités, tout en gardant beaucoup de flexibilité. En outre, le développement est beaucoup plus rapide que "à la main".

Sommaire

Conclusion

Les masques vus en cours pour l'amincissement et l'épaississement sont issus d'une conversion de masques pour des matrices hexagonales. Nous avons comparé plusieurs variantes et choisi des masques qui donnaient les résultats théoriques attendus.
Ce projet nous a permis de mieux comprendre les opérateurs vus en cours.
Nous avons ainsi un peu recollé avec l'implémentation, et les problèmes d'optimisation cruciaux dans les lourdes fonctions de traitement d'image.
Cela a permis de nous sensibiliser à l'utilité d'un code propre, standard, multi-plateforme (notre programme a été compilé avec GCC, VCC, BCC sous Windows et Linux). Vous pouvez consulter les sources (zip 122Ko)

Sommaire
https://alexandre.alapetite.fr

Quitter