www.gusucode.com > VC图像处理-车牌识别系统源程序源码程序 > VC图像处理-车牌识别系统源程序源码程序/code/DigitClass.cpp

    // DigitClass.cpp: implementation of the CDigitClass class.
// Download by http://www.NewXing.com
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "DigitClass.h"
#include "Thinner.h"
//#include "dib.h"
#include "math.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDigitClass::CDigitClass()
{

}

CDigitClass::~CDigitClass()
{

}

/*void CDigitClass::CopyArToBitmap(void)
{
	LONG x, y;
	digitWidth = digitdib.GetWidth();
	digitHeight = digitdib.GetHeight();
	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitdib.SetPixel8(x, y, digitarray[x][y]);
			//digitdib.SetPixel8(x, y, 0);
		}
	}
}

void CDigitClass::CopyBitmapToAr(void)
{
	LONG x, y;
	digitWidth = digitdib.GetWidth();
	digitHeight = digitdib.GetHeight();

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray[x][y] = digitdib.GetPixel8(x, y);
			TRACE("%d ",digitdib.GetPixel8(x, y));
		}
	}
}*/

void CDigitClass::BinaryDigit(BYTE thre)
{
//	digitWidth = digitdib.GetWidth();
//	digitHeight = digitdib.GetHeight();

	LONG x, y;

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			if(digitarray[x][y] >= thre)
				digitarray[x][y]=(BYTE)1;
			else
				digitarray[x][y]=(BYTE)0;
		}
	}
}

void CDigitClass::BinaryDigit()
{
    int x,y;	
	int k=0;

	long double total=0;
	float aver=0;

	for(x=0;x<digitWidth;x++)
	{
		for(y=0;y<digitHeight;y++)
		{	
			total+=digitarray[x][y];	
		}
	}
	aver=(BYTE)(total/(float)(digitWidth*digitHeight));
	
	float delt; 
	float sub=0; 
	for(x=0;x<digitWidth;x++)
	{
		for(y=0;y<digitHeight;y++)
		{			
			sub+=(digitarray[x][y]-aver)*(digitarray[x][y]-aver);			 
		}
	}
	delt=(float)(sqrt(sub/(float)(digitWidth*digitHeight)));
	
	BYTE judge;
	judge=(BYTE)(delt+aver);
	for(x=0;x<digitWidth;x++)
	{
		for(y=0;y<digitHeight;y++)
		{
			if(digitarray[x][y]>=judge)
			{
				digitarray[x][y]=1;
			}
			else
			{
				digitarray[x][y]=0;
			}
		}
	}
}


void CDigitClass::ThinDigit_1()
{
	LONG x,y,k;
	k=0;

//	digitWidth = digitdib.GetWidth();
//	digitHeight = digitdib.GetHeight();

	for(x=0; x<digitWidth; x++)
	{
		digitarray[x][0] = (BYTE)0;
		digitarray[x][digitHeight-1] = (BYTE)0;
	}

	for(y=0; y<digitHeight; y++)
	{
		digitarray[0][y] = (BYTE)0;
		digitarray[digitWidth-1][y] = (BYTE)0;
	}

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray1[k] = digitarray[x][y];
			if(digitarray1[k] != 0)
				digitarray1[k] = (BYTE)1;
			k++;
		}
	}

	ThinnerHilditch((void *)digitarray1, digitWidth, digitHeight);

	k=0;
	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray[x][y] = digitarray1[k];
			if(digitarray[x][y]!=0)
				digitarray[x][y] = (BYTE)1;
			k++;
		}
	}
}

void CDigitClass::ThinDigit_2()
{
	LONG x,y,k;
	k=0;

//	digitWidth = digitdib.GetWidth();
//	digitHeight = digitdib.GetHeight();

	for(x=0; x<digitWidth; x++)
	{
		digitarray[x][0] = (BYTE)0;
		digitarray[x][digitHeight-1] = (BYTE)0;
	}

	for(y=0; y<digitHeight; y++)
	{
		digitarray[0][y] = (BYTE)0;
		digitarray[digitWidth-1][y] = (BYTE)0;
	}

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray1[k] = digitarray[x][y];
			if(digitarray1[k] != 0)
				digitarray1[k] = (BYTE)1;
			k++;
		}
	}

	ThinnerPavlidis((void *)digitarray1, digitWidth, digitHeight);

	k=0;
	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray[x][y] = digitarray1[k];
			if(digitarray[x][y]!=0)
				digitarray[x][y] = (BYTE)1;
			k++;
		}
	}
}

