lfuzzy_c_means.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 /* ****************************************************************** */
00020 /*                             lfuzzy_c_means.c                                 */ 
00021 /* ****************************************************************** */
00022 /*                                                                    */
00023 /*            Classifictation du type Fuzzy C-mean                    */
00024 /*                                                                    */
00025 /* ****************************************************************** */
00026 /*  Dernière modification: Ramasso E. & Jullien S. 08/12/03           */
00027 /*                                                                    */
00028 /* ****************************************************************** */
00029 
00030 
00037 #include "classifier.h"
00038 #include "image.h"
00039 #include "proto2D.h"
00040 #include "fuzzy_c_means.h"
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include <math.h>
00045 #include <time.h>
00046 #include <ctype.h>
00047 
00048 
00049 
00050 #define ABS(X)          ((X)<0?-(X):(X))
00051 
00065 
00066 /* *************************  LECTURE  *******************************/
00086 param *fuzzy_c_means_lect( fuzzy_c_means_t *fcm, param *ptp, char *debq)
00087 {
00088   char question[500];
00089 
00090   sprintf(question, "%s nombre de classes [nb_class] (entier)", debq); 
00091   lec_param(question, ptp);
00092   fcm->nb_class = atoi(ptp->rep);
00093   ptp = ptp->next;
00094 
00095   sprintf(question, "%s indice de flou [fuzzy_coeff] (>1) (reel)", debq); 
00096   lec_param(question, ptp);
00097   fcm->fuzzy_coeff = (float)atof(ptp->rep);
00098   ptp = ptp->next;
00099 
00100   sprintf(question, "%s seuil d'arret [threshold] [0, 1] (ex:0.001) (reel)", debq); 
00101   lec_param(question, ptp);
00102   fcm->threshold = (float)atof(ptp->rep);
00103   ptp = ptp->next;
00104 
00105   sprintf(question, "%s nombre maximum d'iterations [nb_it] (entier)", debq); 
00106   lec_param(question, ptp);
00107   fcm->nb_it = atoi(ptp->rep);
00108   ptp = ptp->next;
00109 
00110   sprintf(question, "%s extension noms fichiers images d'appartenance (.ima|.ras|.imf), non sauvees si ''", debq); 
00111   lec_param(question, ptp);
00112   strcpy(fcm->extension, ptp->rep);
00113   ptp = ptp->next;
00114 
00115   sprintf(question, "%s Quelle initialisation? ( 0 | 1 | nom_fichier )", debq); 
00116   lec_param(question, ptp);
00117   strcpy(fcm->init_type, ptp->rep);
00118   ptp = ptp->next;
00119 
00120   return(ptp);
00121 }
00122 
00123 
00124 
00125 
00126 
00127 /* *************************  INITIALISATION  ***************************/
00149 int fuzzy_c_means_init(fuzzy_c_means_t *fcm, data_input dataI , data_output *dataO)
00150 {
00151   int i, k, j;
00152 
00153   printf("\n fuzzy_c_mean init...");
00154 
00155   dataO->nb_class = fcm->nb_class;
00156   dataO->nb_pts = dataI.nb_pts;
00157   dataO->type = FUZZY_CHOICE;
00158   dataO->equ_nb_cols = dataI.equ_nb_cols;
00159   dataO->equ_nb_rows = dataI.equ_nb_rows;
00160 
00161    fcm->centre=(unsigned short **)Calloc(fcm->nb_class,sizeof(*fcm->centre));
00162    for (k=0;k<fcm->nb_class;k++)
00163        fcm->centre[k]=(unsigned short *)Calloc(dataI.nb_attr,sizeof(unsigned short));
00164  
00165    alloc_classifier_data_output(dataO);
00166 
00167    /* appel init */
00168    init_coeff_appartenance(fcm, dataI, dataO);
00169 
00170    printf("\ninit fcm OK.\n");
00171 }
00172 
00173 
00174 
00175 
00176 
00177 /* *************************  CALCUL  ***************************/
00194 int fuzzy_c_means_calc(fuzzy_c_means_t *fcm, data_input dataI , data_output *dataO)
00195 { 
00196   int i,j,k,t;
00197   float media,tmp;    
00198   
00199   printf("\nfcm calc...\n\n"); 
00200 
00201   t=0;
00202   printf("Nb. de iterations[nb_it]=%d\n",fcm->nb_it);
00203   printf("\n");
00204   while(t<fcm->nb_it)
00205       {
00206           printf("\n");
00207           printf(" Itération numéro %d\n",t);
00208           printf("\n");
00209 
00210           calcul_centroides(fcm,dataI, dataO);
00211           calcul_coeff_appartenance(fcm, dataI, dataO);
00212 
00213           media=fcm->variation/(fcm->nb_class*(dataI.nb_pts));
00214           printf("===> seuil = %1.5f",fcm->threshold);
00215           printf("   --->>    la variation actuelle = %1.5f",media);
00216           if (media<fcm->threshold) break;
00217 
00218           if (t<fcm->nb_it-1) printf("  ...  donc, continue\n");
00219           
00220           t++;    
00221       }
00222 
00223  
00224   printf("\n");
00225   printf("\n");
00226 
00227   printf("Calcul effectué!\n");
00228   if (t!=fcm->nb_it) printf("L'algorithme a terminé le calcul après  %d cycles.\n",t+1);
00229   else printf("\nNb. maximum d'itérations atteint !!! \n");
00230 
00231   printf("\n");
00232 }
00233 
00235 
00236 
00237 /* Ces fonctions servent à effectuer le calcul.
00238 Elles sont utilisées dans la fonction fcm_calc. */
00239 
00240 /* **************************  FUNCTIONS  ****************************** */
00241 /* *************************  ALLOCATION  ************************** */
00242 /*
00243     \brief Fonction d'allocation
00244 
00245         
00246     \param nelem correspond au nombre d'éléments que l'on veut allouer
00247     \param elsize correspond a la taille des éléments à allouer
00248     \return renvoie un caractère qui indique si l'opération s'est bien déroulée
00249     \author Premiere version: F. Florea
00250     \author Seconde version: E. Ramasso & S. Jullien
00251     \version 01/12/03
00252 */
00253 char *Calloc(unsigned nelem,unsigned elsize)
00254 {
00255 char *ptr;
00256 if((ptr=calloc(nelem,elsize))==NULL)
00257      {
00258      perror("MEMORY ALLOCATION ERROR");
00259      exit(3);
00260      }
00261 return ptr;
00262 }
00263 
00264 
00265 /* *************************  APPARTENANCE  ***************************/
00266 /*
00267     \brief Fonction d'appartenance
00268 
00269     Cette fonction recalcule les coefficients d'appartenance
00270 
00271     \param fcm le descripteur du classifieur fuzzy C mean
00272     \param dataI structure contenant les données d'entrée
00273     \param dataO pointeur sur la structure contenant les données de sortie
00274     \author Premiere version: F. Florea
00275     \author Seconde version: E. Ramasso & S. Jullien
00276    \version 11.0 (01/12/03); Include : proto2D.h, fcm.h
00277 */
00278 void calcul_coeff_appartenance(fuzzy_c_means_t *fcm, data_input dataI , data_output *dataO)
00279 {
00280   int i,j,k,l,x,y,z,a,b;
00281   float S,S1,S2,S3;
00282 
00283   fcm->variation=0; 
00284   for(a=0;a<dataI.nb_pts;a++)
00285     for(i=0;i<fcm->nb_class;i++)
00286       {
00287         S3=S1=S2=S=0;
00288         
00289         for(x=0;x<dataI.nb_attr;x++)
00290           S1=S1+pow((dataI.attributes[x][a]-fcm->centre[i][x]),2);
00291         
00292         S3=1/pow(S1+0.001,1/(fcm->fuzzy_coeff-1));
00293         
00294         for(j=0;j<fcm->nb_class;j++)
00295           {
00296             for(y=0;y<dataI.nb_attr;y++)
00297               S2=S2+pow((dataI.attributes[y][a]-fcm->centre[j][y]),2);
00298             
00299             S2=1/pow(S2,1/(fcm->fuzzy_coeff-1));
00300             S=S+S2;
00301           }
00302         
00303         fcm->variation=fcm->variation+ABS(dataO->classes.fuzzy[i][a]-(S3/S))*10;
00304         dataO->classes.fuzzy[i][a]=S3/S;
00305       } 
00306 
00307 }
00308 
00309 
00310 
00311 /* *************************  CENTROIDES  ***************************/
00312 /*
00313     \brief Fonction d'appartenance
00314 
00315     Cette fonction recalcule les centroïdes
00316   
00317     \param fcm le descripteur du classifieur fuzzy C mean
00318     \param dataI structure contenant les données d'entrée
00319     \param dataO pointeur sur la structure contenant les données de sortie
00320     \author Premiere version: F. Florea
00321     \author Seconde version: E. Ramasso & S. Jullien
00322     \version 01/12/03
00323 */
00324 void calcul_centroides(fuzzy_c_means_t *fcm, data_input dataI , data_output *dataO)
00325 {
00326   int i,j,k,l;
00327   float S1,S2;
00328   
00329   for(j=0;j<dataI.nb_attr;j++)
00330     {
00331      for(i=0;i<fcm->nb_class;i++)
00332          {
00333          S1=S2=0;
00334          for(k=0;k<dataI.nb_pts;k++)
00335            {
00336              S1=S1+pow(dataO->classes.fuzzy[i][k],fcm->fuzzy_coeff)*dataI.attributes[j][k];
00337              S2=S2+pow(dataO->classes.fuzzy[i][k],fcm->fuzzy_coeff);
00338            }
00339          fcm->centre[i][j]=(int)(S1/S2);
00340          printf("centre[%d][%d] = %d\n",i,j,fcm->centre[i][j]);
00341          }
00342     printf("\n");
00343     }
00344 }
00345 
00346 
00347 
00348 /* *************************  INITIALISATION CENTROÏDES  ***************/
00349 /*
00350     \brief Fonction d'initialisation des centroides
00351 
00352     Cette fonction initialise la valeur des centroïdes.
00353 
00354     
00355     \param fcm le descripteur du classifieur fuzzy C mean
00356     \param dataI structure contenant les données d'entrée
00357     \param dataO pointeur sur la structure contenant les données de sortie
00358     \author Premiere version: F. Florea
00359     \author Seconde version: E. Ramasso & S. Jullien
00360     \version 01/12/03
00361 */
00362 
00363 void init_coeff_appartenance(fuzzy_c_means_t *fcm, data_input dataI , data_output *dataO)
00364 {
00365   int tmp;
00366   int i,j,k,x;
00367   float *a;
00368   int max,rnd;
00369   FILE *toto;
00370   
00371   if ((strlen(fcm->init_type)==1)&&( (strstr(fcm->init_type,"0")!=NULL) || (strstr(fcm->init_type,"1")!=NULL) ))
00372     {
00373       printf("...Choix d'initialisation = %d\n",atoi(fcm->init_type));
00374       
00375       /* si init_type=0 => initialisation tableaux avec les coef. d'appartenance directement random */
00376       if (atoi(fcm->init_type) == 0)
00377         {
00378           srand((unsigned int)time(NULL));
00379           for(i=0;i<dataI.nb_pts;i++)
00380             {
00381               max=0;
00382               for(k=0;k<fcm->nb_class;k++)
00383                 {
00384                   dataO->classes.fuzzy[k][i]=(rand()%(100));
00385                   max=max+dataO->classes.fuzzy[k][i];
00386                 }
00387               
00388               for(k=0;k<fcm->nb_class;k++)
00389                 if (max!=0) dataO->classes.fuzzy[k][i]=(dataO->classes.fuzzy[k][i])/max;
00390             }            
00391         }
00392       
00393       /* si init_type=1 => initialisation centre des classes aleatoires, et ensuite calcul des 
00394          tableaux avec coeff. d'appartenance directement */
00395       else if (atoi(fcm->init_type) == 1)
00396         {
00397           a=(float *)Calloc(fcm->nb_class,sizeof(float));
00398           
00399           /* calcul max dans l'image d'entrée */
00400           max=0;
00401           for(k=0;k<dataI.nb_attr;k++)
00402             for(i=0;i<dataI.nb_pts;i++)
00403               if (dataI.attributes[k][i]>max) max=dataI.attributes[k][i];
00404           
00405           
00406           /* initialisation des centroïdes aleatoires */
00407           for(x=0;x<dataI.nb_attr;x++)
00408             for(i=0;i<fcm->nb_class;i++)
00409               fcm->centre[i][x]=rand()%(max);
00410           
00411           
00412           /* initialisation des coefficients d'appartenance à partir des centroïdes */
00413           for(x=0;x<dataI.nb_attr;x++)
00414             for(i=0;i<dataI.nb_pts;i++)
00415               {
00416                 max=0;
00417                 for(k=0;k<fcm->nb_class;k++)
00418                   {
00419                     a[k]=ABS(fcm->centre[k][x]-dataI.attributes[x][i]);
00420                     max=max+a[k];
00421                   }
00422                 for(k=0;k<fcm->nb_class;k++)
00423                   dataO->classes.fuzzy[k][i]=a[k]/max;
00424               }
00425           
00426         }
00427     }
00428   
00429   /* nom_fichier = initialisation centre des classes avec l'information lue dans un fichier ".txt" */
00430   else
00431     {
00432       printf("...initialisation par fichier = lecture dans '%s' les coeff suivants :\n\n",fcm->init_type);
00433       /* allocation */
00434       a=(float *)Calloc(fcm->nb_class,sizeof(float));
00435 
00436       /* ouvrir fichier */
00437       toto=fopen(fcm->init_type,"r");
00438       /* recuperation */
00439       for(i=0;i<fcm->nb_class;i++)
00440         {
00441           for(j=0;j<dataI.nb_attr;j++)
00442             {
00443             fscanf(toto,"%d ", &tmp);
00444             fcm->centre[i][j] = (unsigned short)tmp;
00445             printf("centre[%d][%d] = %d \t",i,j,fcm->centre[i][j]);
00446           }   
00447         printf("\n");
00448         }
00449 
00450       /* fermeture fichier */
00451       fclose(toto);
00452       
00453       /* initialisation des coefficients d'appartenance à partir des centroïdes */
00454       for(x=0;x<dataI.nb_attr;x++)
00455         for(i=0;i<dataI.nb_pts;i++)
00456           {
00457             max=0;
00458             for(k=0;k<fcm->nb_class;k++)
00459               {
00460                 a[k]=ABS(fcm->centre[k][x]-dataI.attributes[x][i]);
00461                 max=max+a[k];
00462               }
00463 
00464             for(k=0;k<fcm->nb_class;k++)
00465               dataO->classes.fuzzy[k][i]=a[k]/max;
00466           }
00467     }
00468   
00469   /* initialisation complète aléatoire */
00470 }
00471 
00472 
00473 
00474 
00475 
00476  
00477 
00478 
00479 
00480 

Generated on Tue Apr 22 13:31:02 2008 for donnee1D by  doxygen 1.5.3