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

📄 dipview.cpp

📁 使用OpenCV和C++实现的车牌识别系统
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
	int row=0;
	int col=0;

	float alph=0.0;
	int*E=new int[width];
	long double*MSE=new long double[9];                         //针对每一个alph的deltl;	

	//统计各列白象素个数
	for(col=0;col<width;col++)
	{
		for(row=0;row<height;row++)
		{	
			if(DisposeImg[row*width+col]==255)
				projArray[col]++;		
		}	
	}

	//一次平滑
	for(int x=1;x<10;x++)
	{
		alph=(float)(0.1*x);
		E[0]=projArray[0];
		for(col=1;col<width;col++)
		{
			E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
		}

		for(col=0;col<width;col++)
		{
			MSE[x-1]+=(projArray[col]-E[col])*(projArray[col]-E[col]);
		}
		MSE[x-1]=MSE[x-1]/width;
	}

	long double min=0.0;
	for(x=1;x<10;x++)
	{
		if(MSE[x-1]>min)
		{
			min=MSE[x-1];
		}
	}
	for(x=1;x<10;x++)
	{
		if(MSE[x-1]==min)
		{
			alph=(float)(0.1*x);
		}
	}
		
	E[0]=projArray[0];
	for(col=1;col<width;col++)
	{
		E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
	}	

	for(col=1;col<width;col++)
	{
		projArray[col]=E[col];
		E[col]=0;
	}

	//二次平滑
	for(x=1;x<10;x++)
	{
		alph=(float)(0.1*x);
		E[0]=projArray[0];
		for(col=1;col<width;col++)
		{
			E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
		}

		for(col=0;col<width;col++)
		{
			MSE[x-1]+=(projArray[col]-E[col])*(projArray[col]-E[col]);
		}
		MSE[x-1]=MSE[x-1]/width;
	}

	min=0.0;
	for(x=1;x<10;x++)
	{
		if(MSE[x-1]<min)
		{
			min=MSE[x-1];
		}
	}
	for(x=1;x<10;x++)
	{
		if(MSE[x-1]==min)
		{
			alph=(float)(0.1*x);
		}
	}

	E[0]=projArray[0];
	for(col=1;col<width;col++)
	{
		E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
	}	
	for(col=1;col<width;col++)
	{
		projArray[col]=E[col];
		E[col]=0;
	}

    //寻找波谷进行分割trough	
	FindTrough(projArray,width);								//获得波谷位置	

	free(E);
	free(MSE);	
}

// 寻找波谷,划分字符区间
void CDipView::FindTrough(int* Array, int size)
{
	int col=0;
	bool*flage=new bool[size];

	bool LFlage=false;                                //a wave start leftside
	bool RFlage=false;                                //a wave end   rightside
	int  LSide=0;                                     //left side
	int  RSide=0;									  //right side
	int  length=0;                                    //area width

	for(col=0;col<size;col++)
	{
		flage[col]=false;
	}

	for(col=1;col<size-1;col++)
	{
		if(Array[col]==0&&Array[col+1]!=0&&LFlage==false)
		{
			flage[col]=true;
			LFlage=true;
		}
		if((Array[col-1]!=0)&&(Array[col]==0)&&(LFlage==true)&&(RFlage==false))
		{
			flage[col]=true;
			RFlage=true;
		}
		if((LFlage==true)&&(RFlage==true))
		{
			LFlage=false;
			RFlage=false;
		}
	}

	for(col=0;col<size;col++)
	{
		Array[col]=0;
		if(flage[col]==true)
		{
			Array[col]=1;
		}
	}
}

// 分割字符
void CDipView::CharacterSplit(int* Array, int size)
{
	CDipDoc *pDoc=GetDocument();

	int width,height;
	width=pDoc->ImgWidth;
	height=pDoc->ImgHeight;	

    int x=Rect_X[0];
	int y=Rect_Y[0];
	int w=Rect_W[0];
	int h=Rect_H[0];

    int num=0;

	for(num=0;num<10;num++)
	{
		cRects[num].x=-1;
		cRects[num].y=-1;
		cRects[num].w=0;
		cRects[num].h=0;
	}

	bool flage=false;
	

	int row=0;
	int col=0;

	int area=0;
	num=0;
	for(col=0;col<size;col++)
	{
		if(Array[col]==1)
		{
			num++;
			if(num%2!=0&&flage==false)
			{	
				
				flage=true;			
				cRects[area].x=x+col;				
			}
			else if(num%2==0&&flage==true)
			{	
				flage=false;						
				cRects[area].w=col-(cRects[area].x-x);
				cRects[area].y=y;
				cRects[area].h=h;
				area++;							
			}
		}
	}

	CharacterNum=area;
	
//	CharacterNum=area+1;

	for(;area>=0;area--)
	{
		if(cRects[area].w!=0)
		{
			for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line
			{
				pDoc->ImgData[row*width+cRects[area].x-1]=255;
				pDoc->ImgData[row*width+(cRects[area].x+cRects[area].w)]=255;	
			}

			for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line
			{
				pDoc->ImgData[(cRects[area].y-1)*width+col]=255;
				pDoc->ImgData[(cRects[area].y+cRects[area].h)*width+col]=255;
			}	
		}				
	}

	//save character
    for(area=CharacterNum;area>=0;area--)
	{
		cDatas[area].w=cRects[area].w;
		cDatas[area].h=cRects[area].h;
		cDatas[area].Img=new BYTE[cRects[area].w*cRects[area].h];

		for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line
		{
			for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line
			{
				cDatas[area].Img[(row-cRects[area].y)*cRects[area].w+(col-cRects[area].x)]=pDoc->ImgData[row*width+col];			
			}				
		}	
	}
}
/*
// 读取样本库,传入一个sample类型的数组(从文件里读出的样本数据将放入其中),返回值为样本个数
int CDipView::LoadCharLib(sample* sa)
{
	CFile cf;	
	
	if(cf.Open(".\\mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
	{
		AfxMessageBox("打开文件失败,\n您最好退出程序");
	}

	int num=0;
	try
	{
		sample sampleTemp;
		
		cf.SeekToBegin();
		DWORD dwBytesRemaining=(DWORD)(cf.GetLength());
		while(dwBytesRemaining)
		{
			UINT nBytesRead=cf.Read(&sampleTemp,sizeof(sample));
			sa[num]=sampleTemp;
			dwBytesRemaining-=nBytesRead;
			num++;
		}
		CString s;
//		s.Format("共读取数据%d个,最后一个的序列号为%d",
//			num,sampleTemp.serialnum);
//		AfxMessageBox(s);	
	}
	catch(CFileException *e)
	{
		e->ReportError();
		e->Delete();
	}
	cf.Close();
	return num;
}

// 缩放算法,一律缩放为20*36
void CDipView::Zoom(BYTE* DisposeImg, int width, int height)
{
	if ((width==20)&&(height==36))
	return;
	
	// 源图像的宽度和高度
	LONG	lWidth=width;
	LONG	lHeight=height;
	
	BYTE *temp_img=new BYTE[width*height];
	
	// 循环变量
	int	i;
	int	j;
	
	for(i = 0; i < height; i++)
	{
		for(j = 0; j < width; j++)
		{			
			temp_img[j+i*width]=DisposeImg[j+i*width];
		}
	}

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

	float XZRatio=(float)( 20.0/(float)(width));
	float YZRatio=(float)(36.0/(float)(height));

	// 象素在源坐标
	LONG	i0;
	LONG	j0;
	
	//归一后的大小
	lNewWidth = 20;
	lNewHeight = 36;
	
	height=lNewHeight;
	width=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);
			
			// 判断是否在源图范围内
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
			{
				// 复制象素
				DisposeImg[j+i*lWidth] = temp_img[j0 + i0*lWidth];			
			}
			else
			{
				// 对于源图中没有的象素,直接赋值为255				
		//		DisposeImg[j+i*lWidth] = 0;
			}			
		}		
	}
	delete [] temp_img;
}

// 二值化算法,二值化为0和1两种值
void CDipView::BinaryImg(BYTE* DisposeImg, int width , int height)
{
	 BYTE *temp=new BYTE[height*width];
	 int x,y;	

	 CopyImg(DisposeImg,temp,width,height);
	
	 long double total=0;
	 float aver=0;
	 for(x=0;x<height;x++)
	 {
		 for(y=0;y<width;y++)
		 {	
			 total+=DisposeImg[x*width+y];			
		 }
	 }
	 aver=(BYTE)(total/(float)(height*width));

	 float delt; 
	 float sub=0; 
	 for(x=0;x<height;x++)
	 {
		 for(y=0;y<width;y++)
		 {			
			 sub+=(DisposeImg[x*width+y]-aver)*(DisposeImg[x*width+y]-aver);			 
		 }
	 }
	 delt=(float)(sqrt(sub/(float)(height*width)));

	 BYTE judge;
	 judge=(BYTE)(delt+aver);
	 for(x=0;x<height;x++)
	 {
		for(y=0;y<width;y++)
		 {
			if(DisposeImg[(x*width)+y]>=judge)
			{
				DisposeImg[(x*width)+y]=(BYTE)1;
			}
			else
			{
				DisposeImg[(x*width)+y]=(BYTE)0;
			}
		}
	 }
	 
	 free(temp);	
}

// Hilditch细化算法
void CDipView::ThinnerHilditch(void* image, unsigned long lx, unsigned long ly)
{
	char *f, *g;
	char n[10];
	unsigned int counter;
	short k, shori, xx, nrn;
	unsigned long i, j;
	long kk, kk11, kk12, kk13, kk21, kk22, kk23, kk31, kk32, kk33, size;
	size = (long)lx * (long)ly;
	g = (char *)malloc(size);

	if(g == NULL)
	{
		printf("error in allocating memory!\n");
		return;
	}

	f = (char *)image;
	for(i=0; i<lx; i++)
	{
		for(j=0; j<ly; j++)
		{
			kk=i*ly+j;
			if(f[kk]!=0)
			{
				f[kk]=1;
				g[kk]=f[kk];
			}
		}
	}

	counter = 1;

	do
	{
		printf("%4d*",counter);
		counter++;
		shori = 0;

		for(i=0; i<lx; i++)
		{
			for(j=0; j<ly; j++)
			{
				kk = i*ly+j;
				if(f[kk]<0)
					f[kk] = 0;
				g[kk]= f[kk];
			}
		}

		for(i=1; i<lx-1; i++)
		{
			for(j=1; j<ly-1; j++)
			{
				kk=i*ly+j;

				if(f[kk]!=1)
					continue;

				kk11 = (i-1)*ly+j-1;
				kk12 = kk11 + 1;
				kk13 = kk12 + 1;
				kk21 = i*ly+j-1;
				kk22 = kk21 + 1;
				kk23 = kk22 + 1;
				kk31 = (i+1)*ly+j-1;
				kk32 = kk31 + 1;
				kk33 = kk32 + 1;

				if((g[kk12]&&g[kk21]&&g[kk23]&&g[kk32])!=0)
					continue;

				nrn = g[kk11] + g[kk12] + g[kk13] + g[kk21] + g[kk23] + 
					g[kk31] + g[kk32] + g[kk33];

				if(nrn <= 1)
				{
					f[kk22] = 2;
					continue;
				}

				n[4] = f[kk11];
				n[3] = f[kk12];
				n[2] = f[kk13];
				n[5] = f[kk21];
				n[1] = f[kk23];
				n[6] = f[kk31];
				n[7] = f[kk32];
				n[8] = f[kk33];
				n[9] = n[1];
				xx = 0;

				for(k=1; k<8; k=k+2)
				{
					if((!n[k])&&(n[k+1]||n[k+2]))
						xx++;
				}

				if(xx!=1)
				{
					f[kk22] = 2;
					continue;
				}

				if(f[kk12] == -1)
				{
					f[kk12] = 0;
					n[3] = 0;
					xx = 0;

					for(k=1; k<8; k=k+2)
					{
						if((!n[k])&&(n[k+1]||n[k+2]))
							xx++;
					}

					if(xx != 1)
					{
						f[kk12] = -1;
						continue;
					}

					f[kk12] = -1;
					n[3] = -1;
				}

				if(f[kk21]!=-1)
				{
					f[kk22] = -1;
					shori = 1;
					continue;
				}

				f[kk21] = 0;
				n[5] = 0;
				xx = 0;

				for(k=1; k<8; k=k+2)
				{
					if((!n[k])&&(n[k+1]||n[k+2]))
					{
						xx++;
					}
				}

				if(xx == 1)
				{
					f[kk21] = -1;
					f[kk22] = -1;
					shori =1;
				}
				else
					f[kk21] = -1;
			}
		}
	}while(shori);

	free(g);
}

// 细化算法
void CDipView::ThinImage(BYTE* image, int width, int height)
{
	LONG x,y,k;
	BYTE image1[10000];
	k=0;
	
	LONG digitWidth = width;
	LONG digitHeight = height;

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

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

	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			image1[k] = image[x*width+y];
			if(image1[k] != 0)
				image1[k] = (BYTE)1;
			k++;
		}
	}

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

	k=0;
	for(x=0; x<digitWidth; x++)
	{
		for(y=0; y<digitHeight; y++)
		{
			image[x*width+y] = image1[k];
			if(image[x*width+y]!=0)
				image[x*width+y] = (BYTE)1;
			k++;
		}
	}
}

// 获取特征

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -