leval_volume.c

Go to the documentation of this file.
00001 /*
00002 *    Copyright (c) 2007. The BATI team. All right reserved.
00003 *
00004 *    This file is part of BATI library.
00005 *
00006 *    BATI library is free software: you can redistribute it and/or modify
00007 *    it under the terms of the GNU General Public License as published by
00008 *    the Free Software Foundation, either version 3 of the License, or
00009 *    (at your option) any later version.
00010 *
00011 *    BATI library  is distributed in the hope that it will be useful,
00012 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *    GNU General Public License for more details.
00015 *
00016 *    You should have received a copy of the GNU General Public License
00017 *    along with BATI library.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00033 #include "eval_volume.h"
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <math.h>
00037 
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <fcntl.h>
00041 #include <unistd.h>
00042 #include <string.h>
00043 
00044 #define ETMAX 17000000 
00045 
00046 #define ABSOL(x,y)  (((x) > (y))? abs(x-y) : abs(y-x))
00047 #define MAX(x,y) (((x)>(y))? (x):(y))
00048 #define MIN(x,y) (((x)<(y))? (x):(y))
00049 #define MIN3(x,y,z) ( ( ((x)<(y))&&((x)<(z))   )?(x):( ( ((x)>(y))&&((y)<(z))  )?y:z  )  )
00050 #define VRAI 1
00051 #define FAUX 0
00052 
00053 typedef char booleen;
00054 
00055  
00056 
00067 param* eval_volume_lect(eval_volume_t* des, param* ptp, char* debq){
00068   char question[500];
00069 
00070   sprintf(question, "%s Classe a etudier (niveau de gris)", debq); 
00071   lec_param(question, ptp);
00072   des->classe = atoi(ptp->rep);
00073   ptp = ptp->next;
00074   
00075   return(ptp);
00076 }
00077 
00078 
00079 
00080 
00081 
00098 int eval_volume_init(eval_volume_t* des, ima3Du1* imaIn){
00099 
00100   /* Allocation de l'image résultat dans le descripteur*/
00101   des->ima_etiq = (ima3Du8 *)malloc(sizeof(ima3Du8));
00102   des->ima_etiq->dimx = imaIn->dimx;
00103   des->ima_etiq->dimy = imaIn->dimy;
00104   des->ima_etiq->dimz = imaIn->dimz;
00105   des->ima_etiq->lgtete = imaIn->lgtete;
00106   des->ima_etiq->dept = imaIn->dept;
00107   allouer_ima3Du8 (des->ima_etiq);
00108 
00109 }
00110 
00111 
00112 
00113 /*
00114   Gestion de l'équivalence entre deux étiquettes (a et b) dans la liste de chainage.
00115   Principe:
00116   On recherche l'étiquette minimum entre a et b. C'est cette étiquette qui sera
00117   utilisé pour le pixel courant ainsi que pour matérialiser l'équivalence.
00118   Puis les deux étiquettes sont traitées de la meme facon: si l'équivalence pour 
00119   l'étiquette a est différente du minimum alors sauvegarder l'équivalence existante 
00120   et ecrire le minimum. Ce traitement est ensuite reappliqué sur l'étiquette de 
00121   l'équivalence sauvgardée jusqu'a retrouver l'étiquette minimum dans la liste 
00122   de chainage.
00123     @param pt_etiq  pointeur sur la liste de chainage
00124     @param a  premiere etiquette
00125     @param b  deuxième etiquette
00126 
00127 
00128   Le but est de conserver la plus petite des 2 étiquettes comme l'étiquette qui
00129   représentera l'équivalence. Cette étiquette va etre remplacee dans toute la chaine
00130   descendante (vers la gauche du tableau).
00131 
00132   exemple: 
00133   indice:   1 2 3 4 5 6 7 8 9
00134   chainage: 1 2 3 2 5 2 7 8 1
00135   
00136   Le résultat de l'équivalence entre 8 et 6 donnera:
00137   indice:   1 2 3 4 5 6 7 8 9
00138   chainage: 1 6 3 2 5 6 7 6 1
00139 
00140 
00141 */
00142 unsigned long int eval_equivalence_2_label( unsigned  long int *pt_etiq, 
00143                                             unsigned  long int  a, 
00144                                             unsigned  long int  b){
00145   
00146   unsigned long  int minimum;
00147   unsigned long  int beta;   /*étiquette en cours de traitement*/
00148   unsigned long  int tmp;    /*sauvegarde des équivalences existants*/
00149   
00150   minimum = MIN(a,b);
00151 
00152   beta = a;
00153   while( pt_etiq[beta]!= minimum){
00154     tmp = pt_etiq[beta];
00155     pt_etiq[beta] = minimum;
00156     beta = tmp;
00157   }
00158 
00159   beta = b;
00160   while( pt_etiq[beta]!= minimum){
00161     tmp = pt_etiq[beta];
00162     pt_etiq[beta] = minimum;
00163     beta = tmp;
00164   }
00165 
00166   return( minimum);
00167 
00168 }
00169 
00170 
00171 
00172 
00173 
00174 /*
00175   Meme traitement que pour l'équivalence de deux étiquettes,
00176   mais pour trois.
00177 */
00178 unsigned long  int eval_equivalence_3_label( unsigned long  int *pt_etiq, 
00179                                         unsigned long  int a, 
00180                                         unsigned long  int b,
00181                                         unsigned long  int c){
00182   
00183   unsigned long  int minimum;
00184   unsigned long  int beta;
00185   unsigned long  int tmp;
00186   
00187   minimum = MIN3( a, b, c);
00188 
00189   beta = a;
00190   while( pt_etiq[beta]!= minimum){
00191     tmp = pt_etiq[beta];
00192     pt_etiq[beta] = minimum;
00193     beta = tmp;
00194   }
00195 
00196   beta = b;
00197   while( pt_etiq[beta]!= minimum){
00198     tmp = pt_etiq[beta];
00199     pt_etiq[beta] = minimum;
00200     beta = tmp;
00201   }
00202 
00203   beta = c;
00204   while( pt_etiq[beta]!= minimum){
00205     tmp = pt_etiq[beta];
00206     pt_etiq[beta] = minimum;
00207     beta = tmp;
00208   }
00209   return( minimum);
00210 
00211 }
00212 
00213 
00214 
00215 
00216 
00217 /*
00218 Rappel sur la composition de la variable cas:
00219  __________________________________________
00220 | 0 | 0 | g-h | a-g | a-h | g-c | h-c | a-c|
00221 --------------------------------------------
00222 
00223 Les bits 0 à 5 sont a 1 si la différence est inférieure au seuil
00224 
00225 
00226 Action a réaliser en fonction des différents cas possibles: 4 actions possibles
00227 - nouvelle etiquette                   c <-- new_etiq()
00228 - étiquette du voisin sans équivalence c <-- etiq[a]
00229 - equivalence entre deux étiquettes    c <-- equiv(a,g)
00230 - équivalence entre trois étiquettes   c <-- equiv(a,g,h)
00231 Les cas non marqué ci-dessous sont des équivalence entre trois étiquettes.
00232 
00233 -- 0--0000 0000---                  c <-- new_etiq()
00234 --------------------
00235 -- 1--0000 0001--a,c--              c <-- etiq[a]
00236 -- 2--0000 0010--h,c--              c <-- etiq[h]
00237 -- 3--0000 0011--h,c-a,c--          c <-- equiv(a,h)
00238 -- 4--0000 0100--g,c--              c <-- etiq[g]
00239 -- 5--0000 0101--g,c-a,c--          c <-- equiv(a,g)
00240 -- 6--0000 0110--g,c-h,c--          c <-- equiv(g,h)
00241 -- 7--0000 0111--g,c-h,c-a,c--
00242 -- 8--0000 1000--a,h--              c <-- new_etiq()
00243 -- 9--0000 1001--a,h-a,c--          c <-- equiv(a,h)
00244 --10--0000 1010--a,h-h,c--          c <-- equiv(a,h)
00245 --------------------
00246 --11--0000 1011--a,h-h,c-a,c--      c <-- equiv(a,h)
00247 --12--0000 1100--a,h-g,c--          c <-- etiq[g]
00248 --13--0000 1101--a,h-g,c-a,c--
00249 --14--0000 1110--a,h-g,c-h,c--
00250 --15--0000 1111--a,h-g,c-h,c-a,c--
00251 --16--0001 0000--a,g--              c <-- new_etiq()
00252 --17--0001 0001--a,g-a,c--          c <-- equiv(a,g)
00253 --18--0001 0010--a,g-h,c--          c <-- etiq[h]
00254 --19--0001 0011--a,g-h,c-a,c--
00255 --20--0001 0100--a,g-g,c--          c <-- equiv(a,g)
00256 --------------------
00257 --21--0001 0101--a,g-g,c-a,c--      c <-- equiv(a,g)
00258 --22--0001 0110--a,g-g,c-h,c--
00259 --23--0001 0111--a,g-g,c-h,c-a,c--
00260 --24--0001 1000--a,g-a,h--          c <-- new_etiq()
00261 --25--0001 1001--a,g-a,h-a,c--
00262 --26--0001 1010--a,g-a,h-h,c--
00263 --27--0001 1011--a,g-a,h-h,c-a,c--
00264 --28--0001 1100--a,g-a,h-g,c--
00265 --29--0001 1101--a,g-a,h-g,c-a,c--
00266 --30--0001 1110--a,g-a,h-g,c-h,c--
00267 --------------------
00268 --31--0001 1111--a,g-a,h-g,c-h,c-a,c--
00269 --32--0010 0000--g,h--              c <-- new_etiq()
00270 --33--0010 0001--g,h-a,c--          c <-- etiq[a]
00271 --34--0010 0010--g,h-h,c--          c <-- equiv(g,h)
00272 --35--0010 0011--g,h-h,c-a,c--
00273 --36--0010 0100--g,h-g,c--          c <-- equiv(g,h)
00274 --37--0010 0101--g,h-g,c-a,c--
00275 --38--0010 0110--g,h-g,c-h,c--      c <-- equiv(g,h)
00276 --39--0010 0111--g,h-g,c-h,c-a,c--
00277 --40--0010 1000--g,h-a,h--          c <-- new_etiq()
00278 --------------------
00279 --41--0010 1001--g,h-a,h-a,c--
00280 --42--0010 1010--g,h-a,h-h,c--
00281 --43--0010 1011--g,h-a,h-h,c-a,c--
00282 --44--0010 1100--g,h-a,h-g,c--
00283 --45--0010 1101--g,h-a,h-g,c-a,c--
00284 --46--0010 1110--g,h-a,h-g,c-h,c--
00285 --47--0010 1111--g,h-a,h-g,c-h,c-a,c--
00286 --48--0011 0000--g,h-a,g--                c <-- new_etiq()
00287 --49--0011 0001--g,h-a,g-a,c--
00288 --50--0011 0010--g,h-a,g-h,c--
00289 --------------------
00290 --51--0011 0011--g,h-a,g-h,c-a,c--
00291 --52--0011 0100--g,h-a,g-g,c--
00292 --53--0011 0101--g,h-a,g-g,c-a,c--
00293 --54--0011 0110--g,h-a,g-g,c-h,c--
00294 --55--0011 0111--g,h-a,g-g,c-h,c-a,c--
00295 --56--0011 1000--g,h-a,g-a,h--            c <-- new_etiq()
00296 --57--0011 1001--g,h-a,g-a,h-a,c--
00297 --58--0011 1010--g,h-a,g-a,h-h,c--
00298 --59--0011 1011--g,h-a,g-a,h-h,c-a,c--
00299 --60--0011 1100--g,h-a,g-a,h-g,c--
00300 --------------------
00301 --61--0011 1101--g,h-a,g-a,h-g,c-a,c--
00302 --62--0011 1110--g,h-a,g-a,h-g,c-h,c--
00303 --63--0011 1111--g,h-a,g-a,h-g,c-h,c-a,c--
00304 
00305 */
00306 
00307 void eval_label_management( unsigned char cas,           /*le cas a traiter*/
00308                        unsigned long  int haut,     /*l'étiquette du haut si elle existe*/
00309                        unsigned long  int gauche,   /*l'étiquette de la gauche si elle existe*/
00310                        unsigned long  int avant,    /*l'étiquette de la section d'avant si elle existe*/
00311                        unsigned long  int *courant, /*pointeur sur la case contenant l'étiquette 
00312                                                       courante a déterminer (dans l'image des étiquette)*/
00313                        unsigned long  int *pt_etiq, /*pointeur sur le tableau permettant le 
00314                                                       chainage des étiquettes*/
00315                        unsigned long  int *nb_etiq  /*nombre d'étiquettes deja utilisées*/
00316             ) 
00317 {
00318   
00319   
00320   if(cas>=64) printf("PROBLEME\n");
00321 
00322   switch (cas) {
00323 
00324   case 0: 
00325   case 8:
00326   case 16:
00327   case 24:
00328   case 32:
00329   case 40:
00330   case 48:
00331   case 56:
00332     /* on attribue une nouvelle etiquette*/
00333     {
00334       *nb_etiq +=1;
00335       if(*nb_etiq>ETMAX-1) *nb_etiq=ETMAX-1;
00336       *courant = *nb_etiq;
00337       return;
00338     }
00339 
00340   case 1:
00341   case 33:
00342     /*  propagation de l'etiquette avant*/
00343     {
00344       *courant = pt_etiq[avant];
00345       return;
00346     }
00347 
00348   case 2: 
00349   case 18:
00350     /* propagation de l'etiquette du haut*/
00351     {
00352       *courant = pt_etiq[haut];
00353       return;
00354     }
00355 
00356   case 4 : 
00357   case 12:
00358     /* propagation de l'etiquette de gauche*/
00359     {
00360       *courant = pt_etiq[gauche];
00361       return;
00362     }
00363     
00364   case 3:
00365   case 9:
00366   case 10:
00367   case 11:
00368     /*equivalence entre avant et haut*/
00369     {
00370       *courant = eval_equivalence_2_label( pt_etiq, avant, haut);
00371       return;
00372     }
00373 
00374 
00375   case 5:
00376   case 17:
00377   case 20:
00378   case 21:
00379     /*equivalence entre avant et gauche*/
00380     {
00381       *courant = eval_equivalence_2_label(pt_etiq, avant, gauche);
00382       return;
00383     }
00384 
00385   case 6:
00386   case 34:
00387   case 36:
00388   case 38:
00389     /*equivalence entre gauche et haut*/
00390     {
00391       *courant = eval_equivalence_2_label(pt_etiq, haut, gauche);
00392       return;
00393     }
00394 
00395   default:
00396     /*équivalence entre gauche, haut et avant */
00397     {
00398       *courant = eval_equivalence_3_label(pt_etiq, haut, gauche, avant);  
00399 
00400       return;
00401     }    
00402   }/*fin du switch*/
00403 
00404 }
00405 
00406 
00407 
00408 /*
00409   Fonction pour la mise à jour des labels à l'aide du tableau de chainage
00410 */
00411 
00412 void 
00413 eval_reetiquetage( ima3Du1* ima_ori,
00414               ima3Du8* ima_etiq,   /* adresse de l'image destination (etiquettes) */
00415               unsigned long  int *pt_etiq,
00416               unsigned long  int *pt_nb_etiq,     /* pointeur sur le nombre de label utilisé moins un*/
00417               unsigned long  int *pt_nb_real_etiq)/* Nombre réal de label apres mise a jour  */
00418 {
00419   register unsigned int x,y,z;
00420   unsigned long int i;
00421   //unsigned long  int label_effectif_max =0;
00422   //unsigned long  int nb_label_effectif =0;
00423   unsigned long  int tmp;
00424   //unsigned long int *pt_nbel; 
00425   //float *pt_moy;
00426   unsigned long int etiq_reelle; /*compteur pour transformer les etiquettes
00427                                    issues de la premiere analyse en étiquettes consécutives*/
00428 
00429 
00430   /*--Mise a jour du tableau de chainage--
00431     On verifie que tous les indices du tableau contiennent un numéro de chainage qui
00432     est directe, c'est a dire vers un indice sans chainage. Dans le cas contraire, 
00433     on parcourt tous le chainage afin d'en trouver le bout que l'on place dans l'indice
00434     en cours d'etude.
00435     Ces cas peuvent arriver car la gestion des équivalences ne s'intéresse qu'au chainage
00436     liés aux étiquettes pour lesquelles on veut mémoriser une équivalence.
00437     
00438     Reprenons l'exemple utilise précédemment:
00439     exemple: 
00440     indice:   1 2 3 4 5 6 7 8 9
00441     chainage: 1 2 3 2 5 2 7 8 1
00442   
00443     Le résultat de l'équivalence entre 8 et 6 donnera avait donné:
00444     indice:   1 2 3 4 5 6 7 8 9
00445     chainage: 1 6 3 2 5 6 7 6 1
00446 
00447     On voit que l'etiquette 4 est équivalente a 2 mais l'étiquette 2 a été mémorisée comme
00448     équivalente a 6 lors de la gestion de l'équivalence entre 6 et 8.
00449     Il faut maintenant mémoriser que l'étiquette 4 est chainée avec l'étiquette 6:
00450 
00451     Résultat:
00452     indice:   1 2 3 4 5 6 7 8 9
00453     chainage: 1 6 3 6 5 6 7 6 1
00454   */
00455   for (i = 0; i <= (*pt_nb_etiq); i++) {        
00456     tmp = i;
00457     while (pt_etiq[tmp]!=tmp){
00458       tmp = pt_etiq[tmp];
00459     }
00460     pt_etiq[i] = tmp;
00461   }
00462 
00463   /*--comptage du nombre de label effectif et re-numérotation des classes de sortie --
00464     Afin d'avoir une numérotation croissante des labels de sortie et de connaitre le nombre
00465     exacte d'ojets, il est nécesaire de les renuméroter tout en conservant les correspondance
00466     dans le tableau de chainage.
00467 
00468     Le nombre d'objet est égale au nombre d'étiquette sans chainage (case du tableau
00469     ou indice=chainage)
00470 
00471     Dans un premier temps la renumérotation ne peut se faire que pour les indices sans chainages
00472     et pour les indices avec un chainage inférieur a l'indice. Donc pour lequel, on a deja géré
00473     la re-numération.
00474     
00475     Pour les indices ayant un numéro de chainage supérieur à l'indice il faudra refaire un passage
00476     apres.
00477     
00478     exemple:
00479     indice:   1 2 3 4 5 6 7 8 9
00480     chainage: 1 6 3 6 5 6 7 6 1
00481     
00482     resultat du 1er passage:
00483     indice:   1 2 3 4 5 6 7 8 9
00484     chainage: 1 6 2 6 3 4 5 4 1
00485                 ?   ? 
00486   */ 
00487   etiq_reelle = 0;
00488   for (i = 0; i <= (*pt_nb_etiq); i++) {
00489     if(pt_etiq[i] == i){
00490       pt_etiq[i] = etiq_reelle;
00491       etiq_reelle++;
00492     }else if(pt_etiq[i] < i){
00493       pt_etiq[i] = pt_etiq[pt_etiq[i]];
00494     }
00495   }
00496 
00497   /*dernier passage pour gérer les étiquettes dont le numéro de chainage etait supérieur lors
00498     du 1er passage.
00499 
00500     resultat du 1er passage:
00501     indice:   1 2 3 4 5 6 7 8 9
00502     chainage: 1 6 2 6 3 4 5 4 1
00503 
00504     resultat du 2eme passage:
00505     indice:   1 2 3 4 5 6 7 8 9
00506     chainage: 1 4 2 4 3 4 5 4 1
00507   */
00508   for (i = 0; i <= (*pt_nb_etiq); i++) {
00509     if( pt_etiq[i]>i )
00510       pt_etiq[i] = pt_etiq[pt_etiq[i]];
00511   }
00512 
00513 
00514 
00515   /*Mise à jour des labels dans l'image des étiquettes*/ 
00516   for( z=0; z<ima_etiq->dimz; z++){
00517     for( x=0; x<ima_etiq->dimx; x++){
00518       for( y=0; y<ima_etiq->dimy; y++){
00519         ima_etiq->data[z][y][x] = pt_etiq[ ima_etiq->data[z][y][x] ];
00520       }
00521     }
00522   }
00523 
00524   /*comme on incrémente apres utilisation le compteur du nombre des étiquettes réelles, il faut
00525     enlever 1 pour avoir le nombre d'objets réel*/
00526   *pt_nb_real_etiq = etiq_reelle-1;
00527 
00528 }
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 /*
00543   Fonction pour la recherche des étiquettes et la gestion du chainage.
00544   Cette fonction suppose etre appliquée sur une image du type "classification"
00545   C'est à dire que tous niveaux de gris différents correspondent à objet
00546   différents
00547 
00548 */
00549 void 
00550 eval_etiquetage_strict(ima3Du1* ima_in,     /* adr de l'image origine (initiale ou segmentee) */
00551            ima3Du8* ima_etiq,   /* adresse de l'image destination (etiquettes) */
00552            unsigned char classe,      /* numéro de la classe à étiqueter (valeur ds ima_in) */
00553            unsigned long int *pt_nb_etiq,     /* nombre de label utilisé*/
00554            unsigned long int *nb_real_etiq)   /* nombre de label apres simplification */
00555 {
00556   int cas;  
00557   register  int x,y,z;
00558   unsigned long int i;
00559   unsigned long  int *pt_etiq;          /* pointeur tableau d'etiquettes */  
00560   unsigned long  int nb_etiq;          /* compteur des etiquettes */ 
00561  
00562 
00563   //printf("size au float %d\n", sizeof(double));
00564   /*Allocation du tableau de chainage*/
00565   pt_etiq = (unsigned long  int *)calloc(ETMAX, sizeof(unsigned long  int)); 
00566   if(pt_etiq == NULL){
00567     printf("Probleme d'allocation mémoire (pt_etiq)\n");
00568     exit(1);
00569   }
00570 
00571 
00572   /*initialisation du tableau*/
00573   for( i=0; i<ETMAX ; i++)
00574     pt_etiq[i] = i; 
00575   /*initialisation de nombre d'étiquette déjà utilisée*/
00576   nb_etiq = 0;
00577   
00578 
00579   /*traitement du premier point du bloc*/
00580   if( ima_in->data[0][0][0] != classe){
00581     ima_etiq->data[0][0][0] = 0;
00582   }
00583   else{
00584     /*attribution d'une nouvelle étiquette*/
00585     nb_etiq +=1;
00586     if(nb_etiq>ETMAX-1) nb_etiq=ETMAX-1;
00587     ima_etiq->data[0][0][0] = nb_etiq;
00588   }
00589 
00590   /*traitement de la premiere ligne du bloc*/
00591   x = 0;
00592   z = 0;
00593   for( y=1; y<ima_in->dimy; y++){
00594     /*Si le voxel n'appartient pas à la classe alors mettre
00595       directement l'étiquette 0 du fond quelque soit sa classe
00596       de départ. Puis passer directement au point suivant*/
00597     if(ima_in->data[z][y][x] != classe){
00598       ima_etiq->data[z][y][x] = 0;
00599       continue;
00600     }
00601     /*Etiquetage du point*/
00602     cas = 0;
00603     if( ima_in->data[z][y][x] == ima_in->data[z][y-1][x] ) 
00604       cas += 4; /*g et c similaire*/
00605     eval_label_management( cas,
00606                       0, /*haut*/
00607                       ima_etiq->data[z][y-1][x],/*gauche*/ 
00608                       0,/*avant*/
00609                       &ima_etiq->data[z][y][x], /*courant*/
00610                       pt_etiq,
00611                       &nb_etiq
00612           );
00613   }
00614   //printf("\nFin Traitement premiere ligne\n");
00615   //for( x=0; x<=nb_etiq; x++)
00616   //printf("%d --> %d\n", x, pt_etiq[x]);
00617 
00618 
00619   /*traitement des autres lignes de la premiere section*/ 
00620   z = 0;
00621   for( x=1; x<ima_in->dimx; x++){
00622     for( y=0; y<ima_in->dimy; y++){
00623 
00624       /*Si le voxel n'appartient pas à la classe alors mettre
00625         directement l'étiquette 0 du fond quelque soit sa classe
00626         de départ. Puis passer directement au point suivant*/
00627       if(ima_in->data[z][y][x] != classe){
00628         ima_etiq->data[z][y][x] = 0;
00629         continue;
00630       }
00631 
00632       /*Etiquetage du point*/
00633       cas = 0;
00634 
00635       /*on peut toujours comparer avec le haut*/
00636       if( ima_in->data[z][y][x] == ima_in->data[z][y][x-1] ) 
00637         cas += 2; /*h et c similaire*/
00638 
00639       /* En plus, si on n'est pas sur la premiere colonne
00640          on peut faire les comparaisons avec la gauche*/
00641       if( y!=0){ 
00642         /*comparaison avec celui de gauche*/
00643         if( ima_in->data[z][y][x] == ima_in->data[z][y-1][x] ) 
00644           cas += 4; /*g et c similaire*/
00645         if( ima_in->data[z][y-1][x] == ima_in->data[z][y][x-1] ) 
00646           cas += 32; /*g et h similaire*/               
00647         eval_label_management( cas,
00648                           ima_etiq->data[z][y][x-1] /*haut*/,
00649                           ima_etiq->data[z][y-1][x]/*gauche*/, 
00650                           0, /*avant*/
00651                           &ima_etiq->data[z][y][x], /*courant*/
00652                           pt_etiq,
00653                           &nb_etiq
00654                           );
00655       }
00656       else{
00657         eval_label_management( cas,
00658                           ima_etiq->data[z][y][x-1] /*haut*/,
00659                           0, /*gauche*/ 
00660                           0, /*avant*/
00661                           &ima_etiq->data[z][y][x], /*courant*/
00662                           pt_etiq,
00663                           &nb_etiq
00664                           );
00665       }
00666     }
00667   }
00668 
00669   
00670   /*traitement des autres sections du bloc*/
00671   for( z=1; z<ima_in->dimz; z++){
00672     for( x=0; x<ima_in->dimx; x++){
00673       for( y=0; y<ima_in->dimy; y++){
00674         
00675         /*Si le voxel n'appartient pas à la classe alors mettre
00676           directement l'étiquette 0 du fond quelque soit sa classe
00677           de départ. Puis passer directement au point suivant*/
00678         if(ima_in->data[z][y][x] != classe){
00679           ima_etiq->data[z][y][x] = 0;
00680           continue;
00681         }
00682         
00683         /*Etiquetage du point*/
00684         cas = 0;
00685         
00686         /*comparaison avec le plan d'avant toujours possible*/
00687         if( ima_in->data[z][y][x] == ima_in->data[z-1][y][x] ) 
00688           cas += 1; /*a et c similaire*/
00689         
00690         
00691         /*gestion de la premiere ligne*/
00692         if(x==0){ 
00693           if(y!=0){ /*on ne se trouve pas sur le premier point de la ligne*/
00694             if( ima_in->data[z][y][x] == ima_in->data[z][y-1][x] ) 
00695               cas += 4; /*g et c similaire*/        
00696             if( ima_in->data[z][y-1][x] == ima_in->data[z-1][y][x] ) 
00697               cas += 16; /*g et a similaire*/
00698             eval_label_management( cas,
00699                               0 /*haut*/,
00700                               ima_etiq->data[z][y-1][x] /*gauche*/, 
00701                               ima_etiq->data[z-1][y][x] /*avant*/,
00702                               &ima_etiq->data[z][y][x], /*courant*/
00703                               pt_etiq,
00704                               &nb_etiq
00705                               );
00706             
00707           }
00708           else{
00709             eval_label_management( cas,
00710                               0 /*haut*/,
00711                               0 /*gauche*/, 
00712                               ima_etiq->data[z-1][y][x] /*avant*/,
00713                               &ima_etiq->data[z][y][x], /*courant*/
00714                               pt_etiq,
00715                               &nb_etiq
00716                               );
00717             
00718           }
00719         }
00720         else{ /*gestion des lignes suivantes*/
00721 
00722           /*comparaison avec le haut toujours possible*/
00723           if(  ima_in->data[z][y][x] == ima_in->data[z][y][x-1] ) 
00724             cas += 2; /*h et c similaire*/          
00725           if(  ima_in->data[z][y][x-1] == ima_in->data[z-1][y][x] ) 
00726             cas += 8; /*h et a similaire*/      
00727             
00728           if(y!=0){ /*on ne se trouve pas sur le premier point de la ligne*/
00729             if( ima_in->data[z][y][x] == ima_in->data[z][y-1][x] ) 
00730               cas += 4; /*g et c similaire*/        
00731             if( ima_in->data[z][y-1][x] == ima_in->data[z-1][y][x] ) 
00732               cas += 16; /*g et a similaire*/       
00733             if( ima_in->data[z][y-1][x] ==  ima_in->data[z][y][x-1] ) 
00734               cas += 32; /*g et h similaire*/
00735             eval_label_management( cas,
00736                               ima_etiq->data[z][y][x-1] /*haut*/,
00737                               ima_etiq->data[z][y-1][x] /*gauche*/, 
00738                               ima_etiq->data[z-1][y][x] /*avant*/,
00739                               &ima_etiq->data[z][y][x], /*courant*/
00740                               pt_etiq,
00741                               &nb_etiq
00742                               );
00743           }
00744           else{
00745             eval_label_management( cas,
00746                               ima_etiq->data[z][y][x-1] /*haut*/,
00747                               0 /*gauche*/, 
00748                               ima_etiq->data[z-1][y][x] /*avant*/,
00749                               &ima_etiq->data[z][y][x], /*courant*/
00750                               pt_etiq,
00751                               &nb_etiq
00752                               );            
00753           }
00754         } /*fin test sur les lignes*/
00755         
00756         
00757       } /*fin sur y*/
00758     } /*fin sur x*/
00759   } /*fin sur z*/
00760   
00761   
00762   printf("nb_etiq = %d (max %d)\n", nb_etiq+1, ETMAX);
00763   if( nb_etiq+1 == ETMAX) {
00764     printf("-----DANGER Pas assez d'etiquettes !!!----\n");
00765   }
00766 
00767   *pt_nb_etiq = nb_etiq+1;
00768 
00769   
00770   eval_reetiquetage( ima_in,
00771                 ima_etiq,   /* adresse de l'image destination (etiquettes) */
00772                 pt_etiq,
00773                 &nb_etiq,        /* nombre de label utilisé*/
00774                 nb_real_etiq);   /*Nombre réal de label apres mise a jour  */
00775 
00776 
00777   /*liberation de la liste de chainage*/
00778   free( pt_etiq);
00779 }
00780 
00781 
00782 
00783 /* 
00784    La fonction calcul_vol_objets calcul le volume (nombre de pixel) de chacun
00785    des objets présents dans un bloc 3D. Ce bloc doit etre avant tout étiqueté avec
00786    des étiquettes consécutives. 
00787    L'étiquette 0 représente le fond de la piece c'est a dire l'ensemble des points
00788    qui n'appartiennent pas à la classe étudiée.
00789    Le parametre nb_objet doit contenir le nombre objets connexes présents dans le bloc
00790    (sans compter le fond)
00791    Les résultats sont sauvegardés dans un fichier (paramètre filename) suivant deux
00792    colonnes: La 1ere contient le numéro de l'étiquette de l'objet et la 2eme le nombre 
00793    de voxel appartenant à l'objet. 
00794 */
00795 
00796 int calcul_vol_objets(eval_volume_t* des, const char *filename, unsigned long int nb_objet){
00797 
00798   unsigned int *vol;
00799   unsigned int repartition_vol[5]={0,0,0,0,0}; /*pour la répartition des volumes*/
00800   unsigned int vol_min, vol_max;
00801   double vol_moy, vol_ecart_type;
00802   register unsigned int x, y, z;
00803   FILE *f;
00804 
00805 
00806   vol = calloc( nb_objet+1,sizeof(unsigned int));
00807   if( vol==NULL) {
00808     printf("Probleme allocation memoire\n");
00809     exit(1);
00810   }
00811 
00812   /*cumul des points*/
00813   for( z=0; z<des->ima_etiq->dimz; z++)
00814     for( y=0; y<des->ima_etiq->dimy; y++)
00815       for( x=0; x<des->ima_etiq->dimx; x++){
00816         vol[des->ima_etiq->data[z][y][x]]++;
00817      }
00818   
00819   printf("un\n");
00820   /*sauvegarde dans un fichier*/  
00821   f=fopen( filename, "w");
00822   if(f==NULL){
00823     perror("Dans calcul_vol_objets");
00824     printf("Erreur ouverture de %s\n", filename);
00825   }
00826   vol_min = vol[1];
00827   vol_max = vol[1];
00828   vol_moy = 0.0;
00829   for( x=1; x<=nb_objet; x++){
00830     fprintf( f, "%d %d\n", x, vol[x] );
00831     if (vol[x] > vol_max) vol_max = vol[x];
00832     if (vol[x] < vol_min) vol_min = vol[x];
00833     vol_moy +=  (double)vol[x]/(double)nb_objet;
00834     /*mise a jour de la répartition des volumes*/
00835     if( vol[x]<10 ) repartition_vol[0]++;
00836     else if ( vol[x]<100 ) repartition_vol[1]++;
00837     else if ( vol[x]<1000 ) repartition_vol[2]++;
00838     else if ( vol[x]<10000 ) repartition_vol[3]++;
00839     else repartition_vol[4]++;
00840   }
00841   //fclose(f);  /*fclose provoque une grave erreur!!! probleme dans la glibc!!!*/
00842   
00843   /*calcul de l'ecart type des volumes*/
00844   vol_ecart_type = 0.0;
00845   for( x=1; x<=nb_objet; x++){
00846     vol_ecart_type += pow( (double)vol[x]-vol_moy, 2.0) / (double)nb_objet;
00847   }
00848   vol_ecart_type = sqrt( vol_ecart_type);
00849 
00850   /*affichage des résultats*/
00851   printf("Volume minimal: %d\n", vol_min);
00852   printf("Volume maximal: %d\n", vol_max);
00853   printf("Volume moyen: %lf\n", vol_moy);
00854   printf("Ecart type: %lf\n", vol_ecart_type);
00855 
00856   printf("Répartion des volumes:\n");
00857   printf("0->9:\t %d\n", repartition_vol[0]);
00858   printf("10->99:\t %d\n", repartition_vol[1]);
00859   printf("100->999:\t %d\n", repartition_vol[2]);
00860   printf("1000->9999:\t %d\n", repartition_vol[3]);
00861   printf("10000-> + :\t %d\n", repartition_vol[4]);
00862 
00863 
00864   /*liberation de la memoire*/
00865   free( vol);
00866 
00867 }
00868 
00869 
00870 
00871 /*
00872   Cette fonction calcul la compacité 3D de chacun des objets.
00873   La compacité 3D est définie par: V/( (4/3) * Pi * (S/ (4*Pi))^(3/2) )
00874 
00875 */
00876 
00877 int calcul_attributs_objets(eval_volume_t* des, const char *filename, unsigned long int nb_objet){
00878 
00879   unsigned int *vol, *surf;
00880   register unsigned int x, y, z;
00881   register char l, m, n;
00882   FILE *f;
00883   booleen env;
00884   double compacite;
00885   double comp_moy;
00886 
00887   comp_moy = 0.0;
00888 
00889   vol = calloc( nb_objet+1,sizeof(unsigned int));
00890   if( vol==NULL) {
00891     printf("Probleme allocation memoire\n");
00892     exit(1);
00893   }
00894 
00895   surf = calloc( nb_objet+1,sizeof(unsigned int));
00896   if( surf==NULL) {
00897     printf("Probleme allocation memoire\n");
00898     exit(1);
00899   }
00900 
00901   
00902   /*cumul des points pour le volume et l'enveloppe*/
00903   printf("Calcul des attributs en cours\n");
00904   for( z=0; z<des->ima_etiq->dimz; z++)
00905     for( y=0; y<des->ima_etiq->dimy; y++)
00906       for( x=0; x<des->ima_etiq->dimx; x++){
00907         /*mise a jour du volume pour la region*/
00908         vol[des->ima_etiq->data[z][y][x]]++;
00909         /*etude de l'enveloppe*/
00910         env=FAUX;
00911         if( z==0 ||  /*gestion des bords de l'image*/
00912             y==0 || 
00913             x==0 ||
00914             z==des->ima_etiq->dimz-1 ||
00915             y==des->ima_etiq->dimy-1 ||
00916             x==des->ima_etiq->dimx-1){ 
00917           env=VRAI;
00918         }else{ /*sinon etude des etiquettes dans le voisinage*/
00919           for( l=-1; l<2; l++ )
00920             for( m=-1; m<2; m++ )
00921               for( n=-1; n<2; n++ ){
00922                 //printf("%d,%d,%d\n,", z+l, y+m, x+n);
00923                 //printf("%d\n",des->ima_etiq->data[z+l][y+m][x+n]);
00924                 if( des->ima_etiq->data[z][y][x] != des->ima_etiq->data[z+l][y+m][x+n]){
00925                   env = VRAI;
00926                   continue;
00927                 }
00928               }
00929         }
00930         /*mise a jour de compteur des voxels appartenant a une enveloppes*/
00931         if(env==VRAI) surf[des->ima_etiq->data[z][y][x]]++;
00932      }
00933   
00934 
00935   /*sauvegarde dans un fichier*/
00936   printf("Sauvagarde des résultats dans %s\n",filename );
00937   f=fopen( filename, "w");
00938   if(f==NULL){
00939     perror("Dans calcul_attributs_objets");
00940     printf("Erreur ouverture de %s\n", filename);
00941   }
00942 
00943   for( x=1; x<=nb_objet; x++){
00944     compacite = (double)vol[x] / ( (4.0/3.0) * M_PI * pow( surf[x]/(4.0*M_PI) ,1.5) );
00945     fprintf( f, "%d %d %d %.4lf\n", x, vol[x], surf[x], compacite );
00946     comp_moy +=  compacite/(double)nb_objet;
00947   }
00948 
00949   printf("Compacitee moyenne: %lf\n", comp_moy);
00950 
00951   /*liberation de la memoire*/
00952   free( vol);
00953   free( surf);
00954 }
00955 
00956 
00957 
00958 
00959 
00960 
00961 /* *************************  CALCUL  ***************************/
00973 int eval_volume_calc(eval_volume_t* des, ima3Du1* imaIn){
00974 
00975   unsigned long int nb_objet_reel, nb_etiq_utilise;
00976 
00977   eval_etiquetage_strict(imaIn, des->ima_etiq, des->classe, &nb_etiq_utilise, &nb_objet_reel);
00978            
00979   //printf("nb etiquettes utilisees: %d\n", nb_etiq_utilise );
00980   printf("Nombre d'objets: %d\n", nb_objet_reel);
00981   
00982   //calcul_vol_objets(des, "eval.txt", nb_objet_reel);
00983   printf("Calcul compacite ...\n");
00984   calcul_attributs_objets(des, "attr.txt", nb_objet_reel);
00985 
00986 }
00987 
00988 
00989 
00990 
00991 int eval_volume_ferm(eval_volume_t* des){
00992 
00993   /*libération de l'image des étiquettes*/
00994   liberer_ima3Du8( des->ima_etiq);
00995   /*libération de la structure pour stocker ima_etiq*/
00996   free(des->ima_etiq);
00997 
00998 
00999 }

Generated on Tue Apr 22 13:31:06 2008 for volume by  doxygen 1.5.3