📄 canny.c
字号:
/*----------------------------------------------------------------------PROGRAM: canny.cDATE: 11/15/94AUTHOR: Baback Moghaddam, baback@media.mit.edu------------------------------------------------------------------------ This routine reads in an ASCII file of the format filename . . . and applies the canny edge detector to each image in the input directory, the resulting magnitude and thresholded images are written to the specified output directoryies under the same names. Canny code is from the AI-lab ---------------------------------------------------------------------- */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <float.h>#include "util.h"#include "io.h"#include "canny.h" #define MAX_CHARS 256/* ----------- Command-Line Parsing Stuff ------- */extern int optind;extern char *optarg;char *progname; /* used to store the name of the program */char comline[MAX_CHARS]; /* used to store the entire command line */#define OPTIONS "i:l:e:m:s:h:f:n:"char *usage = "\t-i indir -l list -e edge_outdir -m mag_outdir\n\\t\t[-s sigma] [-h high_thresh] [-f thr_factor] [-n iterations]\n\n";char *help="\Canny edge-detection on a set of images\n\n\-i indir \t input directory (containing raw files + descriptor)\n\-l listfile \t ASCII list of files in indir to process (one per line)\n\-e edge_outdir \t output directory for binary edge images\n\-m mag_outdir \t output directory for edge magnitude images\n\-s float \t Canny sigma parameter (default = 1)\n\-h float \t Canny high threshold (0 - 100) (default = 30)\n\-f float \t Canny threshold factor (0 - 1) (default = 0.1)\n\-n int \t Canny grow iterations (default = 30)\n\n";/*----------------------------------------------------------------------*/main(int argc, char **argv){ register int i,j,k,l,ii,jj; int f, c, nframe, nfeatures, sets, bytes_pixel; int nrow, ncol, M, N; char command[MAX_CHARS],indir[MAX_CHARS],listfile[MAX_CHARS], \ infile[MAX_CHARS], filterfile[MAX_CHARS],outdir[MAX_CHARS], \ filename[MAX_CHARS], line[MAX_CHARS], line_outdir[MAX_CHARS], mag_outdir[MAX_CHARS]; float **image_in, **image_out; unsigned char **uchar_image; float fval1, fval2, fval; FILE *fp, *fp2; /* for output values dump */ /* ---- Canny stuff ---- */ float h_threshold; int bytes; int vert_size, horiz_size; float **picture, **xdirection, **ydirection, **hgrm_working_space; char *im, **edges, **w1space, **w2space; /* required input flags */ int errflag = 0; int inflag = 0; int listflag = 0; int outflag = 0; /* command line defaults */ int line_outdir_select = 0; int mag_outdir_select = 0; /* This is the default for smoothing (must be > 0) */ float sigma = CANNY_SIGMA_DEF; /* This is the default for 'growing' (must be >= 0) */ int passes = CANNY_PASSES_DEF; /* This is the default for thresholding (must be 0 < hp < 100) */ float h_percent = CANNY_H_PERC_DEF; /* This is the default for thresholding (must be 0 < tf < 1 */ float thr_factor = CANNY_THR_FACTOR; progname = argv[0]; for (i=0; i<argc; i++) strcat(comline, argv[i]),strcat(comline, " "); /* ---------------------- Command Line Parse ------------------------ */ while ((c = getopt(argc, argv, OPTIONS)) != EOF) switch (c) { case 'i': strcpy(indir, optarg); inflag = 1; break; case 'l': strcpy(listfile, optarg); listflag = 1; break; case 'e': strcpy(line_outdir, optarg); line_outdir_select = outflag = 1; break; case 'm': strcpy(mag_outdir, optarg); mag_outdir_select = outflag = 1; break; case 's': sigma = atof(optarg); break; case 'h': h_percent = atof(optarg); break; case 'f': thr_factor = atof(optarg); break; case 'n': passes = atoi(optarg); break; case '?': errflag = 1; break; } /* command line error check */ if (errflag || !inflag || !outflag || !listflag) { fprintf(stderr,"\nUSAGE: %s %s\n%s\n", progname, usage, help); /*print_documentation(sigma, h_percent, thr_factor, passes);*/ exit(-1); } /* ---- read indir descriptor file -------- */ read_descriptor(indir, &nframe, &sets, &bytes_pixel, &ncol, &nrow); if (sets>1) myerror("Input files must be single-set DAT files!"); if (bytes_pixel>1) myerror("Input files must be unsigned char!"); vert_size = nrow; horiz_size = ncol; /* ---- allocate memory for Canny code data ------*/ picture = (float **) matrix(0, vert_size-1, 0, horiz_size-1); xdirection = (float **) matrix(0, vert_size-1, 0, horiz_size-1); ydirection = (float **) matrix(0, vert_size-1, 0, horiz_size-1); hgrm_working_space = (float **) matrix(0, vert_size-1, 0, horiz_size-1); edges = scmatrix(0, vert_size-1, 0, horiz_size-1); w1space = scmatrix(0, vert_size-1, 0, horiz_size-1); w2space = scmatrix(0, vert_size-1, 0, horiz_size-1); /* ----- allocate memory for my stuff ------- */ image_in = matrix(1, nrow, 1, ncol); image_out = matrix(1, nrow, 1, ncol); uchar_image = cmatrix(1, nrow, 1, ncol); /* ---- loop over input list file and warp ------- */ if ((fp = fopen(listfile, "r")) == NULL) { fprintf(stderr,"ERROR: Could not open input file %s \n\n", listfile); exit(1); } nframe = 0; while (fgets(line, MAX_CHARS, fp)) { if (strncmp(line, "#", 1) != 0 && strlen(line)>1) { nframe++; /* ------- read image ------- */ sscanf(line,"%s",infile); sprintf(filename,"%s/%s", indir, infile); read_RAW(filename, image_in, nrow, ncol); fprintf(stdout,"Read %d-by-%d uchar input image file %s\n", nrow, ncol, filename); convert_1f_to_0f(image_in, picture, vert_size, horiz_size); /* gsmooth smooths an array with a gaussian filter */ gsmooth(picture, sigma, vert_size, horiz_size); /* gradmax takes the smoothed picture and replaces it with the gradient magnitude (a mutation). It also returns the x and y derivatives, and it returns the map of local maximums. */ gradmax(picture, xdirection, ydirection, edges, vert_size, horiz_size); /* find_thres takes the x derivative and y derivative arrays, a histogram percentile value, and an array (as working space) to estimate the high threshold for thresholding */ h_threshold = find_thres(xdirection, ydirection, h_percent, hgrm_working_space,vert_size, horiz_size); /* threshold takes arguments: gradient magnitude array, map of local maximums, a value for high threshold, the number of passes for 'growing', and two arrays for work space. It returns the final edge map in the array of local maximums (a mutation). */ threshold(picture, edges, h_threshold, thr_factor, passes, w1space, w2space, vert_size, horiz_size); /* write edge map and magnitude of gradient at edges */ if (line_outdir_select) { convert_0c_to_1uc(edges, uchar_image, vert_size, horiz_size); sprintf(filename,"%s/%s", line_outdir, infile); write_RAW(filename, uchar_image, vert_size, horiz_size); fprintf(stdout,"Wrote %d-by-%d binary edge output file %s\n", nrow, ncol, filename); } if (mag_outdir_select) { magedges(picture, edges, vert_size, horiz_size); convert_0f_to_1uc(picture, uchar_image, vert_size, horiz_size); sprintf(filename,"%s/%s", mag_outdir, infile); write_RAW(filename, uchar_image, vert_size, horiz_size); fprintf(stdout,"Wrote %d-by-%d edge-magnitude output file %s\n", nrow, ncol, filename); } fprintf(stdout,"\n"); } } /* --- write output descriptor file in outdir ------ */ if (line_outdir_select) write_descriptor(line_outdir, nframe, ncol, nrow, 1, comline); if (mag_outdir_select) write_descriptor(mag_outdir, nframe, ncol, nrow, 1, comline); fclose(fp); /* ---- free Canny memory ---- */ free_matrix(picture, 0, vert_size-1, 0, horiz_size-1); free_matrix(xdirection, 0, vert_size-1, 0, horiz_size-1); free_matrix(ydirection, 0, vert_size-1, 0, horiz_size-1); free_matrix(hgrm_working_space, 0, vert_size-1, 0, horiz_size-1); free_scmatrix(edges, 0, vert_size-1, 0, horiz_size-1); free_scmatrix(w1space, 0, vert_size-1, 0, horiz_size-1); free_scmatrix(w2space, 0, vert_size-1, 0, horiz_size-1); /* --- free my stuff ---- */ free_matrix(image_in, 1, nrow, 1, ncol); free_matrix(image_out, 1, nrow, 1, ncol); free_cmatrix(uchar_image, 1, nrow, 1, ncol); return 0;}/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */void convert_1f_to_0f(float **in, float **out, int nrow, int ncol)/* copies in[1..nrow][1..ncol] to out[0...(nrow-1)][0..(ncol-1)] */{ register int i,j; for (i=1; i<=nrow; i++) for (j=1; j<=ncol; j++) out[i-1][j-1] = in[i][j];}void convert_0c_to_1uc(char **in, unsigned char **out, int nrow, int ncol)/* copies in[0...(nrow-1)][0..(ncol-1)] to out[1..nrow][1..ncol] */{ register int i,j; for (i=0; i<nrow; i++) for (j=0; j<ncol; j++) out[i+1][j+1] = in[i][j];}void convert_0f_to_1uc(float **in, unsigned char **out, int nrow, int ncol)/* copies in[0...(nrow-1)][0..(ncol-1)] to out[1..nrow][1..ncol] */{ register int i,j; for (i=0; i<nrow; i++) for (j=0; j<ncol; j++) out[i+1][j+1] = (unsigned char) in[i][j];}/*===========================================================================*/void print_documentation(float s, float h, float l, int i){ char *message = "\Canedge is a simplified version of an edge detector developed by \\nJohn Canny at MIT's Artificial Intelligence laboratory. The detector\\nfirst smooths an image using a gaussian shaped low pass filter. \\nThen the gradient magnitude of the smoothed image is non-maximum\\nsuppressed in the direction of the gradient. These maxima are then\\nthresholded at a high threshold, and again at a low threshold (which\\nis some fraction of the high threshold). Every maxima above the\\nhigh threshold is an edge. The next step is called edge 'growing'.\\nEvery point above the low threshold (but not above the high threshold)\\nis marked as an edge if it is next to a point above the high threshold.\\nThis process is repeated several times and thus, the edges are\\n'grown'.\n"; printf("\nusage: canedge [-s float] [-h float] [-l float] [-i int] in_im line_im mag_im\n\n"); printf("-s float : smoothing sigma\n"); printf(" Default: %f\n",s); printf("-h float : high threshold\n"); printf(" Default: %f\n",h); printf("-l float : low threshold\n"); printf(" Default: %f\n",l); printf("-i int : growing iterations\n"); printf(" Default: %d\n",i); printf("\n%s\n",message);}/*===========================================================================*/void parse_options(int argc, char *argv[], float *s, float *h, float *l, int *i, char *indir, char *line_outdir, char *mag_outdir){ int errflag = 0; int fileloc = 0; char c; while ((c = getopt(argc, argv, OPTIONS)) != EOF) switch (c) { case 's': *s = atof(optarg); fileloc += 2; break; case 'l': *l = atof(optarg); fileloc += 2; break; case 'i': *i = atoi(optarg); fileloc += 2; break; case '?': errflag = 1; break; } if (argc != fileloc + 4) { print_documentation(*s, *h, *l, *i); exit(-1); } fprintf(stderr,"%d s %s \n", fileloc, argv[fileloc+1]); strcpy(indir, argv[fileloc+1]); strcpy(line_outdir, argv[fileloc+2]); strcpy(mag_outdir, argv[fileloc+3]);}/*===========================================================================*//* These functions are part of my first version of a float gaussian smoother. The include file sizes.h contains size information. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -