hysteresis.C

Go to the documentation of this file.
00001 /*! @file BeoSub/hysteresis.C [put description here] */
00002 
00003 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/hysteresis.C $
00004 // $Id: hysteresis.C 6182 2006-01-31 18:41:41Z rjpeters $
00005 
00006 /*******************************************************************************
00007 * FILE: hysteresis.c
00008 * This code was re-written by Mike Heath from original code obtained indirectly
00009 * from Michigan State University. heath@csee.usf.edu (Re-written in 1996).
00010 *******************************************************************************/
00011 
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 
00015 #define VERBOSE 0
00016 
00017 #define NOEDGE 0
00018 #define POSSIBLE_EDGE 128
00019 #define EDGE 255
00020 
00021 /*******************************************************************************
00022 * PROCEDURE: follow_edges
00023 * PURPOSE: This procedure edges is a recursive routine that traces edgs along
00024 * all paths whose magnitude values remain above some specifyable lower
00025 * threshhold.
00026 * NAME: Mike Heath
00027 * DATE: 2/15/96
00028 *******************************************************************************/
00029 int follow_edges(unsigned char *edgemapptr, short *edgemagptr, short lowval,
00030    int cols)
00031 {
00032    short *tempmagptr;
00033    unsigned char *tempmapptr;
00034    int i;
00035    int x[8] = {1,1,0,-1,-1,-1,0,1},
00036        y[8] = {0,1,1,1,0,-1,-1,-1};
00037 
00038    //derecursify this! and then collect statistics to recognize rectangles etc... similar to graph traversal with MSTs
00039    for(i=0;i<8;i++){
00040       tempmapptr = edgemapptr - y[i]*cols + x[i];
00041       tempmagptr = edgemagptr - y[i]*cols + x[i];
00042 
00043       if((*tempmapptr == POSSIBLE_EDGE) && (*tempmagptr > lowval)){
00044          *tempmapptr = (unsigned char) EDGE;
00045          follow_edges(tempmapptr,tempmagptr, lowval, cols);
00046       }
00047    }
00048 
00049    return 0;
00050 }
00051 
00052 /*******************************************************************************
00053 * PROCEDURE: apply_hysteresis
00054 * PURPOSE: This routine finds edges that are above some high threshhold or
00055 * are connected to a high pixel by a path of pixels greater than a low
00056 * threshold.
00057 * NAME: Mike Heath
00058 * DATE: 2/15/96
00059 *******************************************************************************/
00060 int apply_hysteresis(short int *mag, unsigned char *nms, int rows, int cols,
00061         float tlow, float thigh, unsigned char *edge)
00062 {
00063    int r, c, pos, numedges, highcount, lowthreshold, highthreshold,
00064        hist[32768];
00065    short int maximum_mag = 0        ;
00066 
00067    /****************************************************************************
00068    * Initialize the edge map to possible edges everywhere the non-maximal
00069    * suppression suggested there could be an edge except for the border. At
00070    * the border we say there can not be an edge because it makes the
00071    * follow_edges algorithm more efficient to not worry about tracking an
00072    * edge off the side of the image.
00073    ****************************************************************************/
00074    for(r=0,pos=0;r<rows;r++){
00075       for(c=0;c<cols;c++,pos++){
00076          if(nms[pos] == POSSIBLE_EDGE) edge[pos] = POSSIBLE_EDGE;
00077          else edge[pos] = NOEDGE;
00078       }
00079    }
00080 
00081    for(r=0,pos=0;r<rows;r++,pos+=cols){
00082       edge[pos] = NOEDGE;
00083       edge[pos+cols-1] = NOEDGE;
00084    }
00085    pos = (rows-1) * cols;
00086    for(c=0;c<cols;c++,pos++){
00087       edge[c] = NOEDGE;
00088       edge[pos] = NOEDGE;
00089    }
00090 
00091    /****************************************************************************
00092    * Compute the histogram of the magnitude image. Then use the histogram to
00093    * compute hysteresis thresholds.
00094    ****************************************************************************/
00095    for(r=0;r<32768;r++) hist[r] = 0;
00096    for(r=0,pos=0;r<rows;r++){
00097       for(c=0;c<cols;c++,pos++){
00098          if(edge[pos] == POSSIBLE_EDGE) hist[mag[pos]]++;
00099       }
00100    }
00101 
00102    /****************************************************************************
00103    * Compute the number of pixels that passed the nonmaximal suppression.
00104    ****************************************************************************/
00105    for(r=1,numedges=0;r<32768;r++){
00106       if(hist[r] != 0) maximum_mag = r;
00107       numedges += hist[r];
00108    }
00109 
00110    highcount = (int)(numedges * thigh + 0.5);
00111 
00112    /****************************************************************************
00113    * Compute the high threshold value as the (100 * thigh) percentage point
00114    * in the magnitude of the gradient histogram of all the pixels that passes
00115    * non-maximal suppression. Then calculate the low threshold as a fraction
00116    * of the computed high threshold value. John Canny said in his paper
00117    * "A Computational Approach to Edge Detection" that "The ratio of the
00118    * high to low threshold in the implementation is in the range two or three
00119    * to one." That means that in terms of this implementation, we should
00120    * choose tlow ~= 0.5 or 0.33333.
00121    ****************************************************************************/
00122    r = 1;
00123    numedges = hist[1];
00124    while((r<(maximum_mag-1)) && (numedges < highcount)){
00125       r++;
00126       numedges += hist[r];
00127    }
00128    highthreshold = r;
00129    lowthreshold = (int)(highthreshold * tlow + 0.5);
00130 
00131    if(VERBOSE){
00132       printf("The input low and high fractions of %f and %f computed to\n",
00133          tlow, thigh);
00134       printf("magnitude of the gradient threshold values of: %d %d\n",
00135          lowthreshold, highthreshold);
00136    }
00137 
00138    /****************************************************************************
00139    * This loop looks for pixels above the highthreshold to locate edges and
00140    * then calls follow_edges to continue the edge.
00141    ****************************************************************************/
00142    for(r=0,pos=0;r<rows;r++){
00143       for(c=0;c<cols;c++,pos++){
00144          if((edge[pos] == POSSIBLE_EDGE) && (mag[pos] >= highthreshold)){
00145             edge[pos] = EDGE;
00146             follow_edges((edge+pos), (mag+pos), lowthreshold, cols);
00147          }
00148       }
00149    }
00150 
00151    /****************************************************************************
00152    * Set all the remaining possible edges to non-edges and calculate the centroid.
00153    ****************************************************************************/
00154    int centroid  = 0;
00155    int numEdgePts = 0;
00156    for(r=0,pos=0;r<rows;r++){
00157       for(c=0;c<cols;c++,pos++)
00158               if(edge[pos] != EDGE) edge[pos] = NOEDGE;
00159         else {
00160                 centroid += pos;
00161                 numEdgePts++;
00162         }
00163    }
00164    if(numEdgePts != 0){
00165      centroid = centroid/numEdgePts;
00166    }
00167    else{
00168      centroid = 0;
00169    }
00170    return centroid;
00171 }
00172 
00173 /*******************************************************************************
00174 * PROCEDURE: non_max_supp
00175 * PURPOSE: This routine applies non-maximal suppression to the magnitude of
00176 * the gradient image.
00177 * NAME: Mike Heath
00178 * DATE: 2/15/96
00179 *******************************************************************************/
00180 void non_max_supp(short *mag, short *gradx, short *grady, int nrows, int ncols,
00181     unsigned char *result)
00182 {
00183     int rowcount, colcount,count;
00184     short *magrowptr,*magptr;
00185     short *gxrowptr,*gxptr;
00186     short *gyrowptr,*gyptr,z1,z2;
00187     short m00,gx=0,gy=0;
00188     float mag1,mag2,xperp=0.0f,yperp=0.0f;
00189     unsigned char *resultrowptr, *resultptr;
00190 
00191 
00192    /****************************************************************************
00193    * Zero the edges of the result image.
00194    ****************************************************************************/
00195     for(count=0,resultrowptr=result,resultptr=result+ncols*(nrows-1);
00196         count<ncols; resultptr++,resultrowptr++,count++){
00197         *resultrowptr = *resultptr = (unsigned char) 0;
00198     }
00199 
00200     for(count=0,resultptr=result,resultrowptr=result+ncols-1;
00201         count<nrows; count++,resultptr+=ncols,resultrowptr+=ncols){
00202         *resultptr = *resultrowptr = (unsigned char) 0;
00203     }
00204 
00205    /****************************************************************************
00206    * Suppress non-maximum points.
00207    ****************************************************************************/
00208    for(rowcount=1,magrowptr=mag+ncols+1,gxrowptr=gradx+ncols+1,
00209       gyrowptr=grady+ncols+1,resultrowptr=result+ncols+1;
00210       rowcount<nrows-2;
00211       rowcount++,magrowptr+=ncols,gyrowptr+=ncols,gxrowptr+=ncols,
00212       resultrowptr+=ncols){
00213       for(colcount=1,magptr=magrowptr,gxptr=gxrowptr,gyptr=gyrowptr,
00214          resultptr=resultrowptr;colcount<ncols-2;
00215          colcount++,magptr++,gxptr++,gyptr++,resultptr++){
00216          m00 = *magptr;
00217          if(m00 == 0){
00218             *resultptr = (unsigned char) NOEDGE;
00219          }
00220          else{
00221             xperp = -(gx = *gxptr)/((float)m00);
00222             yperp = (gy = *gyptr)/((float)m00);
00223          }
00224 
00225          if(gx >= 0){
00226             if(gy >= 0){
00227                     if (gx >= gy)
00228                     {
00229                         /* 111 */
00230                         /* Left point */
00231                         z1 = *(magptr - 1);
00232                         z2 = *(magptr - ncols - 1);
00233 
00234                         mag1 = (m00 - z1)*xperp + (z2 - z1)*yperp;
00235 
00236                         /* Right point */
00237                         z1 = *(magptr + 1);
00238                         z2 = *(magptr + ncols + 1);
00239 
00240                         mag2 = (m00 - z1)*xperp + (z2 - z1)*yperp;
00241                     }
00242                     else
00243                     {
00244                         /* 110 */
00245                         /* Left point */
00246                         z1 = *(magptr - ncols);
00247                         z2 = *(magptr - ncols - 1);
00248 
00249                         mag1 = (z1 - z2)*xperp + (z1 - m00)*yperp;
00250 
00251                         /* Right point */
00252                         z1 = *(magptr + ncols);
00253                         z2 = *(magptr + ncols + 1);
00254 
00255                         mag2 = (z1 - z2)*xperp + (z1 - m00)*yperp;
00256                     }
00257                 }
00258                 else
00259                 {
00260                     if (gx >= -gy)
00261                     {
00262                         /* 101 */
00263                         /* Left point */
00264                         z1 = *(magptr - 1);
00265                         z2 = *(magptr + ncols - 1);
00266 
00267                         mag1 = (m00 - z1)*xperp + (z1 - z2)*yperp;
00268 
00269                         /* Right point */
00270                         z1 = *(magptr + 1);
00271                         z2 = *(magptr - ncols + 1);
00272 
00273                         mag2 = (m00 - z1)*xperp + (z1 - z2)*yperp;
00274                     }
00275                     else
00276                     {
00277                         /* 100 */
00278                         /* Left point */
00279                         z1 = *(magptr + ncols);
00280                         z2 = *(magptr + ncols - 1);
00281 
00282                         mag1 = (z1 - z2)*xperp + (m00 - z1)*yperp;
00283 
00284                         /* Right point */
00285                         z1 = *(magptr - ncols);
00286                         z2 = *(magptr - ncols + 1);
00287 
00288                         mag2 = (z1 - z2)*xperp  + (m00 - z1)*yperp;
00289                     }
00290                 }
00291             }
00292             else
00293             {
00294                 if ((gy = *gyptr) >= 0)
00295                 {
00296                     if (-gx >= gy)
00297                     {
00298                         /* 011 */
00299                         /* Left point */
00300                         z1 = *(magptr + 1);
00301                         z2 = *(magptr - ncols + 1);
00302 
00303                         mag1 = (z1 - m00)*xperp + (z2 - z1)*yperp;
00304 
00305                         /* Right point */
00306                         z1 = *(magptr - 1);
00307                         z2 = *(magptr + ncols - 1);
00308 
00309                         mag2 = (z1 - m00)*xperp + (z2 - z1)*yperp;
00310                     }
00311                     else
00312                     {
00313                         /* 010 */
00314                         /* Left point */
00315                         z1 = *(magptr - ncols);
00316                         z2 = *(magptr - ncols + 1);
00317 
00318                         mag1 = (z2 - z1)*xperp + (z1 - m00)*yperp;
00319 
00320                         /* Right point */
00321                         z1 = *(magptr + ncols);
00322                         z2 = *(magptr + ncols - 1);
00323 
00324                         mag2 = (z2 - z1)*xperp + (z1 - m00)*yperp;
00325                     }
00326                 }
00327                 else
00328                 {
00329                     if (-gx > -gy)
00330                     {
00331                         /* 001 */
00332                         /* Left point */
00333                         z1 = *(magptr + 1);
00334                         z2 = *(magptr + ncols + 1);
00335 
00336                         mag1 = (z1 - m00)*xperp + (z1 - z2)*yperp;
00337 
00338                         /* Right point */
00339                         z1 = *(magptr - 1);
00340                         z2 = *(magptr - ncols - 1);
00341 
00342                         mag2 = (z1 - m00)*xperp + (z1 - z2)*yperp;
00343                     }
00344                     else
00345                     {
00346                         /* 000 */
00347                         /* Left point */
00348                         z1 = *(magptr + ncols);
00349                         z2 = *(magptr + ncols + 1);
00350 
00351                         mag1 = (z2 - z1)*xperp + (m00 - z1)*yperp;
00352 
00353                         /* Right point */
00354                         z1 = *(magptr - ncols);
00355                         z2 = *(magptr - ncols - 1);
00356 
00357                         mag2 = (z2 - z1)*xperp + (m00 - z1)*yperp;
00358                     }
00359                 }
00360             }
00361 
00362             /* Now determine if the current point is a maximum point */
00363 
00364             if ((mag1 > 0.0) || (mag2 > 0.0))
00365             {
00366                 *resultptr = (unsigned char) NOEDGE;
00367             }
00368             else
00369             {
00370                 if (mag2 == 0.0)
00371                     *resultptr = (unsigned char) NOEDGE;
00372                 else
00373                     *resultptr = (unsigned char) POSSIBLE_EDGE;
00374             }
00375         }
00376     }
00377 }
Generated on Sun May 8 08:40:20 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3