📄 canny_src.txt
字号:
* dy images. Because not all derriviatives are computed in the same way, this
* code allows for dx or dy to have been calculated in different ways.
*
* FOR X: xdirtag = -1 for [-1 0 1]
* xdirtag = 1 for [ 1 0 -1]
*
* FOR Y: ydirtag = -1 for [-1 0 1]'
* ydirtag = 1 for [ 1 0 -1]'
*
* The resulting angle is in radians measured counterclockwise from the
* xdirection. The angle points "up the gradient".
*******************************************************************************/
void radian_direction(short int *delta_x, short int *delta_y, int rows,
int cols, float **dir_radians, int xdirtag, int ydirtag)
{
int r, c, pos;
float *dirim=NULL;
double dx, dy;
/****************************************************************************
* Allocate an image to store the direction of the gradient.
****************************************************************************/
if((dirim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
fprintf(stderr, "Error allocating the gradient direction image.\n");
exit(1);
}
*dir_radians = dirim;
for(r=0,pos=0;r<rows;r++){
for(c=0;c<cols;c++,pos++){
dx = (double)delta_x[pos];
dy = (double)delta_y[pos];
if(xdirtag == 1) dx = -dx;
if(ydirtag == -1) dy = -dy;
dirim[pos] = (float)angle_radians(dx, dy);
}
}
}
/*******************************************************************************
* FUNCTION: angle_radians
* PURPOSE: This procedure computes the angle of a vector with components x and
* y. It returns this angle in radians with the answer being in the range
* 0 <= angle <2*PI.
*******************************************************************************/
double angle_radians(double x, double y)
{
double xu, yu, ang;
xu = fabs(x);
yu = fabs(y);
if((xu == 0) && (yu == 0)) return(0);
ang = atan(yu/xu);
if(x >= 0){
if(y >= 0) return(ang);
else return(2*M_PI - ang);
}
else{
if(y >= 0) return(M_PI - ang);
else return(M_PI + ang);
}
}
/*******************************************************************************
* PROCEDURE: magnitude_x_y
* PURPOSE: Compute the magnitude of the gradient. This is the square root of
* the sum of the squared derivative values.
* NAME: Mike Heath
* DATE: 2/15/96
*******************************************************************************/
void magnitude_x_y(short int *delta_x, short int *delta_y, int rows, int cols,
short int **magnitude)
{
int r, c, pos, sq1, sq2;
/****************************************************************************
* Allocate an image to store the magnitude of the gradient.
****************************************************************************/
if((*magnitude = (short *) calloc(rows*cols, sizeof(short))) == NULL){
fprintf(stderr, "Error allocating the magnitude image.\n");
exit(1);
}
for(r=0,pos=0;r<rows;r++){
for(c=0;c<cols;c++,pos++){
sq1 = (int)delta_x[pos] * (int)delta_x[pos];
sq2 = (int)delta_y[pos] * (int)delta_y[pos];
(*magnitude)[pos] = (short)(0.5 + sqrt((float)sq1 + (float)sq2));
}
}
}
/*******************************************************************************
* PROCEDURE: derrivative_x_y
* PURPOSE: Compute the first derivative of the image in both the x any y
* directions. The differential filters that are used are:
*
* -1
* dx = -1 0 +1 and dy = 0
* +1
*
* NAME: Mike Heath
* DATE: 2/15/96
*******************************************************************************/
void derrivative_x_y(short int *smoothedim, int rows, int cols,
short int **delta_x, short int **delta_y)
{
int r, c, pos;
/****************************************************************************
* Allocate images to store the derivatives.
****************************************************************************/
if(((*delta_x) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
fprintf(stderr, "Error allocating the delta_x image.\n");
exit(1);
}
if(((*delta_y) = (short *) calloc(rows*cols, sizeof(short))) == NULL){
fprintf(stderr, "Error allocating the delta_x image.\n");
exit(1);
}
/****************************************************************************
* Compute the x-derivative. Adjust the derivative at the borders to avoid
* losing pixels.
****************************************************************************/
if(VERBOSE) printf(" Computing the X-direction derivative.\n");
for(r=0;r<rows;r++){
pos = r * cols;
(*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos];
pos++;
for(c=1;c<(cols-1);c++,pos++){
(*delta_x)[pos] = smoothedim[pos+1] - smoothedim[pos-1];
}
(*delta_x)[pos] = smoothedim[pos] - smoothedim[pos-1];
}
/****************************************************************************
* Compute the y-derivative. Adjust the derivative at the borders to avoid
* losing pixels.
****************************************************************************/
if(VERBOSE) printf(" Computing the Y-direction derivative.\n");
for(c=0;c<cols;c++){
pos = c;
(*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos];
pos += cols;
for(r=1;r<(rows-1);r++,pos+=cols){
(*delta_y)[pos] = smoothedim[pos+cols] - smoothedim[pos-cols];
}
(*delta_y)[pos] = smoothedim[pos] - smoothedim[pos-cols];
}
}
/*******************************************************************************
* PROCEDURE: gaussian_smooth
* PURPOSE: Blur an image with a gaussian filter.
* NAME: Mike Heath
* DATE: 2/15/96
*******************************************************************************/
void gaussian_smooth(unsigned char *image, int rows, int cols, float sigma,
short int **smoothedim)
{
int r, c, rr, cc, /* Counter variables. */
windowsize, /* Dimension of the gaussian kernel. */
center; /* Half of the windowsize. */
float *tempim, /* Buffer for separable filter gaussian smoothing. */
*kernel, /* A one dimensional gaussian kernel. */
dot, /* Dot product summing variable. */
sum; /* Sum of the kernel weights variable. */
/****************************************************************************
* Create a 1-dimensional gaussian smoothing kernel.
****************************************************************************/
if(VERBOSE) printf(" Computing the gaussian smoothing kernel.\n");
make_gaussian_kernel(sigma, &kernel, &windowsize);
center = windowsize / 2;
/****************************************************************************
* Allocate a temporary buffer image and the smoothed image.
****************************************************************************/
if((tempim = (float *) calloc(rows*cols, sizeof(float))) == NULL){
fprintf(stderr, "Error allocating the buffer image.\n");
exit(1);
}
if(((*smoothedim) = (short int *) calloc(rows*cols,
sizeof(short int))) == NULL){
fprintf(stderr, "Error allocating the smoothed image.\n");
exit(1);
}
/****************************************************************************
* Blur in the x - direction.
****************************************************************************/
if(VERBOSE) printf(" Bluring the image in the X-direction.\n");
for(r=0;r<rows;r++){
for(c=0;c<cols;c++){
dot = 0.0;
sum = 0.0;
for(cc=(-center);cc<=center;cc++){
if(((c+cc) >= 0) && ((c+cc) < cols)){
dot += (float)image[r*cols+(c+cc)] * kernel[center+cc];
sum += kernel[center+cc];
}
}
tempim[r*cols+c] = dot/sum;
}
}
/****************************************************************************
* Blur in the y - direction.
****************************************************************************/
if(VERBOSE) printf(" Bluring the image in the Y-direction.\n");
for(c=0;c<cols;c++){
for(r=0;r<rows;r++){
sum = 0.0;
dot = 0.0;
for(rr=(-center);rr<=center;rr++){
if(((r+rr) >= 0) && ((r+rr) < rows)){
dot += tempim[(r+rr)*cols+c] * kernel[center+rr];
sum += kernel[center+rr];
}
}
(*smoothedim)[r*cols+c] = (short int)(dot*BOOSTBLURFACTOR/sum + 0.5);
}
}
free(tempim);
free(kernel);
}
/*******************************************************************************
* PROCEDURE: make_gaussian_kernel
* PURPOSE: Create a one dimensional gaussian kernel.
* NAME: Mike Heath
* DATE: 2/15/96
*******************************************************************************/
void make_gaussian_kernel(float sigma, float **kernel, int *windowsize)
{
int i, center;
float x, fx, sum=0.0;
*windowsize = 1 + 2 * ceil(2.5 * sigma);
center = (*windowsize) / 2;
if(VERBOSE) printf(" The kernel has %d elements.\n", *windowsize);
if((*kernel = (float *) calloc((*windowsize), sizeof(float))) == NULL){
fprintf(stderr, "Error callocing the gaussian kernel array.\n");
exit(1);
}
for(i=0;i<(*windowsize);i++){
x = (float)(i - center);
fx = pow(2.71828, -0.5*x*x/(sigma*sigma)) / (sigma * sqrt(6.2831853));
(*kernel)[i] = fx;
sum += fx;
}
for(i=0;i<(*windowsize);i++) (*kernel)[i] /= sum;
if(VERBOSE){
printf("The filter coefficients are:\n");
for(i=0;i<(*windowsize);i++)
printf("kernel[%d] = %f\n", i, (*kernel)[i]);
}
}
<------------------------- end canny_edge.c ------------------------->
<------------------------- begin hysteresis.c ------------------------->
/*******************************************************************************
* 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 <stdio.h>
#include <stdlib.h>
#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -