Main Page   Data Structures   File List   Data Fields   Globals  

gradient.c

Go to the documentation of this file.
00001 #include        "sadie.h"
00002 
00003 /*-Copyright Information------------------------------------------------------*/
00004 /* Copyright (c) 1988 by the University of Arizona Digital Image Analysis Lab */
00005 /*----------------------------------------------------------------------------*/
00006 /*-General Information--------------------------------------------------------*/
00007 /*                                                                            */
00008 /*   This function computes a two-dimensional gradient (magnitude and         */
00009 /*   direction) of an image, using two user-supplied convolution kernels.     */
00010 /*   The magnitude is computed as the vector magnitude of the output          */
00011 /*   of the two kernels, and the direction is computed as the angle           */
00012 /*   between the two orthogonal gradient vectors.                             */
00013 /*                                                                            */
00014 /*----------------------------------------------------------------------------*/
00015 /*-Background Information-----------------------------------------------------*/
00016 /*                                                                            */
00017 /*   Robinson, G.S.:                                                          */
00018 /*   "Detection and Coding of Edges Using Directional Masks."                 */
00019 /*   Optical Engineering, Vol. 16, No. 6 (Nov/Dec 1977), pp. 580-585          */
00020 /*                                                                            */
00021 /*----------------------------------------------------------------------------*/
00022 /*-Interface Information------------------------------------------------------*/
00023 void
00024 GRADIENT (IMAGE * in,           /*  I   Pointer to the input image.                           */
00025           PIXEL * vert,         /*  I   Pointer to a square convolution kernel[size][size] for */
00026           /*      the y-derivative. It should return positive values    */
00027           /*      for gradients increasing to the "top" of the image.   */
00028           PIXEL * horz,         /*  I   Pointer to a square convolution kernel[size][size] for */
00029           /*      the x-derivative. It should return positive values    */
00030           /*      for gradients increasing to the "right" of the image. */
00031           short size,           /*  I   Kernel size in lines and pixels/line.                 */
00032           IMAGE ** out1,        /*  O   Address of a pointer to the output image              */
00033           /*      containing the gradient magnitude.                    */
00034           IMAGE ** out2         /*  O   Address of a pointer to the output image              */
00035           /*      containing the gradient direction.                    */
00036 /*----------------------------------------------------------------------------*/
00037   )
00038 {
00039   register short i, j, k, l, m, n = size / 2;
00040   char msg[SLEN];
00041   double dv, dh, pinc, psum;
00042 
00043   int progmeter;
00044   double progress;
00045   int progcount, progtotal, progincr;
00046   int cancel = 0;
00047 
00048   progmeter = ProgMeter_Create ("Gradient");
00049   progress = 0.0;
00050 
00051   if (TIMES)
00052     TIMING (T_GRADIENT);
00053   if (NAMES)
00054     {
00055       MESSAGE ('I', "");
00056       MESSAGE ('I', "GRADIENT");
00057       MESSAGE ('I', "");
00058       sprintf (msg, " Input image:                    %s", in->text);
00059       MESSAGE ('I', msg);
00060       sprintf (msg, " Kernel size: lines and pixels:  %d", size);
00061       MESSAGE ('I', msg);
00062       if (size <= SLEN / 16)
00063         {
00064           MESSAGE ('I', " Horizontal kernel:");
00065           for (i = 0; i < size; i++)
00066             {
00067               for (j = k = 0, msg[k++] = ' '; j < size;
00068                    j += 1, k = strlen (msg))
00069                 {
00070                   sprintf (msg + k, "%12.4e", (double) horz[i * size + j]);
00071                 }
00072               MESSAGE ('I', msg);
00073             }
00074           MESSAGE ('I', " Vertical kernel:");
00075           for (i = 0; i < size; i++)
00076             {
00077               for (j = k = 0, msg[k++] = ' '; j < size;
00078                    j += 1, k = strlen (msg))
00079                 {
00080                   sprintf (msg + k, "%12.4e", (double) vert[i * size + j]);
00081                 }
00082               MESSAGE ('I', msg);
00083             }
00084         }
00085       else
00086         {
00087           MESSAGE ('I', " Kernels too large to list.");
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 (size < 2 || size % 2 == 0)
00099     {
00100       MESSAGE ('E',
00101                " Size of convolution mask must be an odd number greater than two.");
00102       goto the_end;
00103     }
00104   else if (size > in->nlin || size > in->npix)
00105     {
00106       MESSAGE ('E',
00107                " Image size must be equal to or greater than convolution mask size.");
00108       goto the_end;
00109     }
00110 
00111   /* create images of appropriate size */
00112   if (!CHECKIMG (*out1))
00113     GETMEM (in->nbnd, in->nlin, in->npix, out1);
00114   if (!*out1)
00115     goto the_end;
00116   if (!CHECKIMG (*out2))
00117     GETMEM (in->nbnd, in->nlin, in->npix, out2);
00118   if (!*out2)
00119     goto the_end;
00120 
00121   /* initialize progress indicator */
00122   if (LINES && !PROGRESS (psum = 0.0))
00123     goto the_end;
00124   pinc = 1.0 / (double) in->nbnd / (double) (in->nlin - 2 * n);
00125   progtotal = in->nbnd * (in->nlin - 2 * n);
00126   progcount = 0;
00127   progincr = rint ((double) progtotal / 20.0);
00128 
00129   for (i = 0; i < in->nbnd; i++)
00130     {
00131 
00132       /* compute convolution */
00133       for (j = n; j < in->nlin - n; j++)
00134         {
00135           for (k = n; k < in->npix - n; k++)
00136             {
00137               dv = dh = 0.0;
00138               for (l = 0; l < size; l++)
00139                 {
00140                   for (m = 0; m < size; m++)
00141                     {
00142                       dv +=
00143                         (double) vert[l * size + m] * (double) in->data[i][j -
00144                                                                            n +
00145                                                                            l]
00146                         [k - n + m];
00147                       dh +=
00148                         (double) horz[l * size + m] * (double) in->data[i][j -
00149                                                                            n +
00150                                                                            l]
00151                         [k - n + m];
00152                     }
00153                 }
00154               (*out1)->data[i][j][k] = (PIXEL) sqrt ((dv * dv + dh * dh));
00155               if (dh == 0.0)
00156                 {
00157                   if (dv > 0.0)
00158                     {
00159                       (*out2)->data[i][j][k] = (PIXEL) (PI / 2.0);
00160                     }
00161                   else if (dv < 0.0)
00162                     {
00163                       (*out2)->data[i][j][k] = (PIXEL) (-PI / 2.0);
00164                     }
00165                   else          /* (dv == 0.0 ) */
00166                     {
00167                       (*out2)->data[i][j][k] = (PIXEL) 0.0;
00168                     }
00169                 }
00170               else
00171                 {
00172                   (*out2)->data[i][j][k] = (PIXEL) atan2 (dv, dh);
00173                 }
00174             }
00175           if (LINES && !PROGRESS (psum += pinc))
00176             goto the_end;
00177           if (progmeter)
00178             {
00179               progcount++;
00180               if ((progcount % progincr) == 0)
00181                 {
00182                   progress =
00183                     ((double) progcount / (double) progtotal) * 100.0;
00184                   cancel = ProgMeter_Update (progmeter, progress);
00185                   if (cancel != 0)
00186                     goto the_end;
00187                 }
00188             }
00189         }
00190 
00191       /* fill top and bottom margins */
00192       for (j = 0; j < n; j++)
00193         {
00194           for (k = n; k < in->npix - n; k++)
00195             {
00196               (*out1)->data[i][j][k] = (*out1)->data[i][n][k];
00197               (*out1)->data[i][in->nlin - j - 1][k] =
00198                 (*out1)->data[i][in->nlin - n - 1][k];
00199               (*out2)->data[i][j][k] = (*out2)->data[i][n][k];
00200               (*out2)->data[i][in->nlin - j - 1][k] =
00201                 (*out2)->data[i][in->nlin - n - 1][k];
00202             }
00203         }
00204 
00205       /* fill left and right margins */
00206       for (j = 0; j < in->nlin; j++)
00207         {
00208           for (k = 0; k < n; k++)
00209             {
00210               (*out1)->data[i][j][k] = (*out1)->data[i][j][n];
00211               (*out1)->data[i][j][in->npix - k - 1] =
00212                 (*out1)->data[i][j][in->npix - n - 1];
00213               (*out2)->data[i][j][k] = (*out2)->data[i][j][n];
00214               (*out2)->data[i][j][in->npix - k - 1] =
00215                 (*out2)->data[i][j][in->npix - n - 1];
00216             }
00217         }
00218     }
00219 
00220 the_end:
00221   if (TIMES)
00222     TIMING (T_EXIT);
00223 
00224   if (progmeter)
00225     {
00226       ProgMeter_Destroy (progmeter);
00227     }
00228 
00229   if (cancel != 0)
00230     {
00231       if (*out1)
00232         RELMEM (*out1);
00233       *out1 = NULL;
00234       if (*out2)
00235         RELMEM (*out2);
00236       *out2 = NULL;
00237     }
00238 }

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