#include #include #define MAX #include "array.h" /* Scale floating point magnitudes and angles to 8 bits */ #define ORI_SCALE 40.0 #define MAG_SCALE 20.0 /* Biggest possible filter mask */ #define MAX_MASK_SIZE 20 /* Fraction of pixels that should be above the HIGH threshold */ float ratio = 0.1; int WIDTH = 0; typedef uc2D IMAGE; int trace (int i, int j, int low, IMAGE& im,IMAGE& mag, IMAGE& ori); float gauss(float x, float sigma); float dGauss (float x, float sigma); float meanGauss (float x, float sigma); void hysteresis (int high, int low, IMAGE& im, IMAGE& mag, IMAGE& oriim); void canny (float s, IMAGE& im, IMAGE& mag, IMAGE& ori); void seperable_convolution (IMAGE& im, float *gau, int width, f2D& smx, f2D& smy); void dxy_seperable_convolution (f2D& im, int nr, int nc, float *gau, int width, f2D& sm, int which); void nonmax_suppress (f2D& dx, f2D& dy, int nr, int nc, IMAGE& mag, IMAGE& ori); void estimate_thresh (IMAGE& mag, int *low, int *hi); int range (IMAGE& im, int i, int j); float norm (float x, float y) { return (float) sqrt ( (double)(x*x + y*y) ); } void canny (float s, IMAGE& im, IMAGE& mag, IMAGE& ori) { int width; f2D smx, smy, dx, dy; int i,j,k,n; float gau[MAX_MASK_SIZE], dgau[MAX_MASK_SIZE], z; /* Create a Gaussian and a derivative of Gaussian filter mask */ for(i=0; i= high) trace (i, j, low, im, mag, oriim); /* Make the edge black (to be the same as the other methods) */ for (i=0; i the low edge threshold, continuing from the pixel at (i,j). */ int trace (int i, int j, int low, IMAGE& im,IMAGE& mag, IMAGE& ori) { int n,m; char flag = 0; if (im.m[i][j] == 0) { im.m[i][j] = 255; flag=0; for (n= -1; n<=1; n++) { for(m= -1; m<=1; m++) { if (i==0 && m==0) continue; if (range(mag, i+n, j+m) && mag.m[i+n][j+m] >= low) if (trace(i+n, j+m, low, im, mag, ori)) { flag=1; break; } } if (flag) break; } return(1); } return(0); } void seperable_convolution (IMAGE& im, float *gau, int width, f2D& smx, f2D& smy) { int i,j,k, I1, I2, nr, nc; float x, y; nr = im.nr; nc = im.nc; for (i=0; i fabs(xc)) { /* The Y component is biggest, so gradient direction is basically UP/DOWN */ xx = fabs(xc)/fabs(yc); yy = 1.0; g2 = norm (dx.m[i-1][j], dy.m[i-1][j]); g4 = norm (dx.m[i+1][j], dy.m[i+1][j]); if (xc*yc > 0.0) { g3 = norm (dx.m[i+1][j+1], dy.m[i+1][j+1]); g1 = norm (dx.m[i-1][j-1], dy.m[i-1][j-1]); } else { g3 = norm (dx.m[i+1][j-1], dy.m[i+1][j-1]); g1 = norm (dx.m[i-1][j+1], dy.m[i-1][j+1]); } } else { /* The X component is biggest, so gradient direction is basically LEFT/RIGHT */ xx = fabs(yc)/fabs(xc); yy = 1.0; g2 = norm (dx.m[i][j+1], dy.m[i][j+1]); g4 = norm (dx.m[i][j-1], dy.m[i][j-1]); if (xc*yc > 0.0) { g3 = norm (dx.m[i-1][j-1], dy.m[i-1][j-1]); g1 = norm (dx.m[i+1][j+1], dy.m[i+1][j+1]); } else { g1 = norm (dx.m[i-1][j+1], dy.m[i-1][j+1]); g3 = norm (dx.m[i+1][j-1], dy.m[i+1][j-1]); } } /* Compute the interpolated value of the gradient magnitude */ if ( (g > (xx*g1 + (yy-xx)*g2)) && (g > (xx*g3 + (yy-xx)*g4)) ) { if (g*MAG_SCALE <= 255) mag.m[i][j] = (unsigned char)(g*MAG_SCALE); else mag.m[i][j] = 255; ori.m[i][j] = atan2 (yc, xc) * ORI_SCALE; } else { mag.m[i][j] = 0; ori.m[i][j] = 0; } } } } void estimate_thresh (IMAGE& mag, int *hi, int *low) { int i,j,k, hist[256], count; /* Build a histogram of the magnitude image. */ for (k=0; k<256; k++) hist[k] = 0; for (i=WIDTH; i 80 or 90% of the pixels j = (int)(ratio*mag.nr*mag.nc); */ j = mag.nr; if (j=im.nr)) return 0; if ((j<0) || (j>=im.nc)) return 0; return 1; } // Test function for canny edge detection void CannyEdgeDetection() { int i,j,k,n; IMAGE im, magim, oriim; cout<<"CANNY: Apply the Canny edge detector to an image.\n"; // 3 adjustable parameters : Lower threshold(low), High threshold(high), Gaussian standard deviation(sigma) // (1) Defaut value for Lower threshold, High threshold, Gaussian standard deviation // float s=1.0; // int low= 0,high=-1; // Test for changing threshold low=50; high=-5; sigma=1.0; // Read the image from file ifstream in1("R_edge.raw",ios::binary); im.Initialize(919,1687); for(int i=0;iim.nr-1-WIDTH; i--) for (j=0; j>key; }