Main Page   Data Structures   File List   Data Fields   Globals  

cluster.c

Go to the documentation of this file.
00001 #include        "sadie.h"
00002 
00003 typedef struct _MERGE
00004 {
00005   short cls1;
00006   short cls2;
00007   PIXEL dist;
00008   struct _MERGE *next;
00009 } MERGE;
00010 
00011 /*-Copyright Information------------------------------------------------------*/
00012 /* Copyright (c) 1990 by the University of Arizona Digital Image Analysis Lab */
00013 /*----------------------------------------------------------------------------*/
00014 /*-General Information--------------------------------------------------------*/
00015 /*                                                                            */
00016 /*   This function determines the intrinsic groupings of pixels in feature    */
00017 /*   space, using an iterative K-means clustering algorithm. Clusters with    */
00018 /*   too few pixels are discarded, and clusters that are too close are merged */
00019 /*   in the iteration process. After the clusters have been determined, the   */
00020 /*   entire input image is classified in a final pass.                        */
00021 /*                                                                            */
00022 /*----------------------------------------------------------------------------*/
00023 /*-Background Information-----------------------------------------------------*/
00024 /*                                                                            */
00025 /*   Duda, R.D., and Hart, P.E.:                                              */
00026 /*   "Pattern Classification and Scene Analysis,"                             */
00027 /*   J. Wiley and Sons, New York, 1973.                                       */
00028 /*                                                                            */
00029 /*----------------------------------------------------------------------------*/
00030 /* Interface Information------------------------------------------------------*/
00031 void
00032 CLUSTER (IMAGE * in,            /*  I   Pointer to the input image.                           */
00033          short niter,           /*  I   Number of iterations.                                 */
00034          short nclass,          /*  I   Number of seed classes.                               */
00035          short csize,           /*  |   Minimum number of pixels in each class.               */
00036          PIXEL mthr,            /*  I   Threshold for merging clusters.                       */
00037          short iinc,            /*  I   Band increment.                                       */
00038          short jinc,            /*  I   Line increment.                                       */
00039          short kinc,            /*  I   Pixels/line increment.                                */
00040          PIXEL othr,            /*  I   Outlier threshold.                                    */
00041          IMAGE ** out           /*  O   Address of a pointer to the output image.             */
00042 /*----------------------------------------------------------------------------*/
00043   )
00044 {
00045   register short i, j, k, m, n, class, nsize, *mrgd = 0;
00046   char msg[SLEN];
00047   long *cnt = 0;
00048   double pinc, psum;
00049   PIXEL *mean = 0, *nwmn = 0, *dev =
00050     0, gmin, gmax, ginc, gsum, gmig, gdiff, gval;
00051   MERGE *head = 0, *tail, *ptr, *newClass;
00052 
00053   if (TIMES)
00054     TIMING (T_CLUSTER);
00055   if (NAMES)
00056     {
00057       MESSAGE ('I', "");
00058       MESSAGE ('I', "CLUSTER");
00059       MESSAGE ('I', "");
00060       sprintf (msg, " Input image:                   %s", in->text);
00061       MESSAGE ('I', msg);
00062       sprintf (msg, " Number of iterations:          %d", niter);
00063       MESSAGE ('I', msg);
00064       sprintf (msg, " Number of seed classes:        %d", nclass);
00065       MESSAGE ('I', msg);
00066       sprintf (msg, " Minimum class size:            %d", csize);
00067       MESSAGE ('I', msg);
00068       sprintf (msg, " Class merging threshold:     %12.4e", mthr);
00069       MESSAGE ('I', msg);
00070       sprintf (msg, " Subsample increment: bands:    %d", iinc);
00071       MESSAGE ('I', msg);
00072       sprintf (msg, "                      lines:    %d", jinc);
00073       MESSAGE ('I', msg);
00074       sprintf (msg, "                      pixels:   %d", kinc);
00075       MESSAGE ('I', msg);
00076       sprintf (msg, " Outlier threshold:           %12.4e", othr);
00077       MESSAGE ('I', msg);
00078       MESSAGE ('I', " ...............");
00079     }
00080 
00081   /* check input */
00082   if (!CHECKIMG (in))
00083     {
00084       MESSAGE ('E', " Can't identify image.");
00085       goto the_end;
00086     }
00087   else if (iinc <= 0)
00088     {
00089       MESSAGE ('E', " Band subsample increment must be greater than zero.");
00090       goto the_end;
00091     }
00092   else if (jinc <= 0)
00093     {
00094       MESSAGE ('E', " Line subsample increment must be greater than zero.");
00095       goto the_end;
00096     }
00097   else if (kinc <= 0)
00098     {
00099       MESSAGE ('E', " Pixel subsample increment must be greater than zero.");
00100       goto the_end;
00101     }
00102   else if (niter <= 0)
00103     {
00104       MESSAGE ('E', " Number of iterations must be greater than zero.");
00105       goto the_end;
00106     }
00107   else if (nclass <= 0)
00108     {
00109       MESSAGE ('E', " Number of classes must be greater than zero.");
00110       goto the_end;
00111     }
00112   else if (csize <= 0)
00113     {
00114       MESSAGE ('E', " Minimum class size must be greater than zero.");
00115       goto the_end;
00116     }
00117   else if (mthr < 0.0)
00118     {
00119       MESSAGE ('E',
00120                " Distance threshold must be greater than or equal to zero.");
00121       goto the_end;
00122     }
00123   else if (othr < 0.0)
00124     {
00125       MESSAGE ('E',
00126                " Distance threshold must be greater than or equal to zero.");
00127       goto the_end;
00128     }
00129 
00130   /* create image of appropriate size */
00131   if (!CHECKIMG (*out))
00132     GETMEM (1, in->nlin, in->npix, out);
00133   if (!*out)
00134     goto the_end;
00135 
00136   /* allocate space */
00137   nsize = nclass + 1;
00138   if (!(mrgd = (short *) malloc (nsize * sizeof (short))))
00139     {
00140       MESSAGE ('E', " Memory request failed.");
00141       goto the_end;
00142     }
00143   if (!(cnt = (long *) malloc (nsize * sizeof (long))))
00144     {
00145       MESSAGE ('E', " Memory request failed.");
00146       goto the_end;
00147     }
00148   if (!(mean = (PIXEL *) malloc (nsize * in->nbnd * sizeof (PIXEL))))
00149     {
00150       MESSAGE ('E', " Memory request failed.");
00151       goto the_end;
00152     }
00153   if (!(nwmn = (PIXEL *) malloc (nsize * in->nbnd * sizeof (PIXEL))))
00154     {
00155       MESSAGE ('E', " Memory request failed.");
00156       goto the_end;
00157     }
00158   if (!(dev = (PIXEL *) malloc (nsize * in->nbnd * sizeof (PIXEL))))
00159     {
00160       MESSAGE ('E', " Memory request failed.");
00161       goto the_end;
00162     }
00163   if (!
00164       (head =
00165        (MERGE *) malloc ((((nclass - 1) * nclass) / 2 + 2) * sizeof (MERGE))))
00166     {
00167       MESSAGE ('E', " Memory request failed.");
00168       goto the_end;
00169     }
00170 
00171   /* initialize progress indicator */
00172   if (LINES && !PROGRESS (psum = 0.0))
00173     goto the_end;
00174   pinc =
00175     0.5 / (double) (niter * (in->nlin / jinc + (in->nlin % jinc ? 1 : 0)) +
00176                     in->nlin);
00177 
00178   /* initialize */
00179   for (i = 0; i < in->nbnd; i++)
00180     {
00181       gmax = gmin = in->data[i][0][0];
00182       for (j = 0; j < in->nlin; j++)
00183         {
00184           for (k = 0; k < in->npix; k++)
00185             {
00186               gmin = min (gmin, in->data[i][j][k]);
00187               gmax = max (gmax, in->data[i][j][k]);
00188             }
00189         }
00190       ginc = (gmax - gmin) / (PIXEL) nclass;
00191       for (m = 1; m < nsize; m++)
00192         {
00193           mean[i * nsize + m] =
00194             gmin + (PIXEL) (((double) m - 0.5) * (double) ginc);
00195         }
00196     }
00197   tail = head + 1;
00198   tail->cls1 = 0;
00199   tail->cls2 = 0;
00200   tail->dist = mthr * (PIXEL) in->nbnd;
00201   tail->next = 0;
00202 
00203   /* iterate */
00204   for (m = 0; m < niter; m++)
00205     {
00206 
00207       /* initialize */
00208       for (n = 0; n < nsize; n++)
00209         {
00210           cnt[n] = 0L;
00211           mrgd[n] = TRUE;
00212           for (i = 0; i < in->nbnd; i++)
00213             {
00214               nwmn[i * nsize + n] = (PIXEL) 0;
00215               dev[i * nsize + n] = (PIXEL) 0;
00216             }
00217         }
00218 
00219       /* cluster */
00220       for (class = 1, j = 0; j < in->nlin; j += jinc)
00221         {
00222           for (k = 0; k < in->npix; k += kinc)
00223             {
00224               gmin = (PIXEL) 0;
00225               for (i = 0; i < in->nbnd; i += iinc)
00226                 {
00227                   gmin +=
00228                     (PIXEL)
00229                     fabs ((double)
00230                           (in->data[i][j][k] - mean[i * nsize + class]));
00231                 }
00232               for (n = 1; n <= nclass; n++)
00233                 {
00234                   if (n != class)
00235                     {
00236                       gsum = (PIXEL) 0;
00237                       for (i = 0; i < in->nbnd && gmin > gsum; i += iinc)
00238                         {
00239                           gsum +=
00240                             (PIXEL)
00241                             fabs ((double)
00242                                   (in->data[i][j][k] - mean[i * nsize + n]));
00243                         }
00244                       if (gmin > gsum)
00245                         {
00246                           gmin = gsum;
00247                           class = n;
00248                         }
00249                     }
00250                 }
00251               (*out)->data[0][j][k] = (PIXEL) class;
00252               for (i = 0; i < in->nbnd; i += iinc)
00253                 {
00254                   nwmn[i * nsize + class] += in->data[i][j][k];
00255                 }
00256               cnt[class] += 1L;
00257             }
00258           if (LINES && !PROGRESS (psum += pinc))
00259             goto the_end;
00260         }
00261 
00262       /* compute new mean vectors and average migration */
00263       gmig = (PIXEL) 0;
00264       for (i = 0; i < in->nbnd; i += iinc)
00265         {
00266           for (n = 1; n <= nclass; n++)
00267             {
00268               if (cnt[n] > 0L)
00269                 {
00270                   nwmn[i * nsize + n] /= (PIXEL) cnt[n];
00271                   gmig +=
00272                     (PIXEL)
00273                     fabs ((double)
00274                           (nwmn[i * nsize + n] - mean[i * nsize + n]));
00275                   mean[i * nsize + n] = nwmn[i * nsize + n];
00276                 }
00277             }
00278         }
00279       gmig /= (double) (in->nbnd * nclass);
00280 
00281       /* compute new standard deviation vectors */
00282       for (j = 0; j < in->nlin; j += jinc)
00283         {
00284           for (k = 0; k < in->npix; k += kinc)
00285             {
00286               for (i = 0; i < in->nbnd; i += iinc)
00287                 {
00288                   class = (short) (*out)->data[0][j][k];
00289                   gdiff = in->data[i][j][k] - mean[i * nsize + class];
00290                   dev[i * nsize + class] += gdiff * gdiff;
00291                 }
00292             }
00293           if (LINES && !PROGRESS (psum += pinc))
00294             goto the_end;
00295         }
00296       for (n = 1; n <= nclass; n++)
00297         {
00298           for (i = 0; i < in->nbnd; i += iinc)
00299             {
00300               if (cnt[n] > 0L)
00301                 {
00302                   dev[i * nsize + n] =
00303                     (PIXEL) sqrt ((double) dev[i * nsize + n] /
00304                                   (double) cnt[n]);
00305                 }
00306             }
00307         }
00308 
00309       /* eliminate classes that are too small */
00310       for (n = 1; n <= nclass; n++)
00311         {
00312           if (cnt[n] < csize)
00313             {
00314               for (j = n; j < nclass; j++)
00315                 {
00316                   for (i = 0; i < in->nbnd; i += iinc)
00317                     {
00318                       mean[i * nsize + j] = mean[i * nsize + j + 1];
00319                       dev[i * nsize + j] = dev[i * nsize + j + 1];
00320                     }
00321                   cnt[j] = cnt[j + 1];
00322                 }
00323               nclass -= 1;
00324               n -= 1;
00325             }
00326         }
00327 
00328       /* find and merge classes that are too close together */
00329       newClass = head + 2;
00330       head->next = tail;
00331       for (n = 1; n <= nclass - 1; n++)
00332         {
00333           for (k = n + 1; k <= nclass; k++)
00334             {
00335               gsum = (PIXEL) 0;
00336               for (i = 0; i < in->nbnd; i += iinc)
00337                 {
00338                   gval = dev[i * nsize + n] + dev[i * nsize + k];
00339                   if (gval != (PIXEL) 0
00340                       && (gval =
00341                           (PIXEL)
00342                           fabs ((double)
00343                                 (mean[i * nsize + n] -
00344                                  mean[i * nsize + k])) / gval) < mthr)
00345                     {
00346                       gsum += gval;
00347                       if (i + iinc >= in->nbnd)
00348                         {
00349                           for (ptr = head; ptr->next->dist <= gsum;
00350                                ptr = ptr->next);
00351                           newClass->cls1 = n;
00352                           newClass->cls2 = k;
00353                           newClass->dist = gsum;
00354                           newClass->next = ptr->next;
00355                           ptr->next = newClass++;
00356                         }
00357                     }
00358                   else
00359                     {
00360                       break;
00361                     }
00362                 }
00363             }
00364         }
00365       for (ptr = head->next; ptr != tail; ptr = ptr->next)
00366         {
00367           if (mrgd[ptr->cls1] == TRUE && mrgd[ptr->cls2] == TRUE)
00368             {
00369               for (i = 0; i < in->nbnd; i += iinc)
00370                 {
00371                   gval =
00372                     mean[i * nsize + ptr->cls1] * cnt[ptr->cls1] +
00373                     mean[i * nsize + ptr->cls2] * cnt[ptr->cls2];
00374                   mean[i * nsize + ptr->cls1] =
00375                     gval / (PIXEL) (cnt[ptr->cls1] + cnt[ptr->cls2]);
00376                 }
00377               for (j = ptr->cls2; j <= nclass - 1; j++)
00378                 {
00379                   for (i = 0; i < in->nbnd; i++)
00380                     {
00381                       mean[i * nsize + j] = mean[i * nsize + j + 1];
00382                     }
00383                 }
00384               mrgd[ptr->cls1] = FALSE;
00385               mrgd[ptr->cls2] = FALSE;
00386               nclass -= 1;
00387             }
00388         }
00389 
00390       /* output iteration statistics */
00391       if (m == 0)
00392         {
00393           MESSAGE ('I', "");
00394           MESSAGE ('I', " Mean vector migration averaged over all classes:");
00395           MESSAGE ('I',
00396                    " Iteration     Migration     Number of classes after merging");
00397         }
00398       sprintf (msg, "%6d%18.4e%20d", m + 1, (double) gmig, nclass);
00399       MESSAGE ('I', msg);
00400     }
00401 
00402   /* initialize */
00403   for (n = 0; n < nsize; n++)
00404     {
00405       cnt[n] = 0L;
00406       for (i = 0; i < in->nbnd; i++)
00407         {
00408           nwmn[i * nsize + n] = (PIXEL) 0;
00409         }
00410     }
00411 
00412   /* classify */
00413   for (class = 1, j = 0; j < in->nlin; j++)
00414     {
00415       for (k = 0; k < in->npix; k++)
00416         {
00417           class = max (1, class);
00418           gmin = (PIXEL) 0;
00419           for (i = 0; i < in->nbnd; i++)
00420             {
00421               gmin +=
00422                 (PIXEL)
00423                 fabs ((double) (in->data[i][j][k] - mean[i * nsize + class]));
00424             }
00425           for (n = 1; n <= nclass; n++)
00426             {
00427               if (n != class)
00428                 {
00429                   gsum = (PIXEL) 0;
00430                   for (i = 0; i < in->nbnd && gmin > gsum; i++)
00431                     {
00432                       gsum +=
00433                         (PIXEL)
00434                         fabs ((double)
00435                               (in->data[i][j][k] - mean[i * nsize + n]));
00436                     }
00437                   if (gmin > gsum)
00438                     {
00439                       gmin = gsum;
00440                       class = n;
00441                     }
00442                 }
00443             }
00444           for (i = 0; i < in->nbnd; i++)
00445             {
00446               if ((PIXEL)
00447                   fabs ((double)
00448                         (in->data[i][j][k] - mean[i * nsize + class])) >
00449                   othr * dev[i * nsize + class])
00450                 {
00451                   class = 0;
00452                   break;
00453                 }
00454             }
00455           (*out)->data[0][j][k] = class;
00456           if (class != 0)
00457             {
00458               for (i = 0; i < in->nbnd; i++)
00459                 {
00460                   nwmn[i * nsize + class] += in->data[i][j][k];
00461                 }
00462             }
00463           cnt[class] += 1L;
00464         }
00465       if (LINES && !PROGRESS (psum += pinc))
00466         goto the_end;
00467     }
00468 
00469   /* compute new mean vectors and average migration */
00470   gmig = (PIXEL) 0;
00471   for (i = 0; i < in->nbnd; i++)
00472     {
00473       for (n = 1; n <= nclass; n++)
00474         {
00475           if (cnt[n] > 0L)
00476             {
00477               nwmn[i * nsize + n] /= (PIXEL) cnt[n];
00478               gmig +=
00479                 (PIXEL)
00480                 fabs ((double) (nwmn[i * nsize + n] - mean[i * nsize + n]));
00481               mean[i * nsize + n] = nwmn[i * nsize + n];
00482             }
00483         }
00484     }
00485   gmig /= (double) (in->nbnd * nclass);
00486 
00487   /* compute new standard deviation vectors */
00488   for (i = 0; i < nsize * in->nbnd; i++)
00489     {
00490       dev[i] = (PIXEL) 0;
00491     }
00492   for (j = 0; j < in->nlin; j++)
00493     {
00494       for (k = 0; k < in->npix; k++)
00495         {
00496           for (i = 0; i < in->nbnd; i++)
00497             {
00498               class = (short) (*out)->data[0][j][k];
00499               if (class != 0)
00500                 {
00501                   gdiff = in->data[i][j][k] - mean[i * nsize + class];
00502                   dev[i * nsize + class] += gdiff * gdiff;
00503                 }
00504             }
00505         }
00506       if (LINES && !PROGRESS (psum += pinc))
00507         goto the_end;
00508     }
00509   for (n = 1; n <= nclass; n++)
00510     {
00511       for (i = 0; i < in->nbnd; i++)
00512         {
00513           if (cnt[n] > 0L)
00514             {
00515               dev[i * nsize + n] =
00516                 (PIXEL) sqrt ((double) dev[i * nsize + n] / (double) cnt[n]);
00517             }
00518         }
00519     }
00520 
00521   /* output iteration statistics */
00522   sprintf (msg, "     *%18.4e%20d", (double) gmig, nclass);
00523   MESSAGE ('I', msg);
00524 
00525   /* output classification statistics */
00526   MESSAGE ('I', "");
00527   MESSAGE ('I', " Mean and standard deviation vectors of each class:");
00528   sprintf (msg, " Class  ");
00529   for (i = 0; i < in->nbnd; i++)
00530     {
00531       sprintf (msg + strlen (msg), "           Band %-11d", i + 1);
00532     }
00533   sprintf (msg + strlen (msg), "# Pixels     %%");
00534   MESSAGE ('I', msg);
00535   sprintf (msg, "%6d", 0);
00536   for (i = 0; i < in->nbnd; i++)
00537     {
00538       sprintf (msg + strlen (msg), "              N/A          ", "");
00539     }
00540   sprintf (msg + strlen (msg), "%10ld%7.1f   (Threshold class)", cnt[0],
00541            100.0 * (double) cnt[0] / ((double) in->nlin * (double) in->npix));
00542   MESSAGE ('I', msg);
00543   for (n = 1; n <= nclass; n++)
00544     {
00545       sprintf (msg, "%6d", n);
00546       for (i = 0; i < in->nbnd; i++)
00547         {
00548           sprintf (msg + strlen (msg), "%13.4e +/-%10.4e",
00549                    (double) mean[i * nsize + n], (double) dev[i * nsize + n]);
00550         }
00551       sprintf (msg + strlen (msg), "%10ld%7.1f", cnt[n],
00552                100.0 * (double) cnt[n] / ((double) in->nlin *
00553                                           (double) in->npix));
00554       MESSAGE ('I', msg);
00555     }
00556 
00557 the_end:
00558   if (mrgd)
00559     free (mrgd);
00560   if (cnt)
00561     free (cnt);
00562   if (mean)
00563     free (mean);
00564   if (nwmn)
00565     free (nwmn);
00566   if (dev)
00567     free (dev);
00568   if (head)
00569     free (head);
00570   if (TIMES)
00571     TIMING (T_EXIT);
00572 }

Generated on Sun May 18 15:36:08 2003 for tclSadie by doxygen1.3