| Prima Homepage Ravi Homepage Le langage scml et la doc Ravi Le module modxdraw Installation Ravi sur Ensibull - PIA99 ImaLab |
ImaLabImaLab est un environnement d'expérimentation avec des images, notamment avec des images de pollen (imalab/pollen), et un environnement de développement d'applications complexes, comprenant analyse et interprétation. Nous décrivons quelques fonctionnalités utiles qui commencent à émerger:
Puis il faut aussi décrire l'environnement de programmation, puisque toute expérimentation passe par l'ajout de nouveaux programmes
En travaillant avec Imalab, on est toujours en train de regarder une image, une séquence d'images, des résultats d'opérateurs ou autres courbes. Les objets clé de notre expérimentation sont donc l'image courante, souvent aussi une séquence d'images, et la fenêtre d'affichage. La fenêtre a la forme d'une "page" sur laquelle on peut visualiser plusieurs images; ce sont les paramètres screen-cols, screen-lines. Des variables globales repèrent ces objects-clé: screen est la fenêtre d'affichage, current-image est l'image courante, ima-sequence est la séquence d'images. Bien entendu, ce sont des objets au sens C++; à présent, screen est un TTrueColor24Win, current-image est un TBitmapABGR, ima-sequence est un vecteur Scheme. Après l'initialisation, un certain nombre de variables globales donnent les informations essentielles sur ces objets:
Initialisation par fichier "mode C++": load-cppfile "name.cpp"
Les séquences d'images de pollen se trouvent dans plusieurs répertoires, indiqués par la variable dirlist. A titre d'exemple, voici les commandes pour visualiser une séquence d'olea:
La première commande, ls-seq "olea", indique les noms des séquences existants dans le répertoire olea. Ensuite, la deuxième commande load-sequence "olea005" charge en mémoire la séquence choisie, puis la commande defile(d) permet de voir défiler les images de la séquence. Les images de la séquence défilent avec un delai d entre 2 images; d n'est pas calibré: 50 produit un défilement assez lent, 10 est rapide. Pendant l'exécution de cette fonction, on contrôle le déroulement via le clavier.
En mode pas-à-pas
view-pages(n)La fonction view-pages() ou view-pages(n) permet de visualiser simultanément plusieurs images consécutives, en affichant screen-cols*screen-lines images dans la fenêtre. n est l'indice de la première image affichée initialement; si n est absent, on reprend la page telle quelle. L'écran doit au préalable être initialisé avec la commande init-screen(col,lin). Interaction avec des touches.
A faire rapidement: menus popup. Affichage de plusieurs séquences en "cinéma"multi-view(sn,s1,s2,i1,i2)sn est le nom d'un pollen (olea, etc.). On fait défiler les images des séquences s1 ... s2 de cette espece; pour chaque séquence on affiche les images i1 .. i2, avec le delai en vigueur.
Exemple type: afficher les images du laplacien de l'image courante, avec des filtrages différents, dans la fenêtre à partir de la position 1:
La fonction mu-affiche-lap sert à l'affichage multiple de laplaciens.
Affiche le laplacien, aux niveaux de filtrage i1,... sous forme d'une image à niveaux de gris (vert en négatif, jaune en positif) dans les position pos,pos+1,... de la fenêtre. Utilise les variables: lap-fact, lap-exp pour normaliser l'affichage;
Affiche le "signe du laplacien" du niveau n en position pos. Affichage ternaire: vert - négatif, jaune - positiv, noir - inférieur à eps. Affichage du niveau optimal du laplacien
affi-opt affiche dans des positions consécutives.
Les contoursOn définit un contour comme un passage par zéro du laplacien; les contours dépendent du filtrage utilisé pour le calcul du laplacien. Différentes fonctions permettent d'afficher tous les points de contours d'un niveau donné, ou de superposer les contours de plusieurs niveaux avec une image. D'autres fonctions suivent un contour fermé trouvé à partir d'un point de départ.
affiche les passages par zéro du niveau k à la position pos, ou pour plusieurs niveaux dans les positions pos,pos+1,... Si les paramètres color et n sont présent, les contours sont superposés avec l'image du laplacien de niveau n; ou, si n=true, avec l'image originale.
superpose les passages par zéro des niveaux k1,... à et les affiche à la position pos. Si le paramètre n est présent, le tout est superposé à l'image du laplacien du niveau n, ou à l'image originale, (comme pour la fonction précédente). Détection de lignes dans l'imageCes fonctions servent à expérimenter avec l'algorithme de recherche de contours fermés Ces contours forment toujours le bord d'un 8-connexe défini par un prédicat, comme par ex. "laplacien > eps". Les noms des fonctions contiennent un b pour border, et une lettre b-y-r pour le prédicat: green, yellow, ridge. b2 désigne le 2ième algorithme.
Exemple d'utilisation:
Dans cet exemple, lap-g-b(false,8,false,5) affiche un contour fermé défini par le "bord d'une zone verte" du laplacien. (Normalement, on affiche en vert les valeurs négatives). Les pixels affichés sont des pixels de frontière d'une région ayant une valeur du laplacien supérieur au seuil eps. Paramètres des fonctions. Paramètre point: la recherche du point initial se fait sur la droite du point donné en premier paramètre (voir la fonction get-point pour le gestion des points). Pour l'algorithme b2, la direction de la recherche est donnée par le paramètre dir. Le paramètre level indique le niveau du laplacien. Le paramètre color indique la couleur d'affichage (false indique le défaut, vert ou jaune). l'argument lpos2 est facultatif, il permet d'indiquer une position de l'écran pour un deuxième tracé du contour.
Pour l'affichage de courbes, on fait appel à gnuplot. Toutes les fonctions (presque) initialisent gnuplot si cela n'a pas déjà été fait. Fonctions d'affichages selon un segment de droite, voir saisie d'une ligne. Une première série de fonctions affiche des profils mulitples, selon différents niveaux de filtrage: gradient, gradient normalisé, laplacien, laplacien normalisé,
Une deuxième série de fonctions affiche des profils simples:
Des fonctions plus anciennes existent, avec un jeu de paramètres plus compliqué, notamment:
Affichage des profils du gradient en un point, pour plusieurs niveaux de filtrage. Le port à utiliser est gnu-port (sauf mise au point).
Mêmes paramètres que la fonction précédente. Affiche le gradient, et le laplacien.
Affichage du laplacien du point p, en fonction du niveau de filtrage. Affichage en reliefgnuplot et geomview permettent d'afficher sous forme de relief. Pour essayer, il y a les 2 fonctions, avec des paramètres analogues: zmesh-rect-float(rectangle,img,e) active geomview pour afficher sous forme de "zmesh" la fenêtre de l'image img définie par rectangle; e est un facteur d'échelle, permettant d'adapter la hauteur du relief. splot-rect-grid(rectangle,img,e) affiche sous forme d'une une "grille-3D" - un grid au sens de gnuplot - la fenêtre de l'image img définie par rectangle; e est un facteur d'échelle, permettant d'adapter la hauteur du relief. Ces fonctions initialisent geomview/gnuplot si besoin.
Qu'on veuille étudier une séquence d'images ou une seule image avec ImaLab, il faut savoir que de nombreuses initialisations doivent se faire dans un certain ordre. Grosso modo, il faut d'abord lire une image, ou une séquence; puis créer la fenêtre d'affichage, calculer les images filtrées, et ensuite on pourra tracer des courbes, afficher des graphiques. Il faut aussi lancer gnuplot, geomview, etc. De plus en plus, les initialisations sont faites automatiquement, selon les besoins, mais il est toujours utile de savoir ce qui doit se passer. Par exemple, les programmes ne peuvent pas deviner combien on veut avoir de places sur l'écran - par défaut, l'écran sera ridiculement petit, avec 1 seule place. On reprend dans ce paragraphe l'ordre usuel des opérations au démarrage de ImaLab. Lire une séquencels-seq "olea" liste les séquences existants dans un répertoire (sous-repertoire de asthma-images), et initialise la variable image-dir. La variable dirlist indique les répertoires qu'on peut lister ainsi. (Alain: en cas de modif, mettre à jour la valeur de dirlist dans le code). load-sequence "olea001"charge la séquence indiqué, dans le vecteur ima-sequence; le nom est toujours relatif a image-dir. On peut afficher les images pendant le chargement: load-sequence(name,true) Ensuite, on peut visualiser la séquence avec les fonctions defile et view-pages. Lors d'une même session avec ImaLab, on peut charger d'autres séquences ultérieurement, avec des dimensions différentes: toutes les structures de données s'adapteront. Lecture d'une sous-sequence load-subsequence(nom,i1,i2,visu)Le booléen visu indique si on veut visualiser la séquence pendant le chargement (cela évite d'attendre). La variable globale sequence-step permet de réduire la densité de la séquence, et de ne lire qu'une image sur n; cette variable vaut 1 initialement. Lecture des images de Nicolasnd-load-subsequence(nom,i1,i2,visu)Les paramètres sont les mêmes que pour la fonction load-subsequence ci-dessus, mais les images sont prises chez Nicolas, selon ses conventions: le nom - WORK1 par ex. - est le nom d'un repertoire dans nd-ima-path, les images ont pour nom sequence-testiii. La séquence est chargée dans ima-sequence, et peut ensuite être affichée, donnée aux opérateurs, etc. comme toute séquence. nd-show-subsequence(nom,i1,i2,visu)affiche seulement les images d'une séquence chez Nicolas, selon le gamma et le delai en vigueur. (Si le numéros des images sont difficiles à lire, penser à changer la couleur des graphiques - SetColor). Initialiser l'image couranteLa fonction image-setup effectue "les" calculs standard pour l'image
courante, et initialise un certain nombre de variables globales;
soit pour une image de la séquence:
image-setup(i) soit pour l'image current-image qui peut, par exemple, être
une image chargée directement; cela évite de s'encombrer
avec une séquence si on ne veut pas la visualiser.
Dans ce cas, on charge d'abord l'image:
current-image = load-tif("olea010_014"); Le nom de l'image est toujours relatif à la variable image-dir,
que l'on peut positionner, par exemple, en appelant
ls-seq.
puis on appèle image-setup() La fonction image-setup initialise les variables suivantes:
Les calculs de filtres multi-échelles se font avec les paramètres
et la fonction MultiFilter dans libFilter (module modFilter, fichier Filter2.cc)
Les fonctions d'affichage d'images sont nombreuses, voici les plus utiles: affiche1() affiche l'image courante, c.à d. l'image current-image. La fonction affiche1 tient compte de la valeur de la variable globale gamma. affiche1(i) affiche la i-ième image de la séquence courante. affiche-pos(ima,place,s) affiche une image ima à la place indiquée sur l'écran; place a une valuer entre 0 et screen-places, pour la 1ière, 2ième, ... place dans la fenêtre. La chaîne s (string) est affichée avec l'image, dans la couleur courante de l'écran (qu'on peut changer avec to-screen(SetColor "couleur")). show-tif(filename) charge une image dans current-image et l'affiche. La correction gammaPlusieurs fonctions - notamment defile, view-pages, affiche1, afficheixy - tiennent compte de la correction gamma; gamma est le nom d'une variable globale, on peut donc le changer à tout moment. affiche-gamma(i1,i2,p,g) affiche les images de la séquence courante, indices i1 à i2, avec un gamma g donné en paramètre, à partir de la place p de l'écran. Cela permet l'affichage aisée d'une ou plusieurs images avec des correctons différentes. D'autres fonctions d'affichage d'images
Méthodes de base pour l'affichageToutes les fonctions d'affichage fon appel à une méthode de la classe TTrueColor24Win dont l'écran screen est une instance (c'est facile à comprendre dans le code Scheme). Les méthodes existantes dans le code C++ prévoient des possibilités qui ne sont pas exploitées actuellement, comme l'affichage de sous-images, ou la copie de l'écran pour écriture dans un fichier. Ces méthodes sont:
Voir le code dans /net/orion/users/alux/GlobalVision/src/X11Win
On effectue très souvent plusieurs analyses concernant un point précis dans l'image, ou un segment de droite, ou un rectangle. Ces entités sont le plus souvent saisies à l'aide de la souris, puis réutilisées. Pour simplifier ce type de gestion, les points saisis avec la souris sont stockés dans une liste point-list, les lignes dans la variable line-list, les rectangles dans rectangle-list. Un exemple d'utilisation: une fonction qui prend comme argument une ligne, comme plot-mu-lap-profile; un premier appel, avec une ligne false, provoque la saisie avec la souris. Lors des appels suivants, on désigne cette même ligne pour le nombre 0. Pour connaitre le numero d'un point "plus ancien", il suffit de regarder la point-list et de repérer son indexe.
Tout argument nommé point, line, rectangle dans cette documentation fonctionne selon ce principe. Les fonctions en question, comme par exemple plot-mu-plot, mu-circle, font pour cela appel aux fonctions get-point, get-line, get-rectangle, resp. La fonction get-point permet d'obtenir les coordonnées d'un point. Sans argument, ce point est défini par un clic-souris. Ces coordonnées sont toujours relatives à l'image, cad. acquises modulo sequence-width et sequence-height.
Les fonctions get-line et get-rectangle sont analogues.
Bien entendu, on peut également garder des points dans des variables:
La fonction mu-circle affiche un cercle dans chacune des places dans la fenêtre, au même endroit.
La macro to-screen permet d'envoyer des commandes à la fenêtre. Chaque argument est un appel de méthode, écrit comme un appel de fonction.
ceci est strictement équivalent à:
Les commandes qu'on peut envoyer à l'écran sont (voir les méthodes de la classe TTrueColor24Win (GlobalVision/src/X11Win/UTrueColor24Win.hh). Elles correspondent directement à des fonctions X; par exemple, la commande DrawString appèle la fonction XDrawString documentée dans le Xlib Reference Manual (p.166).
Fonctions
La fonction init-gnuplot crée un pipe Unix vers gnuplot; ce pipe correspond au port-ravi gnuplot-port. En écrivant dans ce port, toute fonction peut commander gnuplot. La fonction to-gnu facilite l'envoi d'une commande courte; cette fonction envoie son argument,puis ajoute une fin de ligne et un flush. La fonction init-gnuplot est appelé automatiquement par les fonctions "splot-..." décrites ci-après, on n'a donc pas à s'en soucier. Le gnuplot-port est fermé automatiquement à la sortie de imalab. Possibilités d'affichage: splot-grid(port,img,x0,y0,l,e) affiche une grille 3-D (grid) représentant le relief d'une fenêtre carrée de l'image img. La fenêtre a pour point supérieur gauche (x0,y0) et le coté l; e est un facteur d'échelle, pour adapter l'allure du relief. Le port sera gnuplot-port; utiliser *scstdout* pour voir ce qui est envoyé à gnuplot. Cette fonction est analogue à la fonction zmesh-float (voir le paragraphe ci-après sur geomview). Exemple: laplacien d'une imagettesplot-grid(gnuplot-port,mflap[4],60,80,20,20) Commandes gnuplot utiles à connaitreA envoyer à l'aide de la fonction to-gnu (par exemple).
Pour plus de détail voir la brochure Gnuplot, version 3.7
La situation est parfaitement analogue à celle de gnuplot. Notamment, le fonctions init-geomwview, q-geomview sont appelées automatiquement selon besoin.
Possibilités d'affichage: Il y a plusieurs fonctions avec des paramètres plus ou moins identiques (même prototype pour les fonctions). zmesh-rect-float(rectangle,img,e) affiche sous forme de "zmesh" (relief quadrillé) la fenêtre de l'image img définie par rectangle; e est un facteur d'échelle, permettant d'adapter la hauteur du relief. zmesh-float(port,img,x0,y0,w,h,e) affiche sous forme de "zmesh" (relief quadrillé) une fenêtre de l'image img. La fenêtre a pour point supérieur gauche (x0,y0), largeur w, hauteur h; e est un facteur d'échelle, permettant d'adapter l'allure du relief. Le port sera geom-port, sauf mise au point. zmesh-byte(port,img,x0,y0,l,c) affiche de facon analogue le canal c d'un bitmap possedant des canaux (méthode GetPixelByte à 3 arguments).
pixrect(bmp,x0,y0,w,h,[ch]) affiche au terminal les pixels d'une imagette de bmp. L'argument optionnel ch permet d'indiquer un canal: 1-2-3 pour g-b-r. Sans l'argument canal, l'impression se fait en flottant. print-rectangle(rect,bmp[,ch])effectue la m^me opération pour un rectangle au sens du vec-segment(vec,i1,12)imprime un morceau d'un vecteur (classes TIntVector etc.)
La fonction image-setup() fait appel à quelques opérateurs de la librairie PrimaVision. Plus généralement, tous les opérateurs sont accessibles. Les fonctions les plus utiles dans cette librairie:
Cette fonction crée un vecteur d'images filtrées, avec des filtres de type "gaussien", pour différents sigmas. Les sigmas utilisés sont: Sinit* pow (Sfactor, indice) avec les indices: indice-init = init, indice-max = final step = freq. L'argument f code le type de filtre:
Ces constantes sont définies dans imalab.
image-setup effectue ce calcul, avec résultat dans voptsig.
calcule dans les étages e=0,1,... de vecdest des "byte-images binaires", c. à d. avec des valeurs 0/1, les pixels qui ont un max (par rapport à sigma) au niveau e.
(cf. livre de Marr, p.63).
Calculer un vecteur avec l' image filtrée:
puis afficher les différences avec
Pour ce qui est de la FFT, voir NR + Nicolas Nouvelle forme simplifiée, affiche l'image et les deux images partieR-partieI de la FFT:
Le résultat est la liste (ima-r ima-i ima-complex). ima-comples sert ensuite d'argument à iFFT.
imalab comprend un ensemble de modules Ravi. |