⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edgedetector.cpp

📁 很珍贵得视频编辑器原码及CODEC。需要安装下列CODEC.可播放多种格式的视频
💻 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 + -