📄 canny_src.txt
字号:
"Canny" edge detector code:
---------------------------
This text file contains the source code for a "Canny" edge detector. It
was written by Mike Heath (heath@csee.usf.edu) using some pieces of a
Canny edge detector originally written by someone at Michigan State
University.
There are three 'C' source code files in this text file. They are named
"canny_edge.c", "hysteresis.c" and "pgm_io.c". They were written and compiled
under SunOS 4.1.3. Since then they have also been compiled under Solaris.
To make an executable program: (1) Separate this file into three files with
the previously specified names, and then (2) compile the code using
gcc -o canny_edge canny_edge.c hysteresis.c pgm_io.c -lm
(Note: You can also use optimization such as -O3)
The resulting program, canny_edge, will process images in the PGM format.
Parameter selection is left up to the user. A broad range of parameters to
use as a starting point are: sigma 0.60-2.40, tlow 0.20-0.50 and,
thigh 0.60-0.90.
If you are using a Unix system, PGM file format conversion tools can be found
at ftp://wuarchive.wustl.edu/graphics/graphics/packages/pbmplus/.
Otherwise, it would be easy for anyone to rewrite the image I/O procedures
because they are listed in the separate file pgm_io.c.
If you want to check your compiled code, you can download grey-scale and edge
images from http://marathon.csee.usf.edu/edge/edge_detection.html. You can use
the parameters given in the edge filenames and check whether the edges that
are output from your program match the edge images posted at that address.
Mike Heath
(10/29/96)
<------------------------- begin canny_edge.c ------------------------->
/*******************************************************************************
* --------------------------------------------
*(c) 2001 University of South Florida, Tampa
* Use, or copying without permission prohibited.
* PERMISSION TO USE
* In transmitting this software, permission to use for research and
* educational purposes is hereby granted. This software may be copied for
* archival and backup purposes only. This software may not be transmitted
* to a third party without prior permission of the copyright holder. This
* permission may be granted only by Mike Heath or Prof. Sudeep Sarkar of
* University of South Florida (sarkar@csee.usf.edu). Acknowledgment as
* appropriate is respectfully requested.
*
* Heath, M., Sarkar, S., Sanocki, T., and Bowyer, K. Comparison of edge
* detectors: a methodology and initial study, Computer Vision and Image
* Understanding 69 (1), 38-54, January 1998.
* Heath, M., Sarkar, S., Sanocki, T. and Bowyer, K.W. A Robust Visual
* Method for Assessing the Relative Performance of Edge Detection
* Algorithms, IEEE Transactions on Pattern Analysis and Machine
* Intelligence 19 (12), 1338-1359, December 1997.
* ------------------------------------------------------
*
* PROGRAM: canny_edge
* PURPOSE: This program implements a "Canny" edge detector. The processing
* steps are as follows:
*
* 1) Convolve the image with a separable gaussian filter.
* 2) Take the dx and dy the first derivatives using [-1,0,1] and [1,0,-1]'.
* 3) Compute the magnitude: sqrt(dx*dx+dy*dy).
* 4) Perform non-maximal suppression.
* 5) Perform hysteresis.
*
* The user must input three parameters. These are as follows:
*
* sigma = The standard deviation of the gaussian smoothing filter.
* tlow = Specifies the low value to use in hysteresis. This is a
* fraction (0-1) of the computed high threshold edge strength value.
* thigh = Specifies the high value to use in hysteresis. This fraction (0-1)
* specifies the percentage point in a histogram of the gradient of
* the magnitude. Magnitude values of zero are not counted in the
* histogram.
*
* NAME: Mike Heath
* Computer Vision Laboratory
* University of South Floeida
* heath@csee.usf.edu
*
* DATE: 2/15/96
*
* Modified: 5/17/96 - To write out a floating point RAW headerless file of
* the edge gradient "up the edge" where the angle is
* defined in radians counterclockwise from the x direction.
* (Mike Heath)
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define VERBOSE 0
#define BOOSTBLURFACTOR 90.0
int read_pgm_image(char *infilename, unsigned char **image, int *rows,
int *cols);
int write_pgm_image(char *outfilename, unsigned char *image, int rows,
int cols, char *comment, int maxval);
void canny(unsigned char *image, int rows, int cols, float sigma,
float tlow, float thigh, unsigned char **edge, char *fname);
void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
short int **smoothedim);
void make_gaussian_kernel(float sigma, float **kernel, int *windowsize);
void derrivative_x_y(short int *smoothedim, int rows, int cols,
short int **delta_x, short int **delta_y);
void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
short int **magnitude);
void apply_hysteresis(short int *mag, unsigned char *nms, int rows, int cols,
float tlow, float thigh, unsigned char *edge);
void radian_direction(short int *delta_x, short int *delta_y, int rows,
int cols, float **dir_radians, int xdirtag, int ydirtag);
double angle_radians(double x, double y);
main(int argc, char *argv[])
{
char *infilename = NULL; /* Name of the input image */
char *dirfilename = NULL; /* Name of the output gradient direction image */
char outfilename[128]; /* Name of the output "edge" image */
char composedfname[128]; /* Name of the output "direction" image */
unsigned char *image; /* The input image */
unsigned char *edge; /* The output edge image */
int rows, cols; /* The dimensions of the image. */
float sigma, /* Standard deviation of the gaussian kernel. */
tlow, /* Fraction of the high threshold in hysteresis. */
thigh; /* High hysteresis threshold control. The actual
threshold is the (100 * thigh) percentage point
in the histogram of the magnitude of the
gradient image that passes non-maximal
suppression. */
/****************************************************************************
* Get the command line arguments.
****************************************************************************/
if(argc < 5){
fprintf(stderr,"\n<USAGE> %s image sigma tlow thigh [writedirim]\n",argv[0]);
fprintf(stderr,"\n image: An image to process. Must be in ");
fprintf(stderr,"PGM format.\n");
fprintf(stderr," sigma: Standard deviation of the gaussian");
fprintf(stderr," blur kernel.\n");
fprintf(stderr," tlow: Fraction (0.0-1.0) of the high ");
fprintf(stderr,"edge strength threshold.\n");
fprintf(stderr," thigh: Fraction (0.0-1.0) of the distribution");
fprintf(stderr," of non-zero edge\n strengths for ");
fprintf(stderr,"hysteresis. The fraction is used to compute\n");
fprintf(stderr," the high edge strength threshold.\n");
fprintf(stderr," writedirim: Optional argument to output ");
fprintf(stderr,"a floating point");
fprintf(stderr," direction image.\n\n");
exit(1);
}
infilename = argv[1];
sigma = atof(argv[2]);
tlow = atof(argv[3]);
thigh = atof(argv[4]);
if(argc == 6) dirfilename = infilename;
else dirfilename = NULL;
/****************************************************************************
* Read in the image. This read function allocates memory for the image.
****************************************************************************/
if(VERBOSE) printf("Reading the image %s.\n", infilename);
if(read_pgm_image(infilename, &image, &rows, &cols) == 0){
fprintf(stderr, "Error reading the input image, %s.\n", infilename);
exit(1);
}
/****************************************************************************
* Perform the edge detection. All of the work takes place here.
****************************************************************************/
if(VERBOSE) printf("Starting Canny edge detection.\n");
if(dirfilename != NULL){
sprintf(composedfname, "%s_s_%3.2f_l_%3.2f_h_%3.2f.fim", infilename,
sigma, tlow, thigh);
dirfilename = composedfname;
}
canny(image, rows, cols, sigma, tlow, thigh, &edge, dirfilename);
/****************************************************************************
* Write out the edge image to a file.
****************************************************************************/
sprintf(outfilename, "%s_s_%3.2f_l_%3.2f_h_%3.2f.pgm", infilename,
sigma, tlow, thigh);
if(VERBOSE) printf("Writing the edge iname in the file %s.\n", outfilename);
if(write_pgm_image(outfilename, edge, rows, cols, "", 255) == 0){
fprintf(stderr, "Error writing the edge image, %s.\n", outfilename);
exit(1);
}
}
/*******************************************************************************
* PROCEDURE: canny
* PURPOSE: To perform canny edge detection.
* NAME: Mike Heath
* DATE: 2/15/96
*******************************************************************************/
void canny(unsigned char *image, int rows, int cols, float sigma,
float tlow, float thigh, unsigned char **edge, char *fname)
{
FILE *fpdir=NULL; /* File to write the gradient image to. */
unsigned char *nms; /* Points that are local maximal magnitude. */
short int *smoothedim, /* The image after gaussian smoothing. */
*delta_x, /* The first devivative image, x-direction. */
*delta_y, /* The first derivative image, y-direction. */
*magnitude; /* The magnitude of the gadient image. */
int r, c, pos;
float *dir_radians=NULL; /* Gradient direction image. */
/****************************************************************************
* Perform gaussian smoothing on the image using the input standard
* deviation.
****************************************************************************/
if(VERBOSE) printf("Smoothing the image using a gaussian kernel.\n");
gaussian_smooth(image, rows, cols, sigma, &smoothedim);
/****************************************************************************
* Compute the first derivative in the x and y directions.
****************************************************************************/
if(VERBOSE) printf("Computing the X and Y first derivatives.\n");
derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y);
/****************************************************************************
* This option to write out the direction of the edge gradient was added
* to make the information available for computing an edge quality figure
* of merit.
****************************************************************************/
if(fname != NULL){
/*************************************************************************
* Compute the direction up the gradient, in radians that are
* specified counteclockwise from the positive x-axis.
*************************************************************************/
radian_direction(delta_x, delta_y, rows, cols, &dir_radians, -1, -1);
/*************************************************************************
* Write the gradient direction image out to a file.
*************************************************************************/
if((fpdir = fopen(fname, "wb")) == NULL){
fprintf(stderr, "Error opening the file %s for writing.\n", fname);
exit(1);
}
fwrite(dir_radians, sizeof(float), rows*cols, fpdir);
fclose(fpdir);
free(dir_radians);
}
/****************************************************************************
* Compute the magnitude of the gradient.
****************************************************************************/
if(VERBOSE) printf("Computing the magnitude of the gradient.\n");
magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude);
/****************************************************************************
* Perform non-maximal suppression.
****************************************************************************/
if(VERBOSE) printf("Doing the non-maximal suppression.\n");
if((nms = (unsigned char *) calloc(rows*cols,sizeof(unsigned char)))==NULL){
fprintf(stderr, "Error allocating the nms image.\n");
exit(1);
}
non_max_supp(magnitude, delta_x, delta_y, rows, cols, nms);
/****************************************************************************
* Use hysteresis to mark the edge pixels.
****************************************************************************/
if(VERBOSE) printf("Doing hysteresis thresholding.\n");
if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){
fprintf(stderr, "Error allocating the edge image.\n");
exit(1);
}
apply_hysteresis(magnitude, nms, rows, cols, tlow, thigh, *edge);
/****************************************************************************
* Free all of the memory that we allocated except for the edge image that
* is still being used to store out result.
****************************************************************************/
free(smoothedim);
free(delta_x);
free(delta_y);
free(magnitude);
free(nms);
}
/*******************************************************************************
* Procedure: radian_direction
* Purpose: To compute a direction of the gradient image from component dx and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -