télécharger 49.02 Kb.
|
TP Traitement d’images applications de traitement d’images Sujets abordés: application, librairie, système, JAI 1.IntroductionLes problèmes de traitement d’images sont intrinsèquement complexes. Ils ne peuvent être résolus par l’utilisation d’un seul algorithme de traitement d’images aussi sophistiqué soit-il, il est souvent nécessaire d’avoir recours un enchaînement de traitements. On qualifie alors « usuellement » d’application le programme contrôlant cet enchaînement. Une application peut donc être considérée comme une surcouche logicielle pour le pilotage de un ou de plusieurs traitement(s) d’images. L’ensemble application + traitement(s) est alors qualifié de « système ». ![]() Il est souvent difficile pour un programmeur de réaliser l’ensemble des traitements nécessaires à son application. Aussi, dans la pratique, on a recours à des librairies de traitements d’images. Ces dernières regroupent, sous forme de bibliothèques de programmes, différents traitements d’images. Reste (seulement) à la charge du programmeur la réalisation de son application. Les systèmes ont généralement pour vocation d’être utilisés dans des contextes industriels. Aussi, les librairies de traitements d’images et applications sont le plus souvent implémentées dans des langages de programmation procéduraux ou orientés objet comme le C, C++, Java, etc. Dans ce TP, on se propose d’étudier et de mettre en oeuvre une librairie de traitements d’images Java pour la conception d’applications : la Java Advanced Imaging (JAI). Ce TP aborde différents aspects liés à la JAI: installation, représentation des images, mise en oeuvre des opérateurs, accès et manipulation des pixels. 2.Introduction à la JAILa JAI est une librairie de traitement d’image Java distribuée par Sun et libre de droit d’utilisation. Cette librairie est en fait une surcouche à la librairie standard java.awt.image de la plateforme J2SDK. Elle regroupe un nombre « conséquent » de traitements d’images et propose des possibilités d’extension1. Son implémentation Java en assure une portabilité aisée. De plus, nombre de traitements sont implémentés nativement. L’utilisation de ces implémentations natives est alors gérée automatiquement par la JAI de façon transparente pour l’utilisateur. Ceci rend donc la JAI aussi performante (en terme de temps de calcul) que des librairies écrites en C/C++. Enfin, la JAI propose un mécanisme original de gestion de graphes d’opérateursError: Reference source not found. Toutes ces caractéristiques font de la JAI une librairie attractive de plus en plus utilisée pour l’implémentation de systèmes de traitement d’images [1]. Un tutorial de la JAI peut être trouvé dans [2]. La JAI est disponible à l’adresse [1]. Elle est également fournies dans l’archive (Fichier) utilisé pour vos TP de traitement d’images. Différentes ressources sont proposées, nous présentons ici les quatre principales :
Remarque : Le guide de la JAI évolue indépendamment des versions de la JAI, il n’est pas systématiquement remis à jour. Certains exemples d’utilisation seront donc à adapter. A ces ressources on se doit d’ajouter L’API documentation de la plateforme J2SDK concernant le package java.awt.image. Les informations concernant ce package constitue en effet un complément de documentation nécessaire à une bonne compréhension de la JAI. La JAI se compose de différents packages, nous décrivons ici les principaux :
Question : Effectuer l’installation de la JAI sur votre machine ainsi que des documentations associées. Vous pourrez vérifier le fonctionnement de cette installation en compilant le programme suivant : import javax.media.jai.*; public class Test { public static void main(String[] args) {} } Il faut pour cela que les (.jar) aient été installés préalablement dans le répertoire d’extension j2sdkx.x.x\jre\lib\ext. Vous pouvez également compiler ce programme à l’aide de l’instruction suivante sans installation préalable des (.jar) si ceux-ci se trouvent dans votre répertoire de travail. javac -classpath jai_core.jar;jai_codec.jar;mlibwrapper_jai.jar Test.java java -cp .\;jai_core.jar;jai_codec.jar;mlibwrapper_jai.jar Test 3.Représentation des imagesLes algorithmes de traitement d’image requièrent l’utilisation d’objet image. Dans cette section, nous présentons les différentes classes utilisées par la JAI pour l’instanciation de ces objets. Les images de la JAI peuvent être multidimensionnelles (c.-à-d. avec plusieurs valeurs associées à un seul pixel) et codées de différentes façons (booléen, entier, en flottant, etc.). Différents modèles de couleur peuvent également être utilisés. De façon à représenter l’ensemble des codages possibles la JAI repose sur l’utilisation d’une variété de classes. Nous présentons ici une description des principales :
![]()
![]() 4.Opérateurs JAIChaque mise en oeuvre d’un traitement d’image donné dans la JAI se fait par appel d’un opérateur spécifique. La JAI propose un nombre « conséquent » d’opérateurs, la mise en oeuvre de ces derniers nécessite un coût minimum de programmation. Elle s’effectue en effet par simple appel de la méthode statique create de la classe JAI. Le code suivant en donne un exemple d’appel de trois opérateurs pour la lecture, l’inversion et l’écriture d’image. import javax.media.jai.*; public class Test { public static void main(String[] args) { PlanarImage img; img = JAI.create("fileload", "woman.bmp"); img = JAI.create("invert", img); JAI.create("filestore",img,"result.bmp"); } } Il existe différents opérateurs dans la JAI regroupés en 8 familles principales. L’ensemble de ces opérateurs est décrit dans la section (3.6) du guide de la JAI. Le tableau suivant présente brièvement ces familles.
Question : Exécuter le tutorial d’utilisation de la JAI afin de mettre en oeuvre ces différentes familles d’opérateurs, commenter les différents exemples. Tenter de reproduire cette image sans le paysage à partir de la démonstration sur l’ajout d’image. ![]() On se propose maintenant de mettre en œuvre différents opérateurs de la JAI pour résoudre un jeu « chercher les différences ». Ce type de jeux est fréquemment présenté dans les magazines de loisirs. Le but en est de chercher un nombre fixé de différences entre une image et son homologue légèrement modifié. Comme toujours dans ce type de jeu, la difficulté de recherche est graduelle. Certaines différences sont évidentes alors que d’autres sont difficiles à identifier. Elles sont même parfois jugées discutables par les lecteurs après analyse des solutions des magazines. C’est le cas des deux images ci-dessous qui comportent 8 différences dont l’une d’entre elles semble difficilement identifiable. ![]() ![]() Question : Mettre en oeuvre l’opérateur substract de la JAI pour effectuer la comparaison de ces deux images. Expliquer pourquoi un seul appel de cet opérateur n’est pas suffisant pour résoudre ce problème. Il est pour cela nécessaire de comprendre le rôle de l’opérateur clamp au sein de l’opérateur substract, détailler le problème. Proposer une solution employant une double soustraction et une combinaison de ces soustractions avec l’opérateur add. Identifier au moins 7 différences à partir de l’analyse des régions résultantes de votre comparaison. Afin de rendre le résultat plus visible vous pourrez utiliser l’opérateur invert. Certains des opérateurs nécessitent la définition de paramètres complexes. De façon à alléger les instructions de commande de ces opérateurs, la JAI permet l’utilisation d’objets ParameterBlock. La classe ParameterBlock est en fait définie dans le package java.awt.image.renderable. Les objets ParameterBlock correspondent à des vecteurs de données spécifiant les différents paramètres d’un opérateur. Ils servent alors d’argument à la méthode create de la classe JAI pour leur lancement. Le code suivant donne un exemple d’utilisation d’un objet ParameterBlock. import javax.media.jai.*; import java.awt.image.renderable.* ; public class Test { public static void main(String[] args) { PlanarImage img = JAI.create("fileload", "woman.bmp"); ParameterBlock pb = new ParameterBlock(); pb.addSource(img); pb.add((float)128); pb.add((float)128); pb.add((float)Math.PI/4); pb.add(new InterpolationBilinear()); img = JAI.create("rotate", pb); JAI.create("filestore",img,"result.bmp"); } } Question : Mettre en oeuvre l’opérateur threshold de la JAI par définition d’un objet ParametterBlock afin de faire ressortir l’image des différences obtenue précédemment. On rappelle que pour une image en niveaux de gris le codage blanc est à 255 et le noir à 0. N’hésiter pas à spécifier un seuillage fort (supérieur à 200) pour faire ressortir les zones de différence. Indiquer la huitième différence. 5.Accès aux données de l’imageAfin de concevoir des algorithmes de traitement d’image images il est nécessaire d’accéder à leurs pixels. De par la représentation des images employée par la JAI, l’accès et la modification des pixels d’une image nécessitent différentes opérations. Tout d’abord, afin d’obtenir les informations à propos des images manipulées, différentes méthodes des classes PlanarImage, SampleModel et ColorModel doivent être utilisées. Le code suivant illustre la mise en oeuvre des principales : import java.awt.image.*; import java.awt.image.renderable.* ; import javax.media.jai.*; public class Test { public static void main(String[] args) { PlanarImage img = JAI.create("fileload", "woman.bmp"); System.out.print("width: "+img.getWidth()+"\n"); System.out.print("height: "+img.getHeight()+"\n"); switch(img.getSampleModel().getDataType()) { case DataBuffer.TYPE_BYTE: System.out.println("byte"); break; case DataBuffer.TYPE_SHORT: System.out.println("short"); break; case DataBuffer.TYPE_USHORT: System.out.println("ushort"); break; case DataBuffer.TYPE_INT: System.out.println("int"); break; case DataBuffer.TYPE_FLOAT: System.out.println("float"); break; case DataBuffer.TYPE_DOUBLE: System.out.println("double"); break; CaseDataBuffer.TYPE_UNDEFINED: System.out.println("undefined"); break; } System.out.print("pixel size: "+img.getColorModel().getPixelSize()+"\n"); } } Basé sur l’exploitation de ces informations, la JAI propose deux modes d’accès à l’image : l’accès directe par parcours du raster ou l’accès par itérateur. La différence entre ces deux modes réside majoritairement dans la gestion des bandes couleur des images. Dans ce TP nous nous positionnons majoritairement sur la gestion d’image en niveaux de gris. Aussi, nous ne présenterons que l’accès direct2. Le code suivant en donne un exemple. Cet accès repose sur l’utilisation de la méthode getData de la classe PlanarImage. Cette dernière permet en effet de récupérer l’objet Raster de l’image. Celui-ci est alors utilisé afin de récupérer un tableau de données via la méthode getPixels correspondant aux pixels de l’image. Ce tableau étant de dimension 1D, il nécessite la gestion d’un offset pour son parcours. PlanarImage img = JAI.create("fileload", "small.bmp"); int width = img.getWidth(), height = img.getHeight(); Raster raster = img.getData(); int[] pixels = new int[width*height]; raster.getPixels(0,0,width,height,pixels); for(int y=0;y for(int x=0;x System.out.print(pixels[width*y+x]+" "); System.out.println(); } Remarque : Ce code n’est valable que pour des images en niveaux de gris L’écriture des images se révèle plus technique de mise en oeuvre. En effet, les objets PlanarImage et Raster ne sont accessibles qu’en lecture seule. L’objectif est alors de les convertir en TiledImage et WritableRaster qui sont eux modifiables en écriture. Les objets TiledImage et WritableRaster créés doivent respecter une structure identique aux objets initiaux PlanarImage et Raster. Pour cela, on utilise la méthode createCompatibleWritableRaster de la classe Raster. Les méthodes setPixels et setData de la classe Raster sont ensuite utilisées pour l’écriture du tableau de pixels. Le code suivant donne un exemple de lecture d’une image, d’inversion de ses pixels et d’écriture de l’image résultat. PlanarImage imgi = JAI.create("fileload", "small.bmp"); int width = imgi.getWidth(), height = imgi.getHeight(); Raster inputRaster = imgi.getData(); int[] pixels = new int[width*height]; inputRaster.getPixels(0,0,width,height,pixels); for(int y=0;y for(int x=0;x pixels[width*y+x] = 255 - pixels[width*y+x]; WritableRaster outputRaster = inputRaster.createCompatibleWritableRaster(); outputRaster.setPixels(0,0,width,height,pixels); TiledImage imgr = new TiledImage(imgi,1,1); imgr.setData(outputRaster); JAI.create("filestore",imgr,"result.bmp"); Question : À partir des exemples présentés dans cette section, implémenter un algorithme permettant de résoudre le problème de recherche de différences entre images résolu précédemment. Cet algorithme devra gérer en une passe les soustractions, l’addition, l’inversion et le seuillage. Question : On se propose d’améliorer l’algorithme précédent en y introduisant un principe de comparaison par zone. L’idée est d’effectuer des comparaisons entre zones des images en tenant compte du voisinage 33 ou 55. Pour ce faire il est conseillé de concevoir une classe Matrix qui, à partir du tableau de pixels 1D extrait du raster, se chargera de la gestion 2D. Implémenter votre algorithme, donner vos résultats par prise en compte des voisinages 33 ou 55. Indiquer pourquoi la prise en compte du voisinage 33 pose des problèmes pour la huitième différence. 6.BibliographieQuelques références bibliographiques disponibles sur Internet : [1] Sun MicroSystem. JAI homepage. http://java.sun.com/products/java-media/jai/ [2] R. Santos. Java Advanced Imaging API: A Tutorial. Divisão de Sensoriamento Remoto, Instituto de Estudos Avançados, Centro Técnico Aeroespacial, São Paulo, Brasil, 2004. 1 Nous n’arborerons pas ces aspects dans ce TP. 2 Nous reportons les lecteurs à [2] pour plus d’information pour l’accès par itérateur. |
![]() | «Justice et Affaires intérieures» : participation en tant que de besoin du Ministre au conseil jai, du Directeur de la dfae au groupe... | ![]() | «Retourne donc là d’où tu viens ! Va te faire agent de change à Hira comme les tiens ! Mais ne te mêle surtout pas d’étudier la médecine,... |
![]() | ![]() | ||
![]() | ![]() | ||
![]() | ![]() | ||
![]() | ![]() |