void CDigitClass::ThinDigit_3()
{
	LONG x,y,k;
	k=0;

//	digitWidth = digitdib.GetWidth();
//	digitHeight = digitdib.GetHeight();

	for(x=0; x<digitWidth; x++)
	{
		digitarray[x][0] = (BYTE)0;
		digitarray[x][digitHeight-1] = (BYTE)0;
	}

	for(y=0; y<digitHeight; y++)
	{
		digitarray[0][y] = (BYTE)0;
		digitarray[digitWidth-1][y] = (BYTE)0;
	}

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray1[k] = digitarray[x][y];
			if(digitarray1[k] != 0)
				digitarray1[k] = (BYTE)1;
			k++;
		}
	}

	ThinnerHilditch((void *)digitarray1, digitWidth, digitHeight);

	k=0;
	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray[x][y] = digitarray1[k];
			if(digitarray[x][y]!=0)
				digitarray[x][y] = (BYTE)1;
			k++;
		}
	}
}

void CDigitClass::ThinDigit_4()
{
	LONG x,y,k;
	k=0;

//	digitWidth = digitdib.GetWidth();
//	digitHeight = digitdib.GetHeight();
	
	for(x=0; x<digitWidth; x++)
	{
		digitarray[x][0] = (BYTE)0;
		digitarray[x][digitHeight-1] = (BYTE)0;
	}

	for(y=0; y<digitHeight; y++)
	{
		digitarray[0][y] = (BYTE)0;
		digitarray[digitWidth-1][y] = (BYTE)0;
	}

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray1[k] = digitarray[x][y];
			if(digitarray1[k] != 0)
				digitarray1[k] = (BYTE)1;
			k++;
		}
	}

	ThiningDIBSkeleton((LPSTR)digitarray1, digitHeight, digitWidth);

	k=0;
	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			digitarray[x][y] = digitarray1[k];
			if(digitarray[x][y]!=0)
				digitarray[x][y] = (BYTE)1;
			k++;
		}
	}
}

void CDigitClass::GetFeature()
{
	int i,j;
	for(i=0; i<13; i++)
		feature[i] = 0;

	//图象是20×36大小的,分成9块

	//第一块
	for(i=0; i<7; i++)
	{
		for(j=0; j<12; j++)
		{
			if(digitarray[i][j]==1)
				feature[0]+=1.0;
		}
	}

	//第二块
	for(i=0; i<7; i++)
	{
		for(j=12; j<24; j++)
		{
			if(digitarray[i][j]==1)
				feature[1]+=1.0;
		}
	}

	//第三块
	for(i=0; i<7; i++)
	{
		for(j=24; j<36; j++)
		{
			if(digitarray[i][j]==1)
				feature[2]+=1.0;
		}
	}

	//第四块
	for(i=7; i<13; i++)
	{
		for(j=0; j<12; j++)
		{
			if(digitarray[i][j]==1)
				feature[3]+=1.0;
		}
	}

	//第五块
	for(i=7; i<13; i++)
	{
		for(j=12; j<24; j++)
		{
			if(digitarray[i][j]==1)
				feature[4]+=1.0;
		}
	}

	//第六块
	for(i=7; i<13; i++)
	{
		for(j=24; j<36; j++)
		{
			if(digitarray[i][j]==1)
				feature[5]+=1.0;
		}
	}

	//第七块
	for(i=13; i<20; i++)
	{
		for(j=0; j<12; j++)
		{
			if(digitarray[i][j]==1)
				feature[6]+=1.0;
		}
	}

	//第八块
	for(i=13; i<20; i++)
	{
		for(j=12; j<24; j++)
		{
			if(digitarray[i][j]==1)
				feature[7]+=1.0;
		}
	}

	//第九块
	for(i=13; i<20; i++)
	{
		for(j=24; j<36; j++)
		{
			if(digitarray[i][j]==1)
				feature[8]+=1.0;
		}
	}

	//下面统计方向交点特征

	for(j=0; j<36; j++)
	{
		if(digitarray[7][j]==1)
			feature[9]+=1.0;
	}

	for(j=0; j<36; j++)
	{
		if(digitarray[13][j]==1)
			feature[10]+=1.0;
	}

	for(i=0; i<20; i++)
	{
		if(digitarray[i][12]==1)
			feature[11]+=1.0;
	}

	for(i=0; i<20; i++)
	{
		if(digitarray[i][24]==1)
			feature[12]+=1.0;
	}
}

