www.pudn.com > Face3DModel.zip > CannyEdgeDetector.cpp
// CannyEdgeDetector.cpp: implementation of the CCannyEdgeDetector class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "global.h"
#include "memory.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define ORIENT_SCALE 40.0
void EdgeDetectOnGrayImage(unsigned char *SrcImage, unsigned char *DstImage, int width, int height, int StandardDev, int LowerThreshold, int HigherThreshold)
{
unsigned char *Derivative=new unsigned char[width*height];
unsigned char *Orient =new unsigned char[width*height];
unsigned char *Strength = new unsigned char[width*height];
memset(Derivative, 0, width*height);
memset(Orient, 0, width*height);
memset(Strength, 0, width*height);
canny_core(StandardDev,width,height,SrcImage,Derivative,Strength,Orient);
thresholding_tracker(HigherThreshold,LowerThreshold,width,height,DstImage,Strength,Orient);
delete [] Derivative;
delete [] Orient;
delete [] Strength;
}
//////////////////////////////////////////////////////////////////
// call canny core routines - these perform a gaussian
// smoothing, calculate a gradient array and suppress
// non- maximal points in this array
//////////////////////////////////////////////////////////////////
int canny_core(double s, int width, int height, unsigned char *data, unsigned char *derivative_mag, unsigned char *magnitude, unsigned char *orientation)
{
int filter_width; // length of 1-D gaussian mask
double *gsmooth_x,*gsmooth_y;
double *derivative_x,*derivative_y;
int i,k,n; // counters
int t; // temp. grad magnitude variable
double a,b,c,d,g0; // mask generation intermediate vars
double ux,uy;
double t1,t2;
double G[20],dG[20],D2G[20]; // gaussian & derivative filter masks
double gc,gn,gs,gw,ge,gnw,gne,gsw,gse;
int picsize,jstart,jlimit;
int ilimit;
register jfactor;
int kfactor1,kfactor2;
int kfactor;
register cindex,nindex,sindex,windex,eindex,nwindex,neindex,swindex,seindex;
int low=1,high=255; // tracker hysteresis parameters
int mag_overflow_count=0; // used to measure how oft mag array overflows
int mag_underflow_count=0; // used to measure how oft mag array underflows
picsize=width*height; // picture area
//////////////////////////////////////////////////
// calc coeffs for 1-dimensional G, dG/dn and
// Delta-squared G filters
//////////////////////////////////////////////////
for(n=0; n<20; ++n)
{
a=gaussian(((double) n),s);
if (a>0.005 || n<2)
{
b=gaussian((double)n-0.5,s);
c=gaussian((double)n+0.5,s);
d=gaussian((double)n,s*0.5);
G[n]=(a+b+c)/3/(6.283185*s*s);
dG[n]=c-b;
D2G[n]=1.6*d-a; /* DOG */
}
else break;
}
filter_width=n;
///////////////////////////////////////////////////
// allocate space for gaussian smoothing arrays
///////////////////////////////////////////////////
gsmooth_x=new double[picsize];
gsmooth_y=new double[picsize];
///////////////////////////////////////////////////
// produce x- and y- convolutions with gaussian
///////////////////////////////////////////////////
ilimit=width-(filter_width-1);
jstart=width*(filter_width-1);
jlimit=width*(height-(filter_width-1));
for (i=filter_width-1;i0)
{
if(fabs(ux)=high)
follow(i,j,low,cols,rows,data,magnitude,orientation);
}
}
////////////////////////////////////
// follow a connected edge
////////////////////////////////////
int follow(int i, int j, int low, int cols, int rows, unsigned char *data, unsigned char *magnitude, unsigned char *orientation)
{
int k,l; // counters
int i_plus_1,i_minus_1,j_plus_1,j_minus_1;
long index,kindex;
char break_flag;
i_plus_1=i+1;
i_minus_1=i-1;
j_plus_1=j+1;
j_minus_1=j-1;
index=i+j*cols;
if (j_plus_1>=rows) j_plus_1=rows-1;
if (j_minus_1<0) j_minus_1=0;
if (i_plus_1>=cols) i_plus_1=cols-1;
if (i_minus_1<0) i_minus_1=0;
if (!data[index])
{
///////////////////////////////////////////////////////////////
// current point must be added to the list of tracked points
///////////////////////////////////////////////////////////////
data[index]=magnitude[index];
///////////////////////////////////////////////////////////////
// now we can check immediately adjacent points to see if
// they too could be added to the track
///////////////////////////////////////////////////////////////
break_flag=0;
for (k=i_minus_1;k<=i_plus_1;k++)
{
for(l=j_minus_1;l<=j_plus_1;++l)
{
kindex=k+l*cols;
if (!(l==j && k==i) && magnitude[kindex]>=low/* && abs(abs(orientation[index]-orientation[kindex])-128)>120*/)
{
if(follow(k,l,low,cols,rows,data,magnitude,orientation))
{
break_flag=1;
break;
}
}
}
if (break_flag) break;
}
return 1;
}
else return 0;
}
unsigned char GetGray(unsigned char x1,unsigned char x2,unsigned char x3)
{
return (float)x1*0.299+x2*0.587+x3*0.114;
}