llabelcc.c

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 /* **************************** llabelcc.c ******************************/
00020 /*                                                                    */
00021 /* ********************************************************************/
00022 
00043 #include "image.h" 
00044 #include "proto2D.h"
00045 #include "labelcc.h" 
00046 #include <stdlib.h>
00047 #include <fcntl.h>
00048 
00049 /* ENST : =============================================================*/
00050 #define TAILLE_TABLE 0x10000
00051 #define new_object ((nbfs >= 2) ? ++objets : 1 + (objets++ % 255))
00052 
00053         /* Variables statiques */
00054 static pixu2 *t_lut;
00055 static pixu2 etiq;
00056 static int connex_8;
00057 static int masque;
00058 static int seuil;
00059 static int negatif;
00060 static int np , nl ;
00061 
00062 pixu1 **ENTREE ;
00063 pixu2 **SORTIE ;
00064 
00065 /* FIN ENST ===================================================================*/
00066 
00067 
00068 /* *************************  LECTURE  *******************************/
00082 param *labelcc_lect( labelcc_t *des, param *ptp, char *debq){
00083   char question[500];
00084 
00085   sprintf(question, "%s connexite : 4 ou 8", debq); 
00086   lec_param(question, ptp);
00087   des->connex = atoi(ptp->rep);
00088   ptp = ptp->next;
00089   if(des->connex!=4 && des->connex!=8 ){
00090       printf("\n>>ERREUR labelcc_lect : connexite %d inconnu (4 ou 8)\n", 
00091              des->connex); 
00092       exit(1);
00093   }
00094 
00095   sprintf(question, "%s seuil : premier niveau de gris des objets", debq); 
00096   lec_param(question, ptp);
00097   des->seuil = atoi(ptp->rep);
00098   ptp = ptp->next;
00099 
00100   sprintf(question, "%s contraste : <0 = objets sombres, >=0 = objets claires",
00101           debq); 
00102   lec_param(question, ptp);
00103   des->contraste = atoi(ptp->rep);
00104   ptp = ptp->next;
00105 
00106   return(ptp);
00107 }
00108 
00109 /* *************************  INITIALISATION  ***************************/
00120 int labelccu1_init(labelcc_t *des, imau1 im0, imau2 *imres){     
00121   /* image resultat */ 
00122   imres->nc = im0.nc;
00123   imres->nr = im0.nr;
00124   sprintf(imres->nom, "%s_label_s%d", im0.nom, des->seuil);
00125   alloc_imau2(imres);
00126 }
00127 
00128 
00129 /* *************************  CALCUL  ***************************/
00141 int labelccu1_calc(labelcc_t *des, imau1 im0, imau2 *imres){
00142 int nbo;
00143 int nbfs=2;
00144 
00145 nbo = ETIQ(&im0, imres, &(des->connex), &(des->seuil), &(des->contraste), &nbfs);
00146 
00147 return(nbo);
00148 }    
00149 
00150 
00151 /* ENST : =============================================================*/
00152 /* **********************************************************************
00153  * NOM 
00154  * 
00155  *      etiq.c : routine pour l'etiquetage des parties connexes d'une image 
00156  *               codee sur un octet. Retourne le nombre d'objets dans l'image.
00157  *
00158  * ****************************************************************************
00159  * SYNOPSIS 
00160  *
00161  * int ETIQ ( IMA_IN, IMA_EX, NP, NL, CONNEX, SEUIL, CONTRASTE, NBFS)
00162  *      imau1   *IMA_IN ;
00163  *      imau2 *IMA_EX ;
00164  *      int *CONNEX;
00165  *      int *SEUIL;
00166  *      int *CONTRASTE;
00167  *      int *NBFS;
00168  * 
00169  * void save_label(imau2 label, char *message)
00170  *
00171  * ****************************************************************************
00172  * DESCRIPTION
00173  *
00174  *      Cette routine effectue l'etiquetage des parties connexes d'une image
00175  *      codee sur 1 octet. Dans l'image de sortie, les pixels d'une meme zone 
00176  *      connexe ont la meme valeur (etiquette) codee sur 2 octets.
00177  *      
00178  *
00179  * ****************************************************************************
00180  * PARAMETRES
00181  *
00182  * IMA_IN (*imau1)
00183  *      Image originale codee sur 1 octet.
00184  *
00185  * IMA_EX (*imau2)
00186  *      Image des etiquettes codee sur 2 octets. L'allocation memoire 
00187  *      de ce tableau doit avoir ete effectuee precedemment.
00188  *
00189  * CONNEX (*int)
00190  *      Pointeur sur la connexite (4 ou 8) qui doit etre utilisee pour 
00191  *      determinee les objets presents dans l'image. N.B. Si *CONNEX n'est
00192  *      pas egal a 4, alors on se place en 8-connexite.
00193  *
00194  * SEUIL (*int)
00195  *      Pointeur sur le seuil (en niveau de gris) entre les objets et le fond.
00196  *      
00197  * CONTRASTE (*int)
00198  *      Pointeur donnant le contraste des objets recherches. Si *CONTRASTE
00199  *      est strictement negatif, on cherche des objets sombres (val <= *SEUIL),
00200  *      sinon on cherche des objets clairs (val >= *SEUIL).
00201  *
00202  * NBFS (*int)
00203  *      Pointeur donnant le nombre d'octets utilises pour coder les pixels
00204  *      dans l'image des etiquettes.
00205  *      N.B. : NBFS doit etre egal a 2.
00206  *
00207  * ****************************************************************************
00208  * HISTORIQUE
00209  *
00210  *
00211  * 25-oct-95  Emmanuel trouve : adaptation aux structure personnelles
00212  *              ajout de save_label
00213  * 22-mars-95 Michel Roux (mroux@ima), TELECOM Paris / IMA.
00214  *     Utilisation des structures Image et Ima16.
00215  *     Suppression des parametres NP et NL
00216  *
00217  * 17-fev-95 Michel Roux (mroux@ima), TELECOM Paris / IMA.
00218  *     Addition de cet entete.
00219  *
00220  * 18-nov-92 Alain Clainchard (clainchard@ima), TELECOM Paris / IMA.
00221  *     Creation
00222  *
00223  */
00224 
00225 int ETIQ ( IMA_IN, IMA_EX, CONNEX, SEUIL, CONTRASTE, NBFS)
00226      imau1 *IMA_IN ;
00227      imau2 *IMA_EX ;
00228      int *CONNEX;
00229      int *SEUIL;
00230      int *CONTRASTE;
00231      int *NBFS;
00232 {
00233 
00234 register unsigned int i, j;
00235 int objets;
00236 int nlf = 2;
00237 int bord = 1;
00238 int nbm = sizeof(pixu1);
00239 int nbfs;
00240 int nargs;
00241 
00242                 /* Controle des arguments */
00243 
00244         connex_8 = (*CONNEX != 4);
00245         negatif = (*CONTRASTE < (int) 0);
00246         seuil = negatif ? 0 : 1;
00247         if (*SEUIL > seuil) seuil = *SEUIL;
00248         nbfs = (*NBFS > 0) ? *NBFS : 0;
00249         masque = connex_8 ? 0xF : 0x7;
00250         ENTREE = IMA_IN->p ; SORTIE = IMA_EX->p ;
00251         np = IMA_IN->nc ; nl = IMA_IN->nr ;
00252 
00253                 /* Initialisation de la table des etiquettes */
00254 
00255         if ((t_lut = (pixu2 *) calloc (TAILLE_TABLE, sizeof(pixu2))) == NULL) {
00256                 fprintf (stderr,"\n*** ETIQ *** Memoire insuffisante.\n");
00257                 exit(2);
00258         }
00259         t_lut[0] = 0;
00260 
00261 
00262                 /* Premiere passe: identification des objets */
00263 
00264         ETIQ_S1 () ;
00265 
00266                 /* Generation des etiquettes definitives */
00267 
00268         for (objets = 1; objets <= (int) etiq; objets++) {
00269                 i = objets; do { j = i; i = t_lut[i]; } while (i != j);
00270                 t_lut[objets] = i;
00271         }
00272         objets = 0;
00273         for (i = 1; i <= (int) etiq; i++) {
00274                 j = t_lut[i];
00275                 t_lut[i] = (pixu2) ((j == i) ? new_object : t_lut[j]);
00276         }
00277         fprintf (stdout, "\n*** ETIQ *** %u objets d‚nombr‚s.\n", objets);
00278 
00279                 /* Deuxieme passe: etiquetage des objets */
00280 
00281         ETIQ_S2 () ;
00282 
00283 
00284         free (t_lut);
00285 
00286         return ((int) objets);
00287 
00288 }
00289 #undef new_object
00290 
00291 /*========================================================================
00292 */
00293 
00294 /* PREMIERE PASSE: identification des objets */
00295 
00296 #define new_label(X)                                                    \
00297         if (etiq == (pixu2) (TAILLE_TABLE - 1)) {                       \
00298                 fprintf (stderr, "\n*** ETIQ *** table satur‚e\n");     \
00299                 exit (2);                                               \
00300         }                                                               \
00301         X = ++etiq;
00302 
00303 #define merge(X, Y)     if (X < Y) Y = t_lut[Y] = X; else X = t_lut[X] = Y;
00304 
00305 ETIQ_S1 ()
00306 {
00307 
00308 register int i,j;
00309 register unsigned int ouest, aux;
00310 unsigned int nord, nord_ouest;
00311 int status;
00312 pixu2 *ptr1, *ptr2 , *bid ;
00313 
00314                 
00315         ptr1 = (pixu2 *) malloc ( np * sizeof ( pixu2 ) ) ;
00316         ptr2 = (pixu2 *) malloc ( np * sizeof ( pixu2 ) ) ;
00317 
00318         for ( i = 0 ; i < np ; ptr2[i++] = 0 ) ;
00319 
00320         etiq = 0 ;
00321 
00322 /* Cas general */
00323 
00324         for ( j = 0 ; j < nl ; j ++ ) {
00325                 bid = ptr1 ;
00326                 ptr1 = ptr2 ;
00327                 ptr2 = bid ;
00328                 
00329                 if (negatif) for (i = 0 ; i < np ; i++)
00330                         ptr2[i] = (pixu2) (( (int) ENTREE[j][i] <= seuil) ? -1 : 0);
00331                 else 
00332                         if (seuil > 1) for (i = 0 ; i < np ; i++)
00333                            ptr2[i] = (pixu2)(( (int) ENTREE[j][i] >= seuil) ? -1 : 0);
00334                         else for ( i = 0 ; i < np ; i++ ) 
00335                            ptr2[i] = (pixu2) ENTREE[j][i] ;
00336 
00337 
00338                 nord_ouest = ouest = status = 0;
00339                 for (i = 0 ; i < np ; i++) {
00340                         status = (status << 2) & masque;
00341                         if ((nord = ptr1[i]) != 0) {
00342                                 while ((aux = t_lut[nord]) != nord) nord = aux;
00343                                 status += 2;
00344                                 }
00345                         if (ptr2[i] != 0) status++;
00346                         switch (status) {
00347                                 case 3:
00348                                 case 11:
00349                                         ouest = nord;
00350                                 case 5:
00351                                 case 13:
00352                                 case 15:
00353                                         break;
00354 
00355                                 case 1:
00356                                         new_label (ouest);
00357                                         t_lut[ouest] = ouest;
00358                                         break;
00359 
00360                                 case 7:
00361                                         merge (nord, ouest);
00362                                         break;
00363 
00364                                 case 9:
00365                                         ouest = nord_ouest;
00366                                         break;
00367 
00368                                 case 6:
00369                                         if (connex_8) merge (nord, ouest);
00370                                 default:
00371                                         ouest = 0;
00372                                 }
00373                         ptr2[i] = (pixu2) ouest; nord_ouest = nord;
00374                         }
00375                 }
00376 }
00377 #undef merge
00378 #undef new_label
00379 
00380 /*========================================================================
00381 */
00382 
00383 /* DEUXIEME PASSE: ETIQUETAGE DES OBJETS */
00384 
00385 #define merge(X, Y)     if (X < Y) Y = X; else X = Y;
00386 
00387 ETIQ_S2 ()
00388 {
00389 
00390 register int i,j;
00391 register unsigned int ouest, aux;
00392 unsigned int nord, nord_ouest;
00393 int status;
00394 pixu2 *ptr1, *ptr2 , *bid ;
00395 
00396         ptr1 = (pixu2 *) malloc ( np * sizeof ( pixu2 ) ) ;
00397         ptr2 = (pixu2 *) malloc ( np * sizeof ( pixu2 ) ) ;
00398 
00399         etiq = 0 ;
00400 
00401         for ( i = 0 ; i < np ; ptr2[i++] = 0 ) ;
00402 
00403 
00404 /* Cas general */
00405 
00406         for ( j = 0 ; j < nl ; j ++ ) {
00407                 bid = ptr1 ;
00408                 ptr1 = ptr2 ;
00409                 ptr2 = bid ;
00410                 
00411                 if (negatif) for (i = 0 ; i < np ; i++)
00412                         ptr2[i] = (pixu2) (( (int) ENTREE[j][i] <= seuil) ? -1 : 0);
00413                 else 
00414                         if (seuil > 1) for (i = 0 ; i < np ; i++)
00415                            ptr2[i] = (pixu2)(( (int) ENTREE[j][i] >= seuil) ? -1 : 0);
00416                         else for ( i = 0 ; i < np ; i++ ) 
00417                            ptr2[i] = (pixu2) ENTREE[j][i] ;
00418 
00419 
00420                 nord_ouest = ouest = status = 0;
00421                 for (i = 0; i < np ; i++) {
00422                         status = (status << 2) & masque;
00423                         if ((nord = ptr1[i]) != 0) status += 2;
00424                         if (ptr2[i] != 0) status++;
00425                         switch (status) {
00426                                 case 3:
00427                                 case 11:
00428                                         ouest = nord;
00429                                 case 5:
00430                                 case 13:
00431                                 case 15:
00432                                         break;
00433 
00434                                 case 1:
00435                                         ouest = ++etiq;
00436                                         break;
00437 
00438                                 case 7:
00439                                         merge (nord, ouest);
00440                                         break;
00441 
00442                                 case 9:
00443                                         ouest = nord_ouest;
00444                                         break;
00445 
00446                                 case 6:
00447                                         if (connex_8) merge (nord, ouest);
00448                                 default:
00449                                         ouest = 0;
00450                         }
00451                         ptr2[i] = (pixu2) ouest; 
00452                         nord_ouest = nord;
00453                         SORTIE[j][i] = (pixu2) t_lut[ouest];
00454                 }
00455         }
00456 }
00457 

Generated on Tue Apr 22 13:31:04 2008 for ima2D by  doxygen 1.5.3