void CDigitClass::FixSize()
{
	if(digitWidth==20&&digitHeight==36)
		return;
	
	LONG	lWidth=digitWidth;
	// 源图像的宽度和高度
	LONG	lHeight=digitHeight;
	
	BYTE *temp_img=new BYTE[lWidth*lHeight];
	
	// 循环变量
	LONG	i;
	LONG	j;

	//memcpy(temp_img,digitarray,lWidth*lHeight);
	for(i = 0; i < digitHeight; i++)
	{
		for(j = 0; j < digitWidth; j++)
		{
			
			temp_img[i*digitWidth+j]=digitarray[j][i];
		}
	}

// 缩放后图像的宽度和高度
	LONG	lNewWidth;
	LONG	lNewHeight;

	float XZRatio=(float) 20/digitWidth;
	float YZRatio=(float) 36/digitHeight;

//	float XZRatio=(float) digitWidth/20;
//	float YZRatio=(float) digitHeight/36;


//	lNewWidth = (LONG) (lWidth * XZRatio + 0.5);
//	lNewHeight = (LONG) (lHeight * YZRatio + 0.5);

	
	
	// 象素在源坐标
	LONG	i0;
	LONG	j0;
	
	//归一后的大小
	lNewWidth = 20;
	lNewHeight = 36;
	
	digitHeight=lNewHeight;
	digitWidth=lNewWidth;


	for(i = 0; i < lNewHeight; i++)
	{
		
		for(j = 0; j < lNewWidth; j++)
		{
			i0 = (LONG) (i / YZRatio + 0.5);
			j0 = (LONG) (j / XZRatio + 0.5);
			
			digitarray[j][i]=Interpolation(temp_img,lWidth,lHeight,j0,i0);
/*			

  
			// 判断是否在源图范围内
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
			{
				// 复制象素
				digitarray[j][i] = temp_img[lHeight * j0 + i0];
			
			}
			else
			{
				// 对于源图中没有的象素,直接赋值为255
				//digitarray[j][i] = 255;
				digitarray[j][i] = 0;
			}*/
			
		}
		
	}
	delete [] temp_img;
}

void CDigitClass::FixSize1()
{
	if(digitWidth==20&&digitHeight==36)
		return;
	
	// 源图像的宽度和高度
	LONG	lWidth=digitWidth;
	LONG	lHeight=digitHeight;
	
	BYTE *temp_img=new BYTE[lWidth*lHeight];
	
	// 循环变量
	LONG	i;
	LONG	j;

	//memcpy(temp_img,digitarray,lWidth*lHeight);
	for(i = 0; i < digitHeight; i++)
	{
		for(j = 0; j < digitWidth; j++)
		{
			
			temp_img[j*digitHeight+i]=digitarray[j][i];
		}
	}
		// 缩放后图像的宽度和高度
	LONG	lNewWidth;
	LONG	lNewHeight;

	float XZRatio=(float) 20/digitWidth;
	float YZRatio=(float) 36/digitHeight;

	

	// 象素在源坐标
	LONG	i0;
	LONG	j0;
	
	// 计算缩放后的图像实际宽度
	// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
	lNewWidth = (LONG) (lWidth * XZRatio + 0.5);
	
	// 计算缩放后的图像高度
	lNewHeight = (LONG) (lHeight * YZRatio + 0.5);


	for(i = 0; i < lNewHeight; i++)
	{
		
		for(j = 0; j < lNewWidth; j++)
		{
			i0 = (LONG) (i / YZRatio + 0.5);
			j0 = (LONG) (j / XZRatio + 0.5);
			
			// 判断是否在源图范围内
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 <lHeight ))
			{
				// 复制象素
				digitarray[j][i] = temp_img[lHeight * j0 + i0];
			}
			else
			{
				// 对于源图中没有的象素,直接赋值为255
				digitarray[j][i] = 255;
			}
			
		}
		
	}
	digitHeight=lNewHeight;
	digitWidth=lNewWidth;

	delete [] temp_img;
}

