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 GRADIENT (
00024 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 ) { register short i, j, k, l, m, n=size/2;
00038     char   msg[SLEN];
00039     double dv, dh, pinc, psum;
00040 
00041     int progmeter;
00042     double progress;
00043     int progcount, progtotal, progincr;
00044     int cancel=0;
00045 
00046     progmeter = ProgMeter_Create("Gradient");
00047     progress = 0.0;
00048 
00049 
00050     if (TIMES) TIMING(T_GRADIENT);
00051     if (NAMES) {
00052         MESSAGE('I',"");
00053         MESSAGE('I',"GRADIENT");
00054         MESSAGE('I',"");
00055         sprintf(msg," Input image:                    %s",in->text);
00056         MESSAGE('I',msg);
00057         sprintf(msg," Kernel size: lines and pixels:  %d",size);
00058         MESSAGE('I',msg);
00059         if (size <= SLEN/16) {
00060             MESSAGE('I'," Horizontal kernel:");
00061             for (i=0; i<size; i++) {
00062                 for (j=k=0,msg[k++]=' '; j<size; j+=1,k=strlen(msg)) {
00063                     sprintf(msg+k,"%12.4e",(double)horz[i*size+j]);
00064                 }
00065                 MESSAGE('I',msg);
00066             }
00067             MESSAGE('I'," Vertical kernel:");
00068             for (i=0; i<size; i++) {
00069                 for (j=k=0,msg[k++]=' '; j<size; j+=1,k=strlen(msg)) {
00070                     sprintf(msg+k,"%12.4e",(double)vert[i*size+j]);
00071                 }
00072                 MESSAGE('I',msg);
00073             }
00074         } else {
00075             MESSAGE('I'," Kernels too large to list.");
00076         }
00077         MESSAGE('I'," ...............");
00078     }
00079 
00080     /* check input */
00081     if (!CHECKIMG(in)) {
00082         MESSAGE('E'," Can't identify image.");
00083         goto the_end;
00084     } else if (size < 2  ||  size%2 == 0) {
00085         MESSAGE('E'," Size of convolution mask must be an odd number greater than two.");
00086         goto the_end;
00087     } else if (size > in->nlin  ||  size > in->npix) {
00088         MESSAGE('E'," Image size must be equal to or greater than convolution mask size.");
00089         goto the_end;
00090     }
00091 
00092     /* create images of appropriate size */
00093     if (!CHECKIMG(*out1)) GETMEM(in->nbnd,in->nlin,in->npix,out1);
00094     if (!*out1) goto the_end;
00095     if (!CHECKIMG(*out2)) GETMEM(in->nbnd,in->nlin,in->npix,out2);
00096     if (!*out2) goto the_end;
00097 
00098     /* initialize progress indicator */
00099     if (LINES  &&  !PROGRESS(psum=0.0)) goto the_end;
00100     pinc = 1.0/(double)in->nbnd/(double)(in->nlin-2*n);
00101     progtotal = in->nbnd * (in->nlin-2*n);
00102     progcount = 0;
00103     progincr = rint((double)progtotal/20.0);
00104 
00105     for (i=0; i<in->nbnd; i++) {
00106 
00107         /* compute convolution */
00108         for (j=n; j<in->nlin-n; j++) {
00109             for (k=n; k<in->npix-n; k++) {
00110                 dv = dh = 0.0;
00111                 for (l=0; l<size; l++) {
00112                     for (m=0; m<size; m++) {
00113                         dv += (double)vert[l*size+m]*(double)in->data[i][j-n+l][k-n+m];
00114                         dh += (double)horz[l*size+m]*(double)in->data[i][j-n+l][k-n+m];
00115                     }
00116                 }
00117                 (*out1)->data[i][j][k] = (PIXEL)sqrt((dv*dv+dh*dh));
00118                 if (dh == 0.0) {
00119                     if (dv > 0.0) {
00120                         (*out2)->data[i][j][k] = (PIXEL)(PI/2.0);
00121                     } else if (dv < 0.0) {
00122                         (*out2)->data[i][j][k] = (PIXEL)(-PI/2.0);
00123                     } else /* (dv == 0.0 ) */ {
00124                         (*out2)->data[i][j][k] = (PIXEL)0.0;
00125                     }
00126                 } else {
00127                     (*out2)->data[i][j][k] = (PIXEL)atan2(dv,dh);
00128                 }
00129             }
00130             if (LINES  &&  !PROGRESS(psum+=pinc)) goto the_end;
00131             if (progmeter) {
00132                     progcount++;
00133                     if ((progcount%progincr) == 0) {
00134                         progress = ((double)progcount/(double)progtotal)*100.0;
00135                         cancel = ProgMeter_Update(progmeter,progress);
00136                         if (cancel != 0) goto the_end;
00137                     }
00138             }
00139         }
00140 
00141         /* fill top and bottom margins */
00142         for (j=0; j<n; j++) {
00143             for (k=n; k<in->npix-n; k++) {
00144                 (*out1)->data[i][j][k]            = (*out1)->data[i][n][k];
00145                 (*out1)->data[i][in->nlin-j-1][k] = (*out1)->data[i][in->nlin-n-1][k];
00146                 (*out2)->data[i][j][k]            = (*out2)->data[i][n][k];
00147                 (*out2)->data[i][in->nlin-j-1][k] = (*out2)->data[i][in->nlin-n-1][k];
00148             }
00149         }
00150 
00151         /* fill left and right margins */
00152         for (j=0; j<in->nlin; j++) {
00153             for (k=0; k<n; k++) {
00154                 (*out1)->data[i][j][k]            = (*out1)->data[i][j][n];
00155                 (*out1)->data[i][j][in->npix-k-1] = (*out1)->data[i][j][in->npix-n-1];
00156                 (*out2)->data[i][j][k]            = (*out2)->data[i][j][n];
00157                 (*out2)->data[i][j][in->npix-k-1] = (*out2)->data[i][j][in->npix-n-1];
00158             }
00159         }
00160     }
00161 
00162     the_end:
00163     if (TIMES) TIMING(T_EXIT);
00164 
00165     if (progmeter) {
00166         ProgMeter_Destroy(progmeter);
00167     }
00168 
00169     if (cancel != 0) {
00170         if (*out1) RELMEM(*out1);
00171         *out1 = NULL;
00172         if (*out2) RELMEM(*out2);
00173         *out2 = NULL;
00174     }
00175 }

Generated on Wed Apr 9 08:56:06 2003 for TREES by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002