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

📄 filters.cs

📁 C#环境的车牌认别系统源代码和30张测试图片
💻 CS
📖 第 1 页 / 共 3 页
字号:
				int maxAverage=0;
				int maxX=0;
				int maxY=0;
				for (int i=0;i<(int)(nHeight/div)+1;i++) 
				{
					if (lineLabel[i]==true&&lineLabel[i+1]==true) 
					{
						for(int j=0; j < (int)(nWidth/lv)-lLenght ; ++j ) 
						{
							int average =countMatch[i,j]  +countMatch[i,j+1] +countMatch[i,j+2]
								+countMatch[i,j+3]+countMatch[i,j+4] +countMatch[i,j+5]// +countMatch[i,j+6]
								+countMatch[i+1,j]+countMatch[i+1,j+1]+countMatch[i+1,j+2]
								+countMatch[i+1,j+3]+countMatch[i+1,j+4] +countMatch[i+1,j+5];// +countMatch[i+1,j+6] ;
							average=average/(lLenght+1)/(vLenght+1);
							if (maxAverage<average) 
							{
								maxAverage=average;
								maxX=i;
								maxY=j;
							}
						}
					}
				}
                

			
				
				
				bool jx1=true,jx2=true;
				int x1=0,x2=0;
				for (int j=0;jx1||jx2;j++)
				{
					if (jx1&&lineLabel[maxX-j]==false)
					{
						jx1=false;
						x1=maxX-j;
					}
					if (jx2&&lineLabel[maxX+j]==false) 
					{
						jx2=false;
						x2=maxX+j;
					}
				}
				for (int i=0;i<x1;i++) 
				{
					lineLabel[i]=false;
				}
				for (int i=x2;i<(int)(nHeight/div)+1;i++) 
				{
					lineLabel[i]=false;
				}
					


//////////////////////////////////////////////////////////////////////////
//寻找车牌的四边
//////////////////////////////////////////////////////////////////////////
						
				// 位置调整	
				int lKZValve=(int)(maxAverage/3);
				int vKZValve=(int)(maxAverage/2.5);
				//int kz1=0,kz2=0;
				int pX1=0,pX2=0,pX3=0,pX4=0,pY1=0,pY2=0,pY3=0,pY4=0; //用于搜索边框的范围
				int pXU=0,pXD=0,pYL=0,pYR=0,pXM=0,pYM=0;
				
			



				//除去两边噪音
				bool l=true,r=true;
				pY1=maxY;
				pY4=maxY+lLenght;
				
				for (int j=1;l||r;j++) 
				{
					if (maxY-j<0&&l) 
					{
						l=false;
						//pY1=0;
					}
					else if ( l&&countMatch[maxX,maxY-j]<vKZValve&&countMatch[maxX+1,maxY-j]<vKZValve) 
					{
						if (maxY-j-2>=0&&countMatch[maxX,maxY-j-2]<vKZValve&&countMatch[maxX+1,maxY-j-2]<vKZValve) 
						{
							l=false;
							pY1=maxY-j+1;
						}
						
					}
					if (maxY+lLenght+j>(int)(nWidth/lv)&&r) 
					{
						r=false;
						pY4=(int)(nWidth/lv);
					}
					else if (r&&countMatch[maxX,maxY+lLenght+j]<vKZValve&&countMatch[maxX+1,maxY+lLenght+j]<vKZValve) 
					{
						if (maxY+lLenght+j+2<(int)(nWidth/lv)+1&&countMatch[maxX,maxY+lLenght+j+2]<vKZValve&&countMatch[maxX+1,maxY+lLenght+j+2]<vKZValve) 
						{
						
							r=false;
							pY4=maxY+lLenght+j-1;
						}
					}
				}
				pY2=(pY1+1)*lv;
				pY3=(pY4-1)*lv;
				// 进一步去除不必要的边线
				bool u=true,d=true;
				pX1=maxX;
				pX4=maxX+vLenght;
				while (u||d) 
				{
					if (u&&pX1-1<0) 
					{
						u=false;
						//pX1=0;
					}
					else if (u&&lineLabel[pX1-1]) 
					{
						bool ok=false;
						for (int j=pY1;j<=pY4;j++) 
						{
							if (pX1-1>=0&&countMatch[pX1-1,j]>lKZValve) 
							{
								ok=true;
								pX1--;
								break;
							}
						}
						if (!ok) 
						{
							u=false;
						}
					}
					else
						u=false;
					
					if (d&&pX4+1>(int)(nHeight/div)) 
					{
						d=false;
					}
					else if (d&&lineLabel[pX4+1]) 
					{
						bool ok=false;
						for (int j=pY1;j<=pY4;j++) 
						{
							if (pX4+1<(int)(nHeight/div)+1&&countMatch[pX4+1,j]>lKZValve) 
							{
								ok=true;
								pX4++;
								break;
							}
						}
						if (!ok) 
						{
							d=false;
						}
					}
					else
						d=false;
				}
				
				pXM=pX1*div+(pX4-pX1)/2*div;
				pYM=pY1*lv+(pY4-pY1)/2*lv;
				//maxX=x1;
				vLenght=x2-x1;
				//水平再调整
				l=true;r=true;
				while (l||r) 
				{
					if (pY1-1<0&&l) 
					{
						l=false;
					}
					else if(l)
					{
						bool match=false;
						for (int i=0;i<=vLenght;i++) 
						{
							if (countMatch[x1+i,pY1-1]>vKZValve) 
							{
								match=true;
								break;
							}
						}
						if (!match) 
						{
							l=false;
						}
						else 	
							pY1--;

						
					}
					if (pY4+1>(int)(nWidth/lv)&&r) 
					{
						r=false;
					}
					else  if(r)
					{
						bool match=false;
						for (int i=0;i<=vLenght;i++) 
						{
							if (countMatch[x1+i,pY4+1]>vKZValve) 
							{
								match=true;
								break;
							}
						}
						if (!match) 
						{
							r=false;
							
						}
						else
							pY4++;
					}
				}
			
				for (int i=0;i<pX1;i++) 
				{
					lineLabel[i]=false;
				}
				for (int i=pX4+1;i<(int)(nHeight/div)+1;i++) 
				{
					lineLabel[i]=false;
				}

				pX2=x1*div-div/2;
				if (pX2<0) {
					pX2=0;
				}
				pX3=x2*div+div/2;
				if (pX3>=nHeight) {
					pX3=nHeight-1;
				}
				pYL=pY1*lv;//-lv;
				bool kz=false;
				for (int i=x1;i<=x2;i++) 
				{
					if (countMatch[i,pY1]>vKZValve) 
					{
						kz=true;
						break;
					}
					if (pY1-1>=0&&countMatch[i,pY1-1]>vKZValve) 
					{
						pYL-=lv;
						break;
					}
				}
				if (kz) 
				{
					pYL-=lv/2;
				}
				if (pYL<=0) {
					pYL=0;
				}
				pYR=(pY4+1)*lv+lv/2;//+lv;
				kz=false;
				for (int i=x1;i<=x2;i++) {
					if (pY4+1<(int )(nWidth/lv)+1&& countMatch[i,pY4+1]>vKZValve) {
						kz=true;
						break;
					}
					if (pY4+2<(int )(nWidth/lv)+1&&countMatch[i,pY4+2]>vKZValve) 
					{
						pYR+=lv;
						break;
					}
				}
				if (kz) {
					pYR+=lv/2;
				}
				if (pYR>=nWidth) {
					pYR=nWidth-1;
				}
				if (pX4-pX1<=3) 
				{
					if (pX1-1>=0) 
					{
						pXU=(pX1-1)*div;
					}
					else
						pXU=0;
					if (pX4+2>=(int)(nHeight/div)) 
					{
						pXD=nHeight;
					}
					else
						pXD=(int)((pX4+1.5)*div+div);
				}
				else if (4<=pX4-pX1&&pX4-pX1<=5) 
				{
					pXU=pX1*div-div/2;
					pXD=(pX4+1)*div+div/2;
				}
				else 
					pXU=pX1*div;
				pXD=(int)((pX4+1.5)*div-div/2);

				pXD+=div/2;
				if (pXD>nHeight-1) {
					pXD=nHeight-1;
				}
				pYL-=lv/2;
				if (pYL<0) {
					pYL=0;
				}
				
				//调整截取的边缘
				LR(m,pX2,pX3,pYL,pYR,out pYL,out pYR);
				UD(m,pXU,pXD,pYL,pYR,out pXU,out pXD);


///////////////////////////////////////////////////////////////////////////
//在图像上添加辅助线
//////////////////////////////////////////////////////////////////////////	
				
				//显示边框
				p = (byte *)(void *)Scan0;
				pp = p;
				for (int i=0;i<nHeight;i++) 
				{
				
					if(i==pXU||i==pXD)
					{
						for (int j=pYL;j<=pYR;j++) 
						{
							pp=p+i*stride+j*3;
							pp[2]=255;pp[0]=pp[1]=0;
						}
					}
					else if (pXU<i&&i<pXD) 
					{
					
						pp=p+i*stride+pYL*3;
						pp[2]=255;pp[0]=pp[1]=0;

						pp=p+i*stride+pYR*3;
						pp[2]=255;pp[0]=pp[1]=0;
					}
				}

				//截取的行线显示在图上
				p = (byte *)(void *)Scan0;
				pp = p;
				for (int i=0;i<(int)(nHeight/div)-1;i++) 
				{
					//画垂线
					for (int k=0;k<nWidth+1;k+=lv) 
					{
						pp=p+(i*div+div/2)*stride+k*3;
						pp[2]=255;
					}

					//在车牌所在水平区域画出横线
					if (lineLabel[i]) 
					{
					
						for(int j=0; j < nWidth; ++j ) 
						{ 
							pp=p+(i*div+div/2)*stride+j*3;
							pp[2]=255;
						}
					}
				}
				outCount=ccm;
				outCount=maxAverage;
								
				outxu=pXU;
				outxd=pXD;
				outyl=pYL;
				outyr=pYR;
				outMaxX=maxX*div-pXU;
				outMaxY=maxY*lv-pYL;
			}
			outGray = newGray;

			b.UnlockBits(bmData); 

			return true; 
		}

		

		/*
		 * 调整车牌左右位置
		 */
		private static bool  LR( float[,] m, int xu,int xd,int yl,int yr,out int pYL,out int pYR)
		{
			int[] projection=new int[yr-yl+1];
			foreach (int i in projection)
			{
				projection[i]=0;
			}
			//垂直投影
			for (int i=xu;i<=xd;i++) 
			{
				for (int j=yl;j<=yr;j++) 
				{
					if (m[i,j]>0) 
					{
						projection[j-yl]++;
					}
				}
			}
			bool l=true,r=true;
			int temp_yr=yr,temp_yl=yl;
			while (l||r) 
			{
				if (temp_yr-temp_yl<=60) 
				{
					l=r=false;
				}
				if (l&&projection[temp_yl-yl]<5){
					temp_yl++;
				}
				else 
				{
					l=false;
				}
				
				if (r&&projection[temp_yr-yl]<5)
				{
					temp_yr--;
				}
				else 
				{
					r=false;
				}	
			}

			pYL=temp_yl;
			pYR=temp_yr;

			return true;
		}
	
	
	
		/*
		 * 调整车牌上下位置
		 */
		private static bool UD(float[,] m,int pXU,int pXD,int pYL,int pYR,out int  xu,out int xd)
		{
			int[] projection=new int[pXD-pXU+1];
			foreach (int i in projection)
			{
				projection[i]=0;
			}
			//水平投影
			for (int i=pXU;i<=pXD;i++) {
				for (int j=pYL;j<=pYR;j++) {
					if (m[i,j]>0) 
					{
						projection[i-pXU]++;
					}
				}
			}
			bool u=true,d=true;
			int temp_xd=pXD-1,temp_xu=pXU+1;
			while (u||d) 
			{
				if (temp_xd-temp_xu<=60) 
				{
					u=d=false;
				}
				if (u&&projection[temp_xu-pXU]<2)
				{
					temp_xu++;
				}
				else 
				{
					u=false;
				}
				
				if (d&&projection[temp_xd-pXU]<2)
				{
					temp_xd--;
				}
				else 
				{
					d=false;
				}	
			}
			xu=temp_xu;

			xd=temp_xd;

			return true;
		}

		
		/*
		 * 对车牌图像二值化
		 */
		public static bool TowValue(Bitmap b,Bitmap c_Bitmap, int maxX,int maxY)
		{ 
			
			int[] c_gray=new int[256];
			int[] c_r=new int[256];
			int[] c_g=new int[256];
			int[] c_b=new int[256];

			zft(b,out c_gray,out c_r,out c_g,out c_b);
			//获取车牌小区域的灰度阶

			int Mr=0;//灰度均值
			long sum=0;
			int count=0;
			for (int i=0;i<256;i++) {
				sum+=c_gray[i]*i;
				count+=c_gray[i];
			}
			Mr=(int)(sum /count);
			int sum1=0;
			int count1=0;
			for (int i=0;i<=Mr;i++) {
				sum1+=c_gray[i]*i;
				count1+=c_gray[i];
			}
			int g1=sum1/count1;

			int sum2=0;
			int count2=0;
			for (int i=Mr;i<=255;i++) 
			{
				sum2+=c_gray[i]*i;
				count2+=c_gray[i];
			}
			int g2=sum2/count2;
			
			//求阀值
			int va;
			if (count1<count2) {//白底黑字
				va=Mr-count1/count2*Math.Abs(g1-Mr);
			}
			else                //黑底白字
				va=Mr+count2/count1*Math.Abs(g2-Mr);

			//对图像二值化
			BitmapData bmData =  b.LockBits(new Rectangle(0, 0,b.Width , b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);				
			unsafe
			{
				int stride = bmData.Stride;
				System.IntPtr Scan0 = bmData.Scan0;   
				byte * p = (byte *)(void *)Scan0;
				int nOffset = stride - b.Width*3;    
    
				int nWidth=b.Width;
				int nHeight=b.Height;

				
				for(int y=0;y < nHeight;++y)
				{ 
					for(int x=0; x < nWidth; ++x ) 
					{
						if (p[0]>va) 
						{
							p[0]=p[1]=p[2]=255;
						}
						else
							p[0]=p[1]=p[2]=0;

						p+=3; 
					} 
					p += nOffset; 

				} 
				
			}
			b.UnlockBits(bmData); 

			return true; 

		}
	}
}

⌨️ 快捷键说明

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