这是[精通VC图像处理(第三版)光盘]的canny算法部分,采用的是模板的方式
我找了很久,需要其它函数,到第二版或者网上找找吧,肯定能找到
#define HDIB HANDLE
#define PI 3.1415926


/**//*************************************************************************
* GausianFilterDIB
*
* Parameters:
* HDIB hDIB - handle to global memory with a DIB spec
* in it followed by the DIB bits
* Return Value:
* BOOL - TRUE is success, else FALSE
* Description:
* Process Gausian filtering
************************************************************************/
BOOL GausianFilterDIB(HDIB hDib)

...{
unsigned char mask[5][5];
int r, c, i, j;
int SUM;

// WaitCursorBegin();

// 5x5 Gaussian mask
mask[0][0] = 2; mask[0][1] = 4; mask[0][2] = 5; mask[0][3] = 4; mask[0][4] = 2;
mask[1][0] = 4; mask[1][1] = 9; mask[1][2] = 12; mask[1][3] = 9; mask[1][4] = 4;
mask[2][0] = 5; mask[2][1] = 12; mask[2][2] = 15; mask[2][3] = 12; mask[2][4] = 5;
mask[3][0] = 4; mask[3][1] = 9; mask[3][2] = 12; mask[3][3] = 9; mask[3][4] = 4;
mask[4][0] = 2; mask[4][1] = 4; mask[4][2] = 5; mask[4][3] = 4; mask[4][4] = 2;

// copy to a new DIB to store original data
HDIB hNewDib = CopyHandle(hDib);
if (! hNewDib)

...{
// WaitCursorEnd();
return FALSE;
}

// new DIB attributes
WORD wDIBWidth = (WORD)DIBWidth(hNewDib);
WORD wDIBHeight = (WORD)DIBHeight(hNewDib);
WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib);

// original DIB become dest image
LPBYTE lpDestDIB = (LPBYTE)GlobalLock(hDib);
LPBYTE lpDestImage = FindDIBBits(lpDestDIB);

// get bits address in DIB
LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
LPBYTE lpDIBits = FindDIBBits(lpDIB);

for(r=0; r<wDIBHeight; r++)

...{
for(c=0; c<wDIBWidth ; c++)

...{
SUM=0;

long lOffset = PIXEL_OFFSET(r,c, wBytesPerLine);

if(r==0 || r==1 || r==wDIBHeight-2 || r==wDIBHeight-1)
SUM = *(lpDIBits + lOffset);
else if(c==0 || c==1 || c==wDIBWidth-2 || c==wDIBWidth-1)
SUM = *(lpDIBits + lOffset);
// Convolution starts here
else

...{
for(i=-2; i<=2; i++)

...{
for(j=-2; j<=2; j++)

...{
lOffset = PIXEL_OFFSET(r+i,c+j, wBytesPerLine);
SUM = SUM + (int)(*(lpDIBits + lOffset) * mask[i+2][j+2]/115);
}
}
}

if(SUM>255)
SUM=255;
if(SUM<0)
SUM=0;

lOffset = PIXEL_OFFSET(r,c, wBytesPerLine);
*(lpDestImage + lOffset) = (unsigned char)(SUM);
}
}

// cleanup temp buffers
GlobalUnlock(hNewDib);
GlobalFree(hNewDib);
GlobalUnlock(hDib);
WaitCursorEnd();
return TRUE;
}



/**//*************************************************************************
* CannyEdegeDetectDIB()
*
* Parameters:
* HDIB hDIB - handle to global memory with a DIB spec
* in it followed by the DIB bits
* Return Value:
* BOOL - TRUE is success, else FALSE
* Description:
* Difference Edege Detect DIB
************************************************************************/
BOOL CannyEdegeDetectDIB(HDIB hDib)

...{
int GX[3][3], GY[3][3];
int sumX, sumY, SUM;
int r,c, i, j;
double ORIENT;
int edgeDirection;
int highThreshold, lowThreshold;
int leftPixel, rightPixel;
int P1, P2, P3, P4, P5, P6, P7, P8;
long lOffset;

WaitCursorBegin();

// 1. convert to gray scale
ConvertToGrayscale(hDib, MEAN_GRAY, 0, 0, 0);

// 2. Gausian Filter DIB
if (! GausianFilterDIB(hDib))

...{
WaitCursorEnd();
return FALSE;
}

// 3. process...

// 3x3 GX Sobel mask. Ref: www.cee.hw.ac.uk/hipr/html/sobel.html
GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1;
GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2;
GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1;

// 3x3 GY Sobel mask. Ref: www.cee.hw.ac.uk/hipr/html/sobel.html
GY[0][0] = 1; GY[0][1] = 2; GY[0][2] = 1;
GY[1][0] = 0; GY[1][1] = 0; GY[1][2] = 0;
GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1;

// copy to a new DIB to store original data
HDIB hNewDib = CopyHandle(hDib);
if (! hNewDib)

...{
WaitCursorEnd();
return FALSE;
}

// new DIB attributes
WORD wDIBWidth = (WORD)DIBWidth(hNewDib);
WORD wDIBHeight = (WORD)DIBHeight(hNewDib);
WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib);

// original DIB become dest image
LPBYTE lpDestDIB = (LPBYTE)GlobalLock(hDib);
LPBYTE lpDestImage = FindDIBBits(lpDestDIB);

// get bits address in DIB
LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
LPBYTE lpDIBits = FindDIBBits(lpDIB);

for(r=0; r<wDIBHeight; r++)

