Main Page   Data Structures   File List   Data Fields   Globals  

mindist.c

Go to the documentation of this file.
00001 #include        "sadie.h"
00002 
00003 /*-Copyright Information------------------------------------------------------*/
00004 /* Copyright (c) 1992 by the University of Arizona Digital Image Analysis Lab */
00005 /*----------------------------------------------------------------------------*/
00006 /*-General Information--------------------------------------------------------*/
00007 /*                                                                            */
00008 /*   This function performs a minimum distance classification on an image.    */
00009 /*                                                                            */
00010 /*   The discriminant function for classification of a pixel to a class is:   */
00011 /*                                                                            */
00012 /*   City-block distance classifier:                                          */
00013 /*      DC(X) = |X - M|                                                       */
00014 /*                                                                            */
00015 /*   Euclidean distance classifier:                                           */
00016 /*      DE(X) = (X - M)**t * (X - M)                                          */
00017 /*                                                                            */
00018 /*   Mahalanobis distance classifier:                                         */
00019 /*      DM(X) = (X - M)**t * C**-1 * (X - M)                                  */
00020 /*                                                                            */
00021 /*   where X is the feature vector, M is the class mean vector, and C**-1     */
00022 /*   is the inverse of the covariance matrix (equal for all classes).         */
00023 /*                                                                            */
00024 /*----------------------------------------------------------------------------*/
00025 /*-Interface Information------------------------------------------------------*/
00026 void
00027 MINDIST (IMAGE * in,            /*  I  Pointer to the input image.                             */
00028          short option,          /*  I  Switch, indicating the type of classifier:              */
00029          /*     CITYBLOCK     -   DC(X)                                 */
00030          /*     EUCLIDEAN     -   DE(X)                                 */
00031          /*     MAHALANOBIS   -   DM(X)                                 */
00032          short nlev,            /*  I  Number of classes                                       */
00033          /*     (and number of graylevels in the output image).         */
00034          double *mean,          /*  I  Pointer to the matrix[nlev][nbnd] of mean graylevels.   */
00035          double *cov,           /*  I  Pointer to the covariance matrix[nbnd][nbnd].           */
00036          IMAGE ** out           /*  O  Address of a pointer to the output image.               */
00037 /*--------------------------------------------------------------------------- */
00038   )
00039 {
00040   register short i, j, k, m, n, l1, l2, ll, nl, np;
00041   char msg[SLEN];
00042   PIXEL *dist = 0, mindist;
00043   double *inv = 0;
00044 
00045   if (TIMES)
00046     TIMING (T_MINDIST);
00047   if (NAMES)
00048     {
00049       MESSAGE ('I', "");
00050       MESSAGE ('I', "MINDIST");
00051       MESSAGE ('I', "");
00052       sprintf (msg, " Input image:          %s", in->text);
00053       MESSAGE ('I', msg);
00054       if (option == CITYBLOCK)
00055         {
00056           MESSAGE ('I', " Classifier:           City-block");
00057         }
00058       else if (option == EUCLIDEAN)
00059         {
00060           MESSAGE ('I', " Classifier:           Euclidean");
00061         }
00062       else if (option == MAHALANOBIS)
00063         {
00064           MESSAGE ('I', " Classifier:           Mahalanobis");
00065         }
00066       sprintf (msg, " Number of classes:    %d", nlev);
00067       MESSAGE ('I', msg);
00068       sprintf (msg, " Mean graylevels:");
00069       MESSAGE ('I', msg);
00070       for (n = j = 0; j < nlev; j++)
00071         {
00072           sprintf (msg, "  Class%3d:          ", j + 1);
00073           for (k = 0, m = strlen (msg); k < in->nbnd; k++, m = strlen (msg))
00074             {
00075               sprintf (msg + m, "%12.4e", mean[n++]);
00076             }
00077           MESSAGE ('I', msg);
00078         }
00079       MESSAGE ('I', " Covariance matrix:");
00080       for (n = j = 0; j < in->nbnd; j++)
00081         {
00082           sprintf (msg, "  Band%4d:          ", j + 1);
00083           for (k = 0, m = strlen (msg); k < in->nbnd; k++, m = strlen (msg))
00084             {
00085               sprintf (msg + m, "%12.4e", cov[n++]);
00086             }
00087           MESSAGE ('I', msg);
00088         }
00089       MESSAGE ('I', " ...............");
00090     }
00091 
00092   /* check input  */
00093   if (!CHECKIMG (in))
00094     {
00095       MESSAGE ('E', "Can't identify image.");
00096       goto the_end;
00097     }
00098   else if (option != CITYBLOCK && option != EUCLIDEAN
00099            && option != MAHALANOBIS)
00100     {
00101       MESSAGE ('E',
00102                " Option must be one of CITYBLOCK, EUCLIDEAN, or MAHALANOBIS.");
00103       goto the_end;
00104     }
00105   else if (nlev <= 0)
00106     {
00107       MESSAGE ('E', "Number of classes must be greater than zero.");
00108       goto the_end;
00109     }
00110 
00111   /* create image of appropriate size */
00112   if (!CHECKIMG (*out))
00113     GETMEM (1, in->nlin, in->npix, out);
00114   if (!*out)
00115     goto the_end;
00116 
00117   /* allocate space for  distance array */
00118   if (!(dist = (PIXEL *) malloc (nlev * sizeof (PIXEL))))
00119     {
00120       MESSAGE ('E', "Memory request failed.");
00121       goto the_end;
00122     }
00123 
00124   /* City-block distance classifier */
00125   if (option == CITYBLOCK)
00126     {
00127       for (nl = 0; nl < in->nlin; nl++)
00128         {
00129           for (np = 0; np < in->npix; np++)
00130             {
00131               for (k = 0; k < nlev; k++)
00132                 {
00133                   dist[k] = 0.0;
00134                   for (i = 0; i < in->nbnd; i++)
00135                     {
00136                       l1 = k * in->nbnd + i;
00137                       dist[k] += fabs (in->data[i][nl][np] - mean[l1]);
00138                     }
00139                 }
00140               mindist = dist[0];
00141               for (i = 0; i < nlev; i++)
00142                 {
00143                   if (dist[i] <= mindist)
00144                     {
00145                       (*out)->data[0][nl][np] = (PIXEL) (i + 1);
00146                     }
00147                 }
00148             }
00149         }
00150 
00151       /* Euclidean distance classifier */
00152     }
00153   else if (option == EUCLIDEAN)
00154     {
00155       for (nl = 0; nl < in->nlin; nl++)
00156         {
00157           for (np = 0; np < in->npix; np++)
00158             {
00159               for (k = 0; k < nlev; k++)
00160                 {
00161                   dist[k] = 0.0;
00162                   for (i = 0; i < in->nbnd; i++)
00163                     {
00164                       l1 = k * in->nbnd + i;
00165                       dist[k] +=
00166                         (in->data[i][nl][np] -
00167                          mean[l1]) * (in->data[i][nl][np] - mean[l1]);
00168                     }
00169                 }
00170               mindist = dist[0];
00171               for (i = 0; i < nlev; i++)
00172                 {
00173                   if (dist[i] <= mindist)
00174                     {
00175                       (*out)->data[0][nl][np] = (PIXEL) (i + 1);
00176                     }
00177                 }
00178             }
00179         }
00180 
00181       /* Mahalanobis distance classifier */
00182     }
00183   else if (option == MAHALANOBIS)
00184     {
00185 
00186       /* allocate space for inverse of covariance matrix and distance array */
00187       if (!(inv = (double *) malloc (in->nbnd * in->nbnd * sizeof (double))))
00188         {
00189           MESSAGE ('E', "Memory request failed.");
00190           goto the_end;
00191         }
00192       if (!(dist = (PIXEL *) malloc (nlev * sizeof (PIXEL))))
00193         {
00194           MESSAGE ('E', "Memory request failed.");
00195           goto the_end;
00196         }
00197       MATRIX_INVERT (cov, in->nbnd, inv);
00198 
00199       for (nl = 0; nl < in->nlin; nl++)
00200         {
00201           for (np = 0; np < in->npix; np++)
00202             {
00203               for (k = 0; k < nlev; k++)
00204                 {
00205                   dist[k] = 0.0;
00206                   for (i = 0; i < in->nbnd; i++)
00207                     {
00208                       for (j = 0; j < in->nbnd; j++)
00209                         {
00210                           l1 = k * in->nbnd + i;
00211                           l2 = k * in->nbnd + j;
00212                           ll = i * in->nbnd + j;
00213                           dist[k] +=
00214                             (in->data[i][nl][np] -
00215                              mean[l1]) * inv[ll] * (in->data[j][nl][np] -
00216                                                     mean[l2]);
00217                         }
00218                     }
00219                 }
00220               mindist = dist[0];
00221               for (i = 0; i < nlev; i++)
00222                 {
00223                   if (dist[i] <= mindist)
00224                     {
00225                       (*out)->data[0][nl][np] = (PIXEL) (i + 1);
00226                     }
00227                 }
00228             }
00229         }
00230     }
00231 
00232 the_end:
00233   if (inv)
00234     free (inv);
00235   if (dist)
00236     free (dist);
00237   if (TIMES)
00238     TIMING (T_EXIT);
00239 }

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