/******************************************************************************* * FILE: hysteresis.c * This code was re-written by Mike Heath from original code obtained indirectly * from Michigan State University. heath@csee.usf.edu (Re-written in 1996). *******************************************************************************/ #include #include #define VERBOSE 0 #define NOEDGE 255 #define POSSIBLE_EDGE 128 #define EDGE 0 /******************************************************************************* * PROCEDURE: follow_edges * PURPOSE: This procedure edges is a recursive routine that traces edgs along * all paths whose magnitude values remain above some specifyable lower * threshhold. * NAME: Mike Heath * DATE: 2/15/96 *******************************************************************************/ follow_edges(unsigned char *edgemapptr, short *edgemagptr, short lowval, int cols) { short *tempmagptr; unsigned char *tempmapptr; int i; float thethresh; int x[8] = {1,1,0,-1,-1,-1,0,1}, y[8] = {0,1,1,1,0,-1,-1,-1}; for(i=0;i<8;i++){ tempmapptr = edgemapptr - y[i]*cols + x[i]; tempmagptr = edgemagptr - y[i]*cols + x[i]; if((*tempmapptr == POSSIBLE_EDGE) && (*tempmagptr > lowval)){ *tempmapptr = (unsigned char) EDGE; follow_edges(tempmapptr,tempmagptr, lowval, cols); } } } /******************************************************************************* * PROCEDURE: apply_hysteresis * PURPOSE: This routine finds edges that are above some high threshhold or * are connected to a high pixel by a path of pixels greater than a low * threshold. * NAME: Mike Heath * DATE: 2/15/96 *******************************************************************************/ void apply_hysteresis(short int *mag, unsigned char *nms, int rows, int cols, float tlow, float thigh, unsigned char *edge) { int r, c, pos, numedges, lowcount, highcount, lowthreshold, highthreshold, i, hist[32768], rr, cc; short int maximum_mag, sumpix; /**************************************************************************** * Initialize the edge map to possible edges everywhere the non-maximal * suppression suggested there could be an edge except for the border. At * the border we say there can not be an edge because it makes the * follow_edges algorithm more efficient to not worry about tracking an * edge off the side of the image. ****************************************************************************/ for(r=0,pos=0;r= highthreshold)){ edge[pos] = EDGE; follow_edges((edge+pos), (mag+pos), lowthreshold, cols); } } } /**************************************************************************** * Set all the remaining possible edges to non-edges. ****************************************************************************/ for(r=0,pos=0;r= 0){ if(gy >= 0){ if (gx >= gy) { /* 111 */ /* Left point */ z1 = *(magptr - 1); z2 = *(magptr - ncols - 1); mag1 = (m00 - z1)*xperp + (z2 - z1)*yperp; /* Right point */ z1 = *(magptr + 1); z2 = *(magptr + ncols + 1); mag2 = (m00 - z1)*xperp + (z2 - z1)*yperp; } else { /* 110 */ /* Left point */ z1 = *(magptr - ncols); z2 = *(magptr - ncols - 1); mag1 = (z1 - z2)*xperp + (z1 - m00)*yperp; /* Right point */ z1 = *(magptr + ncols); z2 = *(magptr + ncols + 1); mag2 = (z1 - z2)*xperp + (z1 - m00)*yperp; } } else { if (gx >= -gy) { /* 101 */ /* Left point */ z1 = *(magptr - 1); z2 = *(magptr + ncols - 1); mag1 = (m00 - z1)*xperp + (z1 - z2)*yperp; /* Right point */ z1 = *(magptr + 1); z2 = *(magptr - ncols + 1); mag2 = (m00 - z1)*xperp + (z1 - z2)*yperp; } else { /* 100 */ /* Left point */ z1 = *(magptr + ncols); z2 = *(magptr + ncols - 1); mag1 = (z1 - z2)*xperp + (m00 - z1)*yperp; /* Right point */ z1 = *(magptr - ncols); z2 = *(magptr - ncols + 1); mag2 = (z1 - z2)*xperp + (m00 - z1)*yperp; } } } else { if ((gy = *gyptr) >= 0) { if (-gx >= gy) { /* 011 */ /* Left point */ z1 = *(magptr + 1); z2 = *(magptr - ncols + 1); mag1 = (z1 - m00)*xperp + (z2 - z1)*yperp; /* Right point */ z1 = *(magptr - 1); z2 = *(magptr + ncols - 1); mag2 = (z1 - m00)*xperp + (z2 - z1)*yperp; } else { /* 010 */ /* Left point */ z1 = *(magptr - ncols); z2 = *(magptr - ncols + 1); mag1 = (z2 - z1)*xperp + (z1 - m00)*yperp; /* Right point */ z1 = *(magptr + ncols); z2 = *(magptr + ncols - 1); mag2 = (z2 - z1)*xperp + (z1 - m00)*yperp; } } else { if (-gx > -gy) { /* 001 */ /* Left point */ z1 = *(magptr + 1); z2 = *(magptr + ncols + 1); mag1 = (z1 - m00)*xperp + (z1 - z2)*yperp; /* Right point */ z1 = *(magptr - 1); z2 = *(magptr - ncols - 1); mag2 = (z1 - m00)*xperp + (z1 - z2)*yperp; } else { /* 000 */ /* Left point */ z1 = *(magptr + ncols); z2 = *(magptr + ncols + 1); mag1 = (z2 - z1)*xperp + (m00 - z1)*yperp; /* Right point */ z1 = *(magptr - ncols); z2 = *(magptr - ncols - 1); mag2 = (z2 - z1)*xperp + (m00 - z1)*yperp; } } } /* Now determine if the current point is a maximum point */ if ((mag1 > 0.0) || (mag2 > 0.0)) { *resultptr = (unsigned char) NOEDGE; } else { if (mag2 == 0.0) *resultptr = (unsigned char) NOEDGE; else *resultptr = (unsigned char) POSSIBLE_EDGE; } } } }