这是[精通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;
}
#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;
}