/* Author: Jonathan Hardy file: canny.cc This file reads in a PGM image file and processes it with the Canny edge detector algorithm. The processed image is then written out to a new PGM image file with "_cnny" appended to the original filename. The arguments are as follows: canny */ #include #include #include #include FILE *ptr; // Image File FILE *cnnyptr; // Output File void main(int argc, char**argv) { char fname[13]; // Image filename char cnnyname[18]; // Output filename char width[4], height[4], numcol[4]; // Image information char Type[3]; // Image type (P5) int n, r, c, data; // Counters and image data variable char temp[100]; // Variable for input comment lines char comment[] = "# New pgm file.\n"; const int ulimit = atoi(argv[2]); // Get upper threshold const int llimit = atoi(argv[3]); // Get lower threshold int filter_width = atoi(argv[4]); // Get filter width float sigma = atoi(argv[5]); // Get sigma /* The following section reads the image file */ strcpy(fname, argv[1]); // Get filename from command line strcat(fname, ".pgm"); // Append filename with ".pgm" ptr = fopen(fname, "rb"); // Open image file fread(&Type, 3, 1, ptr); // Get image type fread(&width, 4, 1, ptr); // If no comment lines, get width while (width[0] == '#'){ // Otherwise, ignore comment lines fgets(temp, 100, ptr); // and get width fread(&width, 4, 1, ptr); } fread(&height, 4, 1, ptr); // Get height const int WIDTH = atoi(width); const int HEIGHT = atoi(height); int ImgArray[HEIGHT][WIDTH]; // Create image array fread(&numcol, 4, 1, ptr); // Get number of colors (255) for (r = 0; r < HEIGHT; r++){ // Get image data and threshold it for (c = 0; c < WIDTH; c++){ data = fgetc(ptr); if ((data < llimit) || (data > ulimit)) ImgArray[r][c] = 0; else ImgArray[r][c] = data; } } fclose(ptr); // Close image file /* The following iteration scans the image array and performs the Canny algorithm on the data. It calculates the magnitude response by taking the square root of the sum of the squares of the dx and dy responses. */ float SmoothX[HEIGHT][WIDTH]; // Array for x-smoothed image float SmoothY[HEIGHT][WIDTH]; // Array for y-smoothed image float DiffX[HEIGHT][WIDTH]; // Array for x-differentiated image double t1, t2, ux, uy; // Temp variables double atmp, btmp, ctmp, dtmp, g0; double gc, gn, gs, gw, ge, gne, gse, gsw, gnw; /* Arrays for the Gaussian and its derivatives */ double G[filter_width], dG[filter_width], D2G[filter_width]; /* This section calculates the values of the Gaussian and its derivatives based on the filter width and sigma provided in the command line */ for (n=0; n0.005 || n<2){ btmp = exp((-((double)n-0.5)*((double)n-0.5)) / (2*sigma*sigma)); ctmp = exp((-((double)n+0.5)*((double)n+0.5)) / (2*sigma*sigma)); dtmp = exp((-n*n)/(0.5*sigma*sigma)); G[n] = (atmp+btmp+ctmp)/3/(6.283185*sigma*sigma); dG[n] = ctmp - btmp; D2G[n] = 1.6*dtmp - atmp; } else break; } filter_width = n; /* Set limits to avoid the image edges */ int climit = WIDTH - (filter_width-1); int rlimit = HEIGHT - (filter_width-1); /* This section performs the Gaussian smoothing */ for (c=filter_width-1; c0){ if (fabs(ux)