...{
for(c=0; c<wDIBWidth; c++)

...{
sumX = 0;
sumY = 0;

// image boundaries
if(r==0 || r==wDIBHeight-1)
SUM = 0;
else if(c==0 || c==wDIBWidth-1)
SUM = 0;

// Convolution starts here
else

...{

/**//***********************************
* X gradient approximation
***********************************/
for(i=-1; i<=1; i++)

...{
for(j=-1; j<=1; j++)

...{
lOffset = PIXEL_OFFSET(r+i,c+j, wBytesPerLine);
sumX = sumX + (int)(*(lpDIBits + lOffset) * GX[i+1][j+1]);
}
}


/**//**************************
* Y gradient approximation
**************************/
for(i=-1; i<=1; i++)

...{
for(j=-1; j<=1; j++)

...{
lOffset = PIXEL_OFFSET(r+i,c+j, wBytesPerLine);
sumY = sumY + (int)(int)(*(lpDIBits + lOffset) * GY[i+1][j+1]);
}
}


/**//***********************************************
* GRADIENT MAGNITUDE APPROXIMATION (Myler p.218)
***********************************************/
SUM = abs(sumX) + abs(sumY);

if(SUM>255)
SUM=255;
if(SUM<0)
SUM=0;
}


/**//***************************
* Magnitude orientation
***************************/

/**//* Cannot divide by zero*/
if(sumX == 0)

...{
if(sumY==0)
ORIENT = 0.0;
else if (sumY<0)

...{
sumY = -sumY;

ORIENT = 90.0;
}
else
ORIENT = 90.0;
}

// Can't take invtan of angle in 2nd Quad
else if(sumX<0 && sumY>0)

...{
sumX = -sumX;
ORIENT = 180 - ((atan((float)(sumY)/(float)(sumX))) * (180/PI));
}

// Can't take invtan of angle in 4th Quad
else if(sumX>0 && sumY<0)

...{
sumY = -sumY;
ORIENT = 180 - ((atan((float)(sumY)/(float)(sumX))) * (180/PI));
}

// else angle is in 1st or 3rd Quad
else
ORIENT = (atan((float)(sumY)/(float)(sumX))) * (180/PI);



/**//***************************************************
* Find edgeDirection by assigning ORIENT a value of
* either 0, 45, 90 or 135 degrees, depending on which
* value ORIENT is closest to
****************************************************/
if(ORIENT < 22.5)
edgeDirection = 0;
else if(ORIENT < 67.5)
edgeDirection = 45;
else if(ORIENT < 112.5)
edgeDirection = 90;
else if(ORIENT < 157.5)
edgeDirection = 135;
else
edgeDirection = 0;


/**//***************************************************
* Obtain values of 2 adjacent pixels in edge
* direction.
****************************************************/
if(edgeDirection == 0)

...{
lOffset = PIXEL_OFFSET(r,c-1, wBytesPerLine);
leftPixel = (int)(*(lpDIBits + lOffset));
lOffset = PIXEL_OFFSET(r,c+1, wBytesPerLine);
rightPixel = (int)(*(lpDIBits + lOffset));
}

else if(edgeDirection == 45)

...{
lOffset = PIXEL_OFFSET(r+1,c-1, wBytesPerLine);
leftPixel = (int)(*(lpDIBits + lOffset));
lOffset = PIXEL_OFFSET(r+1,c+1, wBytesPerLine);
rightPixel = (int)(*(lpDIBits + lOffset));
}

else if(edgeDirection == 90)

...{
lOffset = PIXEL_OFFSET(r-1,c, wBytesPerLine);
leftPixel = (int)(*(lpDIBits + lOffset));
lOffset = PIXEL_OFFSET(r+1,c, wBytesPerLine);
rightPixel = (int)(*(lpDIBits + lOffset));
}

else

...{
lOffset = PIXEL_OFFSET(r-1,c-1, wBytesPerLine);
leftPixel = (int)(*(lpDIBits + lOffset));
lOffset = PIXEL_OFFSET(r-1,c+1, wBytesPerLine);
rightPixel = (int)(*(lpDIBits + lOffset));
}


/**//*********************************************
* Compare current magnitude to both adjacent
* pixel values. And if it is less than either
* of the 2 adjacent values - suppress it and make
* a nonedge.
*********************************************/

if(SUM < leftPixel || SUM < rightPixel)
SUM = 0;
else

...{

/**//**********************
* Hysteresis
**********************/
highThreshold = 120;
lowThreshold = 40;

lOffset = PIXEL_OFFSET(r,c, wBytesPerLine);
if(SUM >= highThreshold)
SUM = *(lpDIBits + lOffset); // edge
else if(SUM < lowThreshold)
SUM = 0; // nonedge

// SUM is between T1 & T2
else

...{
// Determine values of neighboring pixels
lOffset = PIXEL_OFFSET(r-1,c-1, wBytesPerLine);
P1 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r-1,c, wBytesPerLine);
P2 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r-1,c+1, wBytesPerLine);
P3 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r,c-1, wBytesPerLine);
P4 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r,c+1, wBytesPerLine);
P5 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r+1,c-1, wBytesPerLine);
P6 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r+1,c, wBytesPerLine);
P7 = (int)*(lpDIBits + lOffset);
lOffset = PIXEL_OFFSET(r+1,c+1, wBytesPerLine);
P8 = (int)*(lpDIBits + lOffset);

// Check to see if neighboring pixel values are edges
lOffset = PIXEL_OFFSET(r,c, wBytesPerLine);
if( P1 > highThreshold || P2 > highThreshold ||
P3 > highThreshold || P4 > highThreshold ||
P5 > highThreshold || P6 > highThreshold ||
P7 > highThreshold || P8 > highThreshold)
SUM = *(lpDIBits + lOffset); // make edge
else
SUM = 0; // make nonedge
}
}

lOffset = PIXEL_OFFSET(r,c, wBytesPerLine);
*(lpDestImage + lOffset) = (BYTE)(SUM);
}
}

// cleanup temp buffers
GlobalUnlock(hNewDib);
GlobalFree(hNewDib);
GlobalUnlock(hDib);
WaitCursorEnd();
return TRUE;
}