📄 edgedetector.cpp
字号:
// EdgeDector.cpp : implementation file
//
#include "stdafx.h"
#include "EdgeDetector.h"
#include "Image.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CEdgeDetector
CEdgeDetector::CEdgeDetector( CImage* pImage )
{
m_pImage = pImage;
m_pImg = m_pImage->GetPtr();
m_Size = m_pImage->GetImageSize();
}
CEdgeDetector::CEdgeDetector( BYTE** pImg, CSize size )
{
m_pImg = pImg;
m_Size = size;
}
CEdgeDetector::~CEdgeDetector()
{
}
/////////////////////////////////////////////////////////////////////////////
// CEdgeDetector member functions
void CEdgeDetector::Edge_Sobel()
{
short my[3][3] = {{-1,-2,-1},{0,0,0},{1,2,1}};
short mx[3][3] = {{-1,0,1},{-2,0,2},{-1,0,1}};
int w = m_Size.cx;
int h = m_Size.cy;
int i,j;
float** gx;
float** gy;
float** g;
gx = new float*[h];
gy = new float*[h];
g = new float*[h];
for( i = 0 ; i < h ; i++ )
{
gx[i] = new float[w];
gy[i] = new float[w];
g[i] = new float[w];
}
BYTE** img = m_pImg;
int m,n;
for( j = 1 ; j < h-1 ; j++ )
{
for( i = 1 ; i < w-1 ; i++ )
{
gx[j][i] = 0;
gy[j][i] = 0;
for( m = 0 ; m < 3 ; m++ )
{
for( n = 0 ; n < 3 ; n++ )
{
gx[j][i] += mx[m][n]*img[j+m-1][i+n-1];
gy[j][i] += my[m][n]*img[j+m-1][i+n-1];
}
}
}
}
float ex,ey;
float max = 0;
for( j = 0 ; j < h ; j++ )
{
for( i = 0 ; i < w ; i++ )
{
if( i == 0 || i == w-1 || j == 0 || j == h-1 )
{
g[j][i] = 0;
}
else
{
ex = gx[j][i]*gx[j][i];
ey = gy[j][i]*gy[j][i];
g[j][i] = (float)sqrt( ex + ey );
}
if( g[j][i] > 255 )
img[j][i] = 255;
else
img[j][i] = (BYTE)g[j][i];
}
}
for( i = 0 ; i < h ; i++ )
{
delete [] gx[i];
delete [] gy[i];
delete [] g[i];
}
delete [] gx;
delete [] gy;
delete [] g;
}
void CEdgeDetector::Edge_Deriche( float a )
{
int w = m_Size.cx;
int h = m_Size.cy;
int l;
int i,j;
float** y1;
float** y2;
float** rx;
float** ry;
if( w > h ) l = w;
else l = h;
y1 = new float*[h];
y2 = new float*[h];
rx = new float*[h];
ry = new float*[h];
for( i = 0 ; i < h ; i++ )
{
y1[i] = new float[w];
y2[i] = new float[w];
rx[i] = new float[w];
ry[i] = new float[w];
memset(y1[i], 0, sizeof(float)*w);
memset(y2[i], 0, sizeof(float)*w);
memset(rx[i], 0, sizeof(float)*w);
memset(ry[i], 0, sizeof(float)*w);
}
BYTE** img = m_pImg;
float k;
k = (float)((1-exp(-a))*(1-exp(-a))/(1+2*a*exp(-a)-exp(-2*a)));
float a1, a2, a3, a4, a5, a6, a7, a8, c1, c2, b1, b2;
a1 = 0; a2 = 1 ; a3 = -1 ; a4 = 0;
a5 = k; a6 = (float)(k*exp(-a)*(a-1)); a7 = (float)(k*exp(-a)*(a+1)); a8 = (float)(-k*exp(-2*a));
c1 = (float)(-(1-exp(-a))*(1-exp(-a)));
c2 = 1;
b1 = (float)(2*exp(-a));
b2 = (float)(-exp(-2*a));
int m,n;
for( j = 2 ; j < h-2 ; j++ )
{
for( i = 2 ; i < w-2 ; i++ )
{
y1[j][i] = img[j][i-1]+b1*y1[j][i-1]+b2*y1[j][i-2];
n = w-1-i;
y2[j][n] = -img[j][n+1]+b1*y2[j][n+1]+b2*y2[j][n+2];
}
for( i = 2 ; i < w-2 ; i++ )
rx[j][i] = c1*(y1[j][i]+y2[j][i]);
}
for( i = 2 ; i < w-2 ; i++ )
{
for( j = 2 ; j < h-2 ; j++ )
{
y1[j][i] = a5*rx[j][i]+a6*rx[j-1][i]+b1*y1[j-1][i]+b2*y1[j-2][i];
m = h-1-j;
y2[m][i] = a7*rx[m+1][i]+a8*rx[m+2][i]+b1*y2[m+1][i]+b2*y2[m+2][i];
}
for( j = 2 ; j < h-2 ; j++ )
rx[j][i] = y1[j][i]+y2[j][i];
}
a5 = 0; a6 = 1; a7 = -1; a8 = 0;
a1 = k; a2 = (float)(k*exp(-a)*(a-1)); a3 = (float)(k*exp(-a)*(a+1)); a4 = (float)(-k*exp(-2*a));
c2 = (float)(-(1-exp(-a))*(1-exp(-a)));
c1 = 1;
b1 = (float)(2*exp(-a));
b2 = (float)(-exp(-2*a));
for( j = 2 ; j < h-2 ; j++ )
{
for( i = 2 ; i < w-2 ; i++ )
{
y1[j][i] = a1*img[j][i]+a2*img[j][i-1]+b1*y1[j][i-1]+b2*y1[j][i-2];
n = w-1-i;
y2[j][n] = a3*img[j][n+1]+a4*img[j][n+2]+b1*y2[j][n+1]+b2*y2[j][n+2];
}
for( i = 2 ; i < w-2 ; i++ )
ry[j][i] = y1[j][i]+y2[j][i];
}
for( i = 2 ; i < w-2 ; i++ )
{
for( j = 2 ; j < h-2 ; j++ )
{
y1[j][i] = ry[j-1][i]+b1*y1[j-1][i]+b2*y1[j-2][i];
m = h-1-j;
y2[m][i] = -ry[m+1][i]+b1*y2[m+1][i]+b2*y2[m+2][i];
}
for( j = 2 ; j < h-2 ; j++ )
ry[j][i] = c2*(y1[j][i]+y2[j][i]);
}
float ex,ey;
for( j = 0 ; j < h ; j++ )
{
for( i = 0 ; i < w ; i++ )
{
ex = rx[j][i]*rx[j][i];
ey = ry[j][i]*ry[j][i];
y1[j][i] = (float)sqrt(ex+ey);
/*if( y1[j][i] < 0.f )
img[j][i] = 0;
else if( y1[j][i] > 255 )
img[j][i] = 255;
else
img[j][i] = (BYTE)y1[j][i];*/
}
}
FindMax( rx, ry, y1, y2 );
Hysteresis( 10, 5, y2, y1, img );
//Hysteresis( 15, 10, y1, y2, img );
//EdgeLink( 7, y1, img );
for( j = 0 ; j < h ; j++ )
{
for( i = 0 ; i < w ; i++ )
{
if( i < 1 || i > w-2 || j < 1 || j > h-2 )
img[j][i] = 255;
else if( img[j][i] != 255 )
img[j][i] = 0;
//else
// img[j][i] = 0;
}
}
for( i = 0 ; i < h ; i++ )
{
delete [] y1[i];
delete [] y2[i];
delete [] rx[i];
delete [] ry[i];
}
delete [] y1;
delete [] y2;
delete [] rx;
delete [] ry;
//Thresholding();
}
void CEdgeDetector::Thresholding()
{
int w = m_Size.cx;
int h = m_Size.cy;
int bs = 7;
int cr = w % bs;
int rr = h % bs;
int rs = h / bs;
int cs = w / bs;
int rm, cm, rw, cw;
if(rr==0) rm = rs; // block 肮荐 (row)
else rm = rs + 1;
if(cr==0) cm = cs; // block 肮荐 (colum)
else cm = cs + 1;
int num, sum, mean;
double var;
BYTE** img = m_pImg;
int r,c,i,j;
for( r = 0 ; r < rm ; r++ )
{
if( r==rs ) rw = rr; // 付瘤阜 block 农扁
else rw = bs;
for( c = 0 ; c < cm ; c++ )
{
if( c==cs ) cw = cr; // 付瘤阜 bloack 农扁
else cw = bs;
num = cw*rw;
// sum苞 histogram 犬伏 拌魂
sum = 0;
for( j = 0 ; j < rw ; j++ )
{
for( i = 0 ; i < cw ; i++ )
{
sum += img[r*bs+j][c*bs+i];
}
}
mean = sum / num; // mean
var = 0.;
for( j = 0 ; j < rw ; j++ )
{
for( i = 0 ; i < cw ; i++ )
{
var += abs(mean-img[r*bs+j][c*bs+i]);
}
}
var /= num;
if( var < 2.5 )
{
for( j = 0 ; j < rw ; j++ )
{
for( i = 0 ; i < cw ; i++ )
{
img[r*bs+j][c*bs+i] = 255;
}
}
}
else
{
for( j = 0 ; j < rw ; j++ )
{
for( i = 0 ; i < cw ; i++ )
{
if( img[r*bs+j][c*bs+i] > mean+var )
img[r*bs+j][c*bs+i] = 0;
else
img[r*bs+j][c*bs+i] = 255;
}
}
}
}
}
}
void CEdgeDetector::Hysteresis(int sh, int sb, float** r, float** rr, BYTE** img)
{
int w = m_Size.cx;
int h = m_Size.cy;
int i,j;
for( i = 0 ; i < w ; i++ )
{
r[0][i] = -1.f;
r[1][i] = -1.f;
r[h-1][i] = -1.f;
r[h-2][i] = -1.f;
}
for( i = 0 ; i < h ; i++ )
{
r[i][0] = -1.f;
r[i][1] = -1.f;
r[i][w-1] = -1.f;
r[i][w-2] = -1.f;
}
for( j = 2 ; j < h-2 ; j++ )
{
for( i =2 ; i < w-2 ; i++ )
{
Confcont( i, j, sh, sb, r, rr, img);
}
}
}
void CEdgeDetector::Confcont(int i, int j, int sh, int sb, float **r, float **rr, BYTE** img)
{
int m;
int w = m_Size.cx;
int h = m_Size.cy;
if( i < 0 || i > w || j < 0 || j > h ) return;
if( r[j][i] >= sh )
{
img[j][i] = 255;
r[j][i] = -1.f;
sh = sb;
for( m = j-1; m < j+2 ; m++ )
{
Confcont( i-1 , m, sh, sb , r, rr, img );
Confcont( i , m, sh, sb , r, rr, img );
Confcont( i+1 , m, sh, sb , r, rr, img );
}
}
}
void CEdgeDetector::EdgeLink( int tol, float** r, BYTE** img )
{
int w = m_Size.cx;
int h = m_Size.cy;
int i,j;
int n;
int x,y;
float max;
int mx,my;
for( j = 1 ; j < h-1 ; j++ )
{
for( i = 1 ; i < w-1 ; i++ )
{
if( img[j][i] == 255 )
{
n = 0;
for( y = j-1 ; y < j+2 ; y++ )
{
for( x = i-1 ; x < i+2 ; x++ )
{
if( img[y][x] == 255 ) n++;
}
}
if( n < 3 )
{
max = -1.f;
for( y = j-1 ; y < j+2 ; y++ )
{
for( x = i-1 ; x < i+2 ; x++ )
{
if( img[y][x] == 255 ) continue;
if( r[y][x] > max )
{
max = r[y][x];
mx = x;
my = y;
}
}
}
if( max > -1.f )
{
if( fabs( r[j][i] - max ) <= tol )
{
img[my][mx] = 255;
LinkEdge( mx, my, tol, r, img );
}
}
}
}
}
}
}
void CEdgeDetector::LinkEdge( int i, int j, int tol, float** r, BYTE** img )
{
int w = m_Size.cx;
int h = m_Size.cy;
int x,y;
int n;
int mx,my;
float max;
if( i == 0 || i == w-1 || j == 0 || j == h-1 ) return;
n = 0;
for( y = j-1 ; y < j+2 ; y++ )
{
for( x = i-1 ; x < i+2 ; x++ )
{
if( img[y][x] == 255 ) n++;
}
}
if( n < 3 )
{
max = -1.f;
for( y = j-1 ; y < j+2 ; y++ )
{
for( x = i-1 ; x < i+2 ; x++ )
{
if( img[y][x] == 255 ) continue;
if( r[y][x] > max )
{
max = r[y][x];
mx = x;
my = y;
}
}
}
if( max > -1.f )
{
if( fabs( r[j][i] - max ) <= tol )
{
img[my][mx] = 255;
LinkEdge( mx, my, tol, r, img );
}
}
}
}
void CEdgeDetector::FindMax(float** rx, float** ry, float** r, float** rr)
{
/* no maxima suppression with linear interpolation */
int i,j;
int w = m_Size.cx;
int h = m_Size.cy;
float g_x,g_y,a_x,a_y,mag1,mag2;
for( j = 1 ; j < h-1 ; j++ )
{
for( i = 1 ; i < w-1 ; i++ )
{
//rr[j][i] = 0.f;
if( r[j][i] != 0 )
{
g_x = rx[j][i];
g_y = ry[j][i];
a_x = (float)fabs(g_x);
a_y = (float)fabs(g_y);
if( (g_x*g_y) > 0.0 )
{
if( a_x > a_y )
{
mag1 = r[j+1][i+1]*a_y/a_x + r[j][i+1]*(a_x-a_y)/a_x;
mag2 = r[j-1][i-1]*a_y/a_x + r[j][i-1]*(a_x-a_y)/a_x;
}
else
{
mag1 = r[j+1][i+1]*a_x/a_y + r[j+1][i]*(a_y-a_x)/a_y;
mag2 = r[j-1][i-1]*a_x/a_y + r[j-1][i]*(a_y-a_x)/a_y;
}
}
else
{
if( a_x > a_y )
{
mag1 = r[j-1][i+1]*a_y/a_x + r[j][i+1]*(a_x-a_y)/a_x;
mag2 = r[j+1][i-1]*a_y/a_x + r[j][i-1]*(a_x-a_y)/a_x;
}
else
{
mag1 = r[j-1][i+1]*a_x/a_y + r[j-1][i]*(a_y-a_x)/a_y;
mag2 = r[j+1][i-1]*a_x/a_y + r[j+1][i]*(a_y-a_x)/a_y;
}
}
}
else
rr[j][i] = 0;
if( (mag1 >= r[j][i]) || (mag2 >= r[j][i]) )
rr[j][i] = 0;
else
rr[j][i] = r[j][i];
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -