// EdgeCanny.cpp: implementation of the CEdgeCanny class.
//
//
#include "stdafx.h"
#include "EdgeCanny.h"
#include "math.h"
#include
#include
//
// Construction/Destruction
//
CEdgeCanny::CEdgeCanny()
{
}
CEdgeCanny::~CEdgeCanny()
{
}
#ifndef MAX
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#endif
void fnFilter2DC(int *dstmat,unsigned char *mat,int *Imag,int iSrcWidth,
int iSrcHeight,int iKWidth,int iKHeight)
{
int iWidthByteDuiqi = iSrcWidth;
while(iWidthByteDuiqi%4 != 0)
{
iWidthByteDuiqi = (iWidthByteDuiqi/4+1)*4;
}
int iDealWidth = (iKWidth-1)/2;
int iDealHeight = (iKHeight-1)/2;
for (int i = 0; i < iSrcHeight; i++)
{
for (int j = 0; j < iSrcWidth; j++)
{
int sum = 0;
for (int ky = -iDealHeight; ky <= iDealHeight; ky++)
{
for (int kx = -iDealWidth; kx <= iDealWidth; kx++)
{
int matValue = 0;
if(i+ky<0 || i+ky>(iSrcHeight-1) || j+kx<0 || j+kx>(iSrcWidth-1) )
{
matValue = 0;
}
else
{
matValue = mat[(i+ky)*iWidthByteDuiqi+(j+kx)];
}
int kValue = Imag[(iDealHeight+ky)*iKWidth+(iDealWidth+kx)];
sum = matValue*kValue + sum;
}
}
dstmat[i*iSrcWidth+j]= (int)sum;
}
}
}
void CEdgeCanny::cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size,int iWidth,int iHeight)
{
//void* buffer = 0;
//int local_alloc = 0;
int origin = 0;
int src_type, dst_type;
unsigned char *src = (unsigned char*)srcarr;
int *dst = (int*)dstarr;
src_type = 0;
dst_type = 3;
origin = 0;
int kernelv[9]={-1,0,1,
-2,0,2,
-1,0,1};
int kernelh[9]={-1,-2,-1,
0,0,0,
1,2,1};
if(1 == dx && 0 == dy)
{
fnFilter2DC(dst,src,kernelh, iWidth, iHeight,3,3);
}
if(0 == dx && 1 == dy)
{
fnFilter2DC(dst,src,kernelv, iWidth, iHeight,3,3);
}
}
void CEdgeCanny::fnSobleEdge(unsigned char *pBuffer,unsigned char **pBufferDst,int iWidth, int iHeight,
bool bVertical,bool bHorizon,int ithreshold,int fillvalue)
{
if( (!bVertical) && (!bHorizon) )
{
return;
}
// int iframe =0;
int *dx = 0;
int *dy = 0;
int aperture_size= 3;
if(bVertical)
{
dx = new int[iWidth*iHeight];
cvSobel( pBuffer, dx, 1, 0, aperture_size,iWidth,iHeight);
}
if(bHorizon)
{
dy = new int[iWidth*iHeight];
cvSobel( pBuffer, dy, 0, 1, aperture_size,iWidth,iHeight);
}
aperture_size = 3;
int iWidthBWByteDuiqi = iWidth;
while(iWidthBWByteDuiqi%4 != 0)
{
iWidthBWByteDuiqi = (iWidthBWByteDuiqi/4+1)*4;
}
if(0 != pBufferDst )
{
*pBufferDst = new unsigned char[iWidthBWByteDuiqi*iHeight];
}
else
{
return;
}
for(int i=0;i
for(int j=0;j
int ivaluev =0;//垂直
int ivalueh =0;//水平
if(bVertical)
{
ivaluev = dx[i*iWidth+j];
ivaluev = abs(ivaluev);
}
if(bHorizon)//
{
ivalueh = dy[i*iWidth+j];
ivalueh = abs(ivalueh);
}
if(abs(ivalueh)< abs(ivaluev))
{
ivalueh = ivaluev;
}
if(abs(ivalueh)
(*pBufferDst)[i*iWidthBWByteDuiqi+j] =0;
}
else
{
(*pBufferDst)[i*iWidthBWByteDuiqi+j] = fillvalue;
}
}
}
m_pdx = dx;
m_pdy = dy;
/* if(0 != dx)
{
delete [] dx;
dx = 0;
}
if(0 != dy)
{
delete [] dy;
dy = 0;
}
*/
//CImageOp objCImageOp;
//int iframe =0;
//objCImageOp.fnWriteGray(*pBufferDst,iframe,iWidth,iHeight,0); //
return;
}
#define INT_MAX 2147483647 /* maximum (signed) int value */
void CEdgeCanny::fnCannyEdge( const BYTE* srcarr, BYTE** dstarr,int iWidth, int iHeight,
double low_thresh, double high_thresh, int aperture_size )
{//?????high_thresh?low_thresh?2?? ??matlab??????//matlab??0.4?2???
//matlab???3???,???????,????????
int *icvFilterSobelVert_8u16s_C1R_p = 0;
void *buffer = 0;
BYTE **stack_top, **stack_bottom = 0;
BYTE *src = (BYTE*)srcarr;
//BYTE *dst = (BYTE**)dstarr;
BYTE **dst = dstarr;
CSizeEdge size;
size.width = iWidth;
size.height = iHeight;
int flags = aperture_size;
int low, high;
int* mag_buf[3];
BYTE* map;
int mapstep, maxsize;
int i, j;
if( low_thresh > high_thresh )
{
// double t;
// CV_SWAP( low_thresh, high_thresh, t );
}
aperture_size &= INT_MAX;
int iWidthByteDuiqi = iWidth;//short???
// while(iWidthByteDuiqi%2 != 0)
// {
// iWidthByteDuiqi = (iWidthByteDuiqi/2+1)*2;
// }
int * dx = new int[iWidthByteDuiqi*iHeight];
int * dy = new int[iWidthByteDuiqi*iHeight];
//cvSobel( src, dx, 1, 0, aperture_size,iWidth,iHeight);//??soble ??dx,??dy/
//cvSobel( src, dy, 0, 1, aperture_size,iWidth,iHeight);
cvSobel( src, dx, 0, 1, aperture_size,iWidth,iHeight);//??soble ??dx,??dy/
cvSobel( src, dy, 1, 0, aperture_size,iWidth,iHeight);
//dx?cv??1000??????dy?1000??cv?????
//low = cvFloor( low_thresh );//??????????
//high = cvFloor( high_thresh );
low = low_thresh;//??????????
high = high_thresh;//ll
buffer = malloc( (size.width+2)*(size.height+2) +
(size.width+2)*3*sizeof(int));
mag_buf[0] = (int*)buffer;
mag_buf[1] = mag_buf[0] + size.width + 2;
mag_buf[2] = mag_buf[1] + size.width + 2;//mag_buf ???3????
map = (BYTE*)(mag_buf[2] + size.width + 2);//?3????
mapstep = size.width + 2;//???
maxsize = MAX( 1 << 10, size.width*size.height/10 );//?,?,????????
stack_top = stack_bottom = (BYTE**)malloc( maxsize*sizeof(stack_top[0]) );
//????,?,??????,??????????????????????
memset( mag_buf[0], 0, (size.width+2)*sizeof(int) );//
memset( map, 1, mapstep );//?3???
memset( map + mapstep*(size.height + 1), 1, mapstep );//
/* sector numbers
(Top-Left Origin)
1 2 3
* * *
* * *
0*******0
* * *
* * *
3 2 1
*/
#define CANNY_PUSH(d) *(d) = (BYTE)2, *stack_top++ = (d)
#define CANNY_POP(d) (d) = *--stack_top
//???,???,??????????
//mag_row = cvMat( 1, size.width, CV_32F );//?????
//float *mag_row = new float[iWidth*iHeight];//??????????
//float *mag_row = new float[iWidth];//??iWidth*iHeight????,??????????mag_row?
//???,?????
// calculate magnitude and angle of gradient, perform non-maxima supression.
// fill the map with one of the following values:
// 0 - the pixel might belong to an edge
// 1 - the pixel can not belong to an edge
// 2 - the pixel does belong to an edge
int dxstep = iWidth;//*2;
int dystep = iWidth;//*2; //??????cv????dx??short?????
//?????????????
for( i = 0; i <= size.height; i++ ) //G:\aa6\test5.bmp 53
{
int* _mag = mag_buf[(i > 0) + 1] + 1;
float* _magf = (float*)_mag;
//const short* _dx = (short*)(dx + dxstep*i);//??????????
//const short* _dy = (short*)(dy + dystep*i);
const int* _dx = (int*)(dx + dxstep*i);//??????????
const int* _dy = (int*)(dy + dystep*i);
BYTE* _map;
int x, y;
int magstep1, magstep2;
int prev_flag = 0;
if( i < size.height )
{
_mag[-1] = _mag[size.width] = 0;//?,?????0.
if( !(flags & CV_CANNY_L2_GRADIENT) )
{
for( j = 0; j < size.width; j++ )
{
_mag[j] = abs(_dx[j]) + abs(_dy[j]);//???????????????????????
//_dy????cv???????
//??????
}//??????mag_buf?? ???????
}
else if( icvFilterSobelVert_8u16s_C1R_p != 0 ) // check for IPP
{
// use vectorized sqrt
/* mag_row = _magf;
for( j = 0; j < size.width; j++ )
{
x = _dx[j]; y = _dy[j];
_magf[j] = (float)((double)x*x + (double)y*y);
}//???????
//cvPow( &mag_row, &mag_row, 0.5 );
//double pow( double x, double y );//??????,?????????
//??icvFilterSobelVert_8u16s_C1R_p?????0??
*/
;
}
else
{
for( j = 0; j < size.width; j++ )
{
x = _dx[j]; y = _dy[j];
_magf[j] = (float)sqrt((double)x*x + (double)y*y);
}
}
}
else
memset( _mag-1, 0, (size.width + 2)*sizeof(int) );
// at the very beginning we do not have a complete ring
// buffer of 3 magnitude rows for non-maxima suppression
if( i == 0 )
continue;
_map = map + mapstep*i + 1;//??map?i??????
_map[-1] = _map[size.width] = 1;
_mag = mag_buf[1] + 1; // take the central row
//
_dx = (int*)(dx + dxstep*(i-1));
_dy = (int*)(dy + dystep*(i-1));
magstep1 = (int)(mag_buf[2] - mag_buf[1]);
magstep2 = (int)(mag_buf[0] - mag_buf[1]);
if( (stack_top - stack_bottom) + size.width > maxsize )
{
BYTE** new_stack_bottom;
maxsize = MAX( maxsize * 3/2, maxsize + size.width );//????,????????,??
//???????
new_stack_bottom = (BYTE**)malloc( maxsize * sizeof(stack_top[0]));
memcpy( new_stack_bottom, stack_bottom, (stack_top - stack_bottom)*sizeof(stack_top[0]) );
//?????copy??????
stack_top = new_stack_bottom + (stack_top - stack_bottom);
free(stack_bottom);
stack_bottom = new_stack_bottom;//?????????
}
for( j = 0; j < size.width; j++ )//?????????
{
#define CANNY_SHIFT 15
#define TG22 (int)(0.4142135623730950488016887242097*(1<
x = _dx[j];
y = _dy[j];
int s = x ^ y;
int m = _mag[j];//m??????????i???????????????
x = abs(x);
y = abs(y);
if( m > low )//low = 50
{
int tg22x = x * TG22;
int tg67x = tg22x + ((x + x) << CANNY_SHIFT);
y <<= CANNY_SHIFT;
if( y < tg22x )
{
if( m > _mag[j-1] && m >= _mag[j+1] )//???????????????
{
if( m > high && !prev_flag && _map[j-mapstep] != 2 )//????2????_map??,0,1.
{//?????????? //?????????????????
CANNY_PUSH( _map + j );//???????????????????
prev_flag = 1;//?????1.????,????????
}
else
_map[j] = (BYTE)0;//?????0._map???i??????//???????0,
//?????????0.?????????0.
continue;
}
}
else if( y > tg67x )
{
if( m > _mag[j+magstep2] && m >= _mag[j+magstep1] )
{
if( m > high && !prev_flag && _map[j-mapstep] != 2 )
{
CANNY_PUSH( _map + j );
prev_flag = 1;
}
else
_map[j] = (BYTE)0;
continue;
}
}
else
{
s = s < 0 ? -1 : 1;
if( m > _mag[j+magstep2-s] && m > _mag[j+magstep1+s] )
{
if( m > high && !prev_flag && _map[j-mapstep] != 2 )
{
CANNY_PUSH( _map + j );
prev_flag = 1;
}
else
_map[j] = (BYTE)0;
continue;
}
}
}//??????,?????0,??????????1,?????????
//?2???????
//2??????????
prev_flag = 0;//?????????1.
_map[j] = (BYTE)1;//????
}
// scroll the ring buffer
_mag = mag_buf[0];/// ????????
mag_buf[0] = mag_buf[1];
mag_buf[1] = mag_buf[2]; //mag_buf?
mag_buf[2] = _mag;//????
}
// now track the edges (hysteresis thresholding)
while( stack_top > stack_bottom )//????? hysteresis:?? ????
{
BYTE* m;
if( (stack_top - stack_bottom) + 8 > maxsize )//????????
{
BYTE** new_stack_bottom;
maxsize = MAX( maxsize * 3/2, maxsize + 8 );//??????????8??
new_stack_bottom = (BYTE**)malloc( maxsize * sizeof(stack_top[0]));
memcpy( new_stack_bottom, stack_bottom, (stack_top - stack_bottom)*sizeof(stack_top[0]) );
stack_top = new_stack_bottom + (stack_top - stack_bottom);
//cvFree( &stack_bottom );
free(stack_bottom);//ll
stack_bottom = new_stack_bottom;
}
CANNY_POP(m);//??? ???8??????????????????????
//m????????????
if( !m[-1] ) //?m?8??,?????0?,????2. ???1,?????
CANNY_PUSH( m - 1 );//???
if( !m[1] )
CANNY_PUSH( m + 1 );//??
if( !m[-mapstep-1] )//?????
CANNY_PUSH( m - mapstep - 1 );
if( !m[-mapstep] )//??
CANNY_PUSH( m - mapstep );
if( !m[-mapstep+1] )//??????
CANNY_PUSH( m - mapstep + 1 );
if( !m[mapstep-1] )//?????
CANNY_PUSH( m + mapstep - 1 );
if( !m[mapstep] )//??
CANNY_PUSH( m + mapstep );
if( !m[mapstep+1] )//??????
CANNY_PUSH( m + mapstep + 1 );
}
// the final pass, form the final image
int dststep = iWidth;
// int iWidthBWByteDuiqi = iWidth;//short???
while(dststep%4 != 0)
{
dststep = (dststep/4+1)*4;
}
if(NULL != dst)
{
*dst = new BYTE[dststep*size.height];
}
else
{
return;
}
for( i = 0; i < size.height; i++ )
{
const BYTE* _map = map + mapstep*(i+1) + 1;//?????????
BYTE* _dst = (*dst) + dststep*i;//??????
for( j = 0; j < size.width; j++ )
_dst[j] = (BYTE)-(_map[j] >> 1);//??????
// 2>>1 ?1
// 1>>1 ?0
// 0>>1 ?0
// ?????????-1??uchar,???1 256??uchar,????????255??
}//??????0?255.
//_map?,?,0,1,2,
//2: >>1,??1,????1.
//1: >>1 ????0.
//0: >>1 ????0.
//???????,??0?1.
// __END__;
if(NULL !=dx)
{
delete [] dx;
dx = NULL;//??? ?dx???,???????
}
if(NULL != dy)
{
delete [] dy;
dy = NULL;
}
if(NULL != buffer)
{
free(buffer);
buffer = NULL;
}
if(NULL != stack_bottom)
{
free(stack_bottom);
stack_bottom = NULL;
}
// CImageOp objCImageOp;
int iframe =0;
// objCImageOp.fnWriteGray(*dst,iframe,iWidth,iHeight,0); //
//objCImageOp.fnWriteGray(pBufferScaled,iframe,iWidth,iHeight,0); //
}
/*
void CEdgeCanny::cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size,int iWidth,int iHeight)
{
//void* buffer = 0;
//int local_alloc = 0;
int origin = 0;
int src_type, dst_type;
unsigned char *src = (unsigned char*)srcarr;
int *dst = (int*)dstarr;
src_type = 0;
dst_type = 3;
origin = 0;
int kernelv[9]={-1,0,1,
-2,0,2,
-1,0,1};
int kernelh[9]={-1,-2,-1,
0,0,0,
1,2,1};
if(1 == dx && 0 == dy)
{
fnFilter2D(dst,src,kernelh, iWidth, iHeight,3,3);
}
if(0 == dx && 1 == dy)
{
fnFilter2D(dst,src,kernelv, iWidth, iHeight,3,3);
}
}
*/
/*
void CEdgeCanny::fnSobleEdge(unsigned char *pBuffer,unsigned char **pBufferDst,int iWidth, int iHeight,
bool bVertical,bool bHorizon,int ithreshold,int fillvalue)
{
if( (!bVertical) && (!bHorizon) )
{
return;
}
// int iframe =0;
int *dx = 0;
int *dy = 0;
int aperture_size= 3;
if(bVertical)
{
dx = new int[iWidth*iHeight];
cvSobel( pBuffer, dx, 1, 0, aperture_size,iWidth,iHeight);
}
if(bHorizon)
{
dy = new int[iWidth*iHeight];
cvSobel( pBuffer, dy, 0, 1, aperture_size,iWidth,iHeight);
}
aperture_size = 3;
int iWidthBWByteDuiqi = iWidth;
while(iWidthBWByteDuiqi%4 != 0)
{
iWidthBWByteDuiqi = (iWidthBWByteDuiqi/4+1)*4;
}
if(0 != pBufferDst )
{
*pBufferDst = new unsigned char[iWidthBWByteDuiqi*iHeight];
}
else
{
return;
}
for(int i=0;i
for(int j=0;j
int ivaluev =0;//垂直
int ivalueh =0;//水平
if(bVertical)
{
ivaluev = dx[i*iWidth+j];
ivaluev = abs(ivaluev);
}
if(bHorizon)//
{
ivalueh = dy[i*iWidth+j];
ivalueh = abs(ivalueh);
}
if(abs(ivalueh)< abs(ivaluev))
{
ivalueh = ivaluev;
}
if(abs(ivalueh)
(*pBufferDst)[i*iWidthBWByteDuiqi+j] =0;
}
else
{
(*pBufferDst)[i*iWidthBWByteDuiqi+j] = fillvalue;
}
}
}
if(0 != dx)
{
delete [] dx;
dx = 0;
}
if(0 != dy)
{
delete [] dy;
dy = 0;
}
//CImageOp objCImageOp;
//int iframe =0;
//objCImageOp.fnWriteGray(*pBufferDst,iframe,iWidth,iHeight,0); //
return;
}
*/
.h
// EdgeCanny.h: interface for the CEdgeCanny class.
//
//
#if !defined(AFX_EDGECANNY_H__60D443F2_3775_4635_8179_F75B91B7FDF8__INCLUDED_)
#define AFX_EDGECANNY_H__60D443F2_3775_4635_8179_F75B91B7FDF8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define CV_CANNY_L2_GRADIENT (1 << 31)
struct CSizeEdge
{
int width;
int height;
};
class CEdgeCanny
{
public:
void fnCannyEdge( const unsigned char* srcarr, unsigned char** dstarr,int iWidth, int iHeight,
double low_thresh, double high_thresh, int aperture_size );
void fnSobleEdge(unsigned char *pBuffer,unsigned char **pBufferDst,int iWidth, int iHeight,
bool bVertical,bool bHorizon,int ithreshold,int fillvalue=255);
CEdgeCanny();
virtual ~CEdgeCanny();
private:
void cvSobel( const void* srcarr, void* dstarr, int dx, int dy, int aperture_size,int iWidth,int iHeight );
int * m_pdx;
int * m_pdy;
};
#endif // !defined(AFX_EDGECANNY_H__60D443F2_3775_4635_8179_F75B91B7FDF8__INCLUDED_)