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; 
}