From 5a422aba704c375a307a902bafe658342e209906 Mon Sep 17 00:00:00 2001 From: scuri Date: Fri, 17 Oct 2008 06:10:15 +0000 Subject: First commit - moving from LuaForge to SourceForge --- src/process/im_canny.cpp | 254 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 src/process/im_canny.cpp (limited to 'src/process/im_canny.cpp') diff --git a/src/process/im_canny.cpp b/src/process/im_canny.cpp new file mode 100644 index 0000000..d749fc0 --- /dev/null +++ b/src/process/im_canny.cpp @@ -0,0 +1,254 @@ +/** \file + * \brief Canny Edge Detector + * + * See Copyright Notice in im_lib.h + * $Id: im_canny.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + +#include + +#include "im_process_loc.h" + +#include +#include +#include + +/* Scale floating point magnitudes to 8 bits */ +static float MAG_SCALE; + +/* Biggest possible filter mask */ +#define MAX_MASK_SIZE 100 + +static float ** f2d (int nr, int nc); +static float gauss(float x, float sigma); +static float dGauss (float x, float sigma); +static float meanGauss (float x, float sigma); +static void seperable_convolution (const imImage* im, float *gau, int width, float **smx, float **smy); +static void dxy_seperable_convolution (float** im, int nr, int nc, float *gau, int width, float **sm, int which); +static void nonmax_suppress (float **dx, float **dy, imImage* mag); + +void imProcessCanny(const imImage* im, imImage* NewImage, float stddev) +{ + int width = 1; + float **smx,**smy; + float **dx,**dy; + int i; + float gau[MAX_MASK_SIZE], dgau[MAX_MASK_SIZE]; + +/* Create a Gaussian and a derivative of Gaussian filter mask */ + for(i=0; iheight, im->width); + smy = f2d (im->height, im->width); + +/* Convolution of source image with a Gaussian in X and Y directions */ + seperable_convolution (im, gau, width, smx, smy); + + MAG_SCALE = 0; + +/* Now convolve smoothed data with a derivative */ + dx = f2d (im->height, im->width); + dxy_seperable_convolution (smx, im->height, im->width, dgau, width, dx, 1); + free(smx[0]); free(smx); + + dy = f2d (im->height, im->width); + dxy_seperable_convolution (smy, im->height, im->width, dgau, width, dy, 0); + free(smy[0]); free(smy); + + if (MAG_SCALE) + MAG_SCALE = 255.0f/(1.4142f*MAG_SCALE); + + /* Non-maximum suppression - edge pixels should be a local max */ + nonmax_suppress (dx, dy, NewImage); + + free(dx[0]); free(dx); + free(dy[0]); free(dy); +} + +static float norm (float x, float y) +{ + return (float) sqrt ( (double)(x*x + y*y) ); +} + +static float ** f2d (int nr, int nc) +{ + float **x, *y; + int i; + + x = (float **)calloc ( nr, sizeof (float *) ); + if (!x) + return NULL; + + y = (float *)calloc ( nr*nc, sizeof (float) ); + if (!y) + return NULL; + + for (i=0; idata[0]; + + nr = im->height; + nc = im->width; + + for (i=0; iwidth + j]; y = gau[0] * im_data[i*im->width + j]; + for (k=1; kwidth + j] + gau[k]*im_data[I2*im->width + j]; + I1 = (j+k)%nc; I2 = (j-k+nc)%nc; + x += gau[k]*im_data[i*im->width + I1] + gau[k]*im_data[i*im->width + I2]; + } + smx[i][j] = x; smy[i][j] = y; + } + } +} + +static void dxy_seperable_convolution (float** im, int nr, int nc, float *gau, int width, float **sm, int which) +{ + int i,j,k, I1, I2; + float x; + + for (i=0; i MAG_SCALE) + MAG_SCALE = x; + } + } +} + +static unsigned char tobyte(float x) +{ + if (x > 255) return 255; + return (unsigned char)x; +} + +static void nonmax_suppress (float **dx, float **dy, imImage* mag) +{ + int i,j; + float xx, yy, g2, g1, g3, g4, g, xc, yc; + unsigned char* mag_data = (unsigned char*)mag->data[0]; + + for (i=1; iheight-1; i++) + { + for (j=1; jwidth-1; j++) + { + /* Treat the x and y derivatives as components of a vector */ + xc = dx[i][j]; + yc = dy[i][j]; + if (fabs(xc)<0.01 && fabs(yc)<0.01) continue; + + g = norm (xc, yc); + + /* Follow the gradient direction, as indicated by the direction of + the vector (xc, yc); retain pixels that are a local maximum. */ + + if (fabs(yc) > fabs(xc)) + { + /* The Y component is biggest, so gradient direction is basically UP/DOWN */ + xx = (float)(fabs(xc)/fabs(yc)); + yy = 1.0; + + g2 = norm (dx[i-1][j], dy[i-1][j]); + g4 = norm (dx[i+1][j], dy[i+1][j]); + if (xc*yc > 0.0) + { + g3 = norm (dx[i+1][j+1], dy[i+1][j+1]); + g1 = norm (dx[i-1][j-1], dy[i-1][j-1]); + } + else + { + g3 = norm (dx[i+1][j-1], dy[i+1][j-1]); + g1 = norm (dx[i-1][j+1], dy[i-1][j+1]); + } + + } + else + { + /* The X component is biggest, so gradient direction is basically LEFT/RIGHT */ + xx = (float)(fabs(yc)/fabs(xc)); + yy = 1.0; + + g2 = norm (dx[i][j+1], dy[i][j+1]); + g4 = norm (dx[i][j-1], dy[i][j-1]); + if (xc*yc > 0.0) + { + g3 = norm (dx[i-1][j-1], dy[i-1][j-1]); + g1 = norm (dx[i+1][j+1], dy[i+1][j+1]); + } + else + { + g1 = norm (dx[i-1][j+1], dy[i-1][j+1]); + g3 = norm (dx[i+1][j-1], dy[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)) ) + { + mag_data[i*mag->width + j] = tobyte(g*MAG_SCALE); + } + } + } +} -- cgit v1.2.3