float CDigitClass::Marroperator(float dr, int x, int y)
{
	double a=(float) (-2.0/3.1415926/dr/dr/dr/dr);
	a=a*(1-(x*x+y*y)/2.0/dr/dr);
	double b=-(double)((x*x+y*y)/2.0/dr/dr);
	b=(double)(exp(b));
	a=a*b;
	return (float)(12.0*a);
}



void CDigitClass::MarrBinary()
{
	float *temp=NULL;
	float *Temp=NULL;
	int i,j;
	temp=new float[digitWidth*digitHeight];
	memset(temp,255,digitWidth*digitHeight*sizeof(float));
	Temp=temp;
	float dr=(float) 1.6;
	float Marr[9][9];
	for(int x=-4;x<=4;x++)
	{
		for(int y=-4;y<=4;y++)
		{
			float result=(float)(-Marroperator(dr,x,y));
			Marr[x+4][y+4]=result;
		}
	}

	for(i=4;i<digitHeight-4;i++)
	{
		for(j=4;j<digitWidth-4;j++)
		{
			Temp[i*digitWidth+j]=0;
			for(int di=-4;di<4;di++)
			{
				for(int dj=-4;dj<4;dj++)
				{
					Temp[i*digitWidth+j]+=
						Marr[4+di][4+dj]*(float)digitarray[j+dj][i+di];
				}
			}
		}
	}

	for(i=0;i<digitHeight;i++)
	{
		for(j=0;j<digitWidth;j++)
		{
			digitarray[j][i]=Temp[i*digitWidth+j]>0?1:0;
		}
	}
	delete [] temp;



}

BYTE CDigitClass::Interpolation(BYTE *image, LONG lWidth, LONG lHeight, FLOAT x, FLOAT y)
{
	// 四个最临近象素的坐标(i1, j1), (i2, j1), (i1, j2), (i2, j2)
	LONG	i1, i2;
	LONG	j1, j2;
	
	// 四个最临近象素值
	BYTE	f1, f2, f3, f4;
	
	// 二个插值中间值
	BYTE	f12, f34;
	
	// 定义一个值,当象素坐标相差小于改值时认为坐标相同
	FLOAT			EXP;
	
	// 赋值
	EXP = (FLOAT) 0.0001;
	
	// 计算四个最临近象素的坐标
	i1 = (LONG) x;
	i2 = i1 + 1;
	j1 = (LONG) y;
	j2 = j1 + 1;
	
	// 根据不同情况分别处理
	if( (x < 0) || (x > lWidth - 1) || (y < 0) || (y > lHeight - 1))
	{
		// 要计算的点不在源图范围内,直接返回255。
		return 255;
	}
	else
	{
		if (fabs(x - lWidth + 1) <= EXP)
		{
			// 要计算的点在图像右边缘上
			if (fabs(y - lHeight + 1) <= EXP)
			{
				// 要计算的点正好是图像最右下角那一个象素,直接返回该点象素值
				f1 = (BYTE) image[lWidth * j1 + i1];
				return f1;
			}
			else
			{
				// 在图像右边缘上且不是最后一点,直接一次插值即可
				f1 = (BYTE)image[lWidth * j1 + i1];
				f3 = (BYTE)image[lWidth * j1 + i2];
				
				// 返回插值结果
				return ((BYTE) (f1 + (y -j1) * (f3 - f1)));
			}
		}
		else if (fabs(y - lHeight + 1) <= EXP)
		{
			// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可
			f1 = (BYTE)image[lWidth * j1 + i1];
			f2 = (BYTE)image[lWidth * j2 + i1];
			
			// 返回插值结果
			return ((BYTE) (f1 + (x -i1) * (f2 - f1)));
		}
		else
		{
			// 计算四个最临近象素值
			f1 = (BYTE) image[lWidth * j1 + i1];
			f2 = (BYTE) image[lWidth * j2 + i1];
			f3 = (BYTE) image[lWidth * j1 + i2];
			f4 = (BYTE) image[lWidth * j2 + i2];
			
			// 插值1
			f12 = (BYTE) (f1 + (x - i1) * (f2 - f1));
			
			// 插值2
			f34 = (BYTE) (f3 + (x - i1) * (f4 - f3));
			
			// 插值3
			return ((BYTE) (f12 + (y -j1) * (f34 - f12)));
		}
	}

}