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

📄 filters.cs

📁 C#环境的车牌认别系统源代码和30张测试图片
💻 CS
📖 第 1 页 / 共 3 页
字号:
											dividend+=15;
										}
										else if (pp[0]>210) 
										{
											sum+=pp[0]*10;
											dividend+=10;
										}
										else if (p[0]>200) 
										{
											sum+=pp[0]*5;
											dividend+=5;
										}
										
										
									}
									
									pp=p;
								}
							sum=sum/dividend;
							if (sum>255) 
							{
								sum = 255;
							}
						
							p[0]=p[1]=p[2]=(byte)(sum);
						  
				
						}
						tt = p[0];
						newGray[tt]++;
						p+=3; 

					} 

					p += nOffset; 

				} 
				
			}
			outGray = newGray;

			b.UnlockBits(bmData); 

			return true; 
		}
	

		
	
	    /*
		 * 定位车牌位置
		 */
		public static bool MarginalFilter(Bitmap b,out int[] outGray,out int outCount,float valve,out int outxu,out int outxd,out int outyl,out int outyr,out int outMaxX,out int outMaxY)

		{
			BitmapData bmData =  b.LockBits(new Rectangle(0, 0,b.Width , b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
				
			int[] newGray = new int[256];

			foreach(int i in newGray)
			{
				newGray[i]=0;
			}
			
			unsafe
			{
				int stride = bmData.Stride;
				System.IntPtr Scan0 = bmData.Scan0;   
				byte * p = (byte *)(void *)Scan0;
				byte * pp;
				int tt;
				int nOffset = stride - b.Width*3;    
    
				int nWidth=b.Width;
				int nHeight=b.Height;
				int Sx = 0;
				int Sy = 0;
				//	float max = 0;
				double sumM = 0;
				double sumCount = 0;
				//sobel模板
				int[] marginalMx = {-1,0,1,-2,0,2,-1,0,1};
				int[] marginalMy = {1,2,1,0,0,0,-1,-2,-1};


				float[,] m = new float[nHeight,nWidth];
				int[,] dlta = new int[nHeight,nWidth];
				
				int div=7;
				int lv=11;

				long sM=0;
				int ccm=0;
				int pWR,pWL,pWHL,pWHR,pWH;

				int Wmin = 1 ;
				int Wmax = 9 ;
				int Bmin = 1 ;
				int Bmax = 5 ;
				bool getStart ;
				bool[] lineLabel= new bool[(int)(nHeight/div)+1];
				double[] sumC= new double[(int)(nHeight/div)+1];
				int[,] countMatch = new int[(int)(nHeight/div)+1,(int)(nWidth/lv)+1];

				int[,] mark = new int[(int)(nHeight/div)+1,nWidth];

				

				
//////////////////////////////////////////////////////////////////////////
//获取图像边缘 并且二值化
//////////////////////////////////////////////////////////////////////////
			
				//sobel算子
				for(int y=0;y < nHeight;++y)
				{ 
					for(int x=0; x < nWidth; ++x ) 
					{ 
						if(!(x<=0||x>=nWidth-1||y<=0||y>=nHeight-1))
						{
							pp=p;
							Sx = 0;
							Sy = 0;
							for(int i = -1;i<= 1;i++)
								for(int j = -1;j<= 1;j++)
								{
									pp+=(j*3+stride*i);
									Sx+=pp[0]* marginalMx[(i+1)*3+j+1];
									Sy+=pp[0]* marginalMy[(i+1)*3+j+1];

									pp=p;

								}
						
							m[y,x] =(int)( Math.Sqrt(Sx*Sx+Sy*Sy));

							//增强白点
							if (m[y,x]>valve/2) 
							{

								if (p[0]>240) 
								{
									m[y,x]+=valve;
								}
								else if(p[0]>220)
								{
									m[y,x]+=(float)(valve*0.8);
								}
								else if (p[0]>200) 
								{
									m[y,x]+=(float)(valve*0.6);
								}
								else if (p[0]>180) 
								{
									m[y,x]+=(float)(valve*0.4);
								}
								else if (p[0]>160) 
								{
									m[y,x]+=(float)(valve*0.2);
								}
							}
							
							float tan ;
							if (Sx!= 0) 
							{
								tan = Sy/Sx;
							}
							else tan = 10000;
							if (-0.41421356<=tan && tan < 0.41421356) 
							{
								dlta[y,x] = 0;
								//	m[y,x]+=valve;
							
							}
							else if (0.41421356<=tan&&tan<2.41421356) 
							{
								dlta[y,x] = 1;
								//m[y,x] = 0;
								
							}
							else if (tan>=2.41421356||tan<-2.41421356) 
							{
								dlta[y,x] = 2;
								//	m[y,x]+=valve;
								
							}
							else
							{
								dlta[y,x] = 3;
								//m[y,x] = 0;
							}
						
						}
						else
							m[y,x]=0;

						p+=3; 
						if (m[y,x]>0) 
						{
							sumCount++;
							sumM += m[y,x];
						}

					} 

					p += nOffset; 

				} 
				
				//非极大值抑制和阀值
				p = (byte *)(void *)Scan0;
				for(int y=0;y < nHeight;++y)
				{ 
					for(int x=0; x < nWidth; ++x ) 
					{ 

						if (m[y,x]>sumM/sumCount*1.2) 
						{
							p[0] = p[1] = p[2] = (byte)(m[y,x]);
							//m[y,x]=1;
						}
						else 
						{
							m[y,x] = 0;
							p[0] = p[1] = p[2] = 0;
						}
						
						if(x>=1&&x<=nWidth-1&&y>=1&&y<=nHeight-1&&m[y,x]>valve)
						{
							switch(dlta[y,x]) 
							{
								case 0 :
									if (m[y,x]>=m[y,x-1]&&m[y,x]>=m[y,x+1]) 
									{
										p[0] = p[1] = p[2] = 255;
									}
									break;

								case 1:
									if (m[y,x]>=m[y+1,x-1]&&m[y,x]>=m[y-1,x+1])
									{
										p[0] = p[1] = p[2] = 255;
									}
									break;

								case 2:
									if (m[y,x]>=m[y-1,x]&&m[y,x]>=m[y+1,x]) 
									{
										p[0] = p[1] = p[2] = 255;
									}
									break;

								case 3:
									if (m[y,x]>=m[y+1,x+1]&&m[y,x]>=m[y-1,x-1])
									{
										p[0] = p[1] = p[2] = 255;
									}
									break;

							}
							
						}
						if (p[0]==255) 
						{
							m[y,x]=1;
						}
						else
						{
							m[y,x]=0;
							p[0] = p[1] = p[2] = 0;
						}
					
						tt = p[0];
						newGray[tt]++;
						p+=3; 
					}
					p += nOffset; 
		
				}




//////////////////////////////////////////////////////////////////////////	
//水平扫描(每div像素一次),识别字符特征
//////////////////////////////////////////////////////////////////////////

				for (int i=0;i<(int)(nHeight/div)+1;i++) 
				{
					for ( int j=0;j<(int)(nWidth/lv)+1 ;j++) 
					{
						countMatch[i,j]=0;
					}					
				}

				p = (byte *)(void *)Scan0;
				for(int y=2*div;y < nHeight-2*div;)
				{ 	
					for (int j=0;j<nWidth;j++) 
					{
						mark[y/div,j]=0;
					}
					for (int i =0;i<div;i++) 
					{
						getStart = true;	
						for(pWR=pWL=pWHL=pWHR=pWH=4; pWH< nWidth-1; pWH++ ) 
						{ 
							//标记每行的第一个白点
							if (getStart) 
							{
								if (m[y+i,pWH]>0) 
								{
									getStart = false;
									pWR=pWL=pWHL=pWHR=pWH;
								}
								else
									continue;
							}
							if (pWR-pWL>nWidth/3||pWHL-pWR>nWidth/3||pWHR-pWHL>nWidth/3) 
							{
								goto L;
							}
							if ( m[y+i,pWH-1]>0&&m[y+i,pWH]<=0)//白-->黑 
							{
								pWHR=pWH-1;
								
								if (pWL!=pWHL )
								{
									if( (Wmin<=(pWR-pWL)&&(pWR-pWL)<=Wmax)						
										||( Bmin<=(pWHL-pWR-1)&&(pWHL-pWR-1)<=Bmax)		
										||( Wmin<=(pWHR-pWHL)&&(pWHR-pWHL)<=Wmax ) )
									{
									
										//记录该点
										//if (pWR-pWL+pWHR-pWHL<11) 
										if (-pWL+pWHR<30) 
										{
											double rate1=Wmax/(Math.Abs((pWR-pWL)-(Wmax-Wmin))/2+1);
											double rate2=Wmax/(Math.Abs((pWHR-pWHL)-(Wmax-Wmin))/2+1);
											double rate3=Bmax*3/(pWHL-pWR);
											mark[y/div,pWL+(pWR-pWL)/2]+=(int)(rate3+rate2+rate2);	
										}
									}
									
									if (pWR-pWL>2*lv) 
									{ //连续白(或)宽于一个字符宽度
										for (int t=pWL+lv/2;t<pWR-lv/2;t+=lv) 
										{
											countMatch[y/div,t/lv]=-1;
										}
										//countMatch[y/div,pWR/lv]=-1;
									}
									if (pWHL-pWR-1>2*lv) 
									{
										for (int t=pWR+lv/2;t<pWHL-lv/2;t+=lv) 
										{
											countMatch[y/div,t/lv]-=1;
										}
										//countMatch[y/div,pWHL/lv]=-1;
									}
									if (pWHR-pWHL>2*lv) 
									{
										for (int t=pWHL+lv/2;t<pWHR-lv/2;t+=lv) 
										{
											countMatch[y/div,t/lv]-=1;
										}
										//countMatch[y/div,pWHR/lv]=-1;
									}
									
								}
								pWR=pWHR;
								pWL=pWHL;
							}
							else if ( m[y+i,pWH-1]<=0&&m[y+i,pWH]>0)//黑-->白
							{
								pWHL=pWH;
							}
						}
					}
				L:y+=div;
				}
		




//////////////////////////////////////////////////////////////////////////
//去除噪音
//////////////////////////////////////////////////////////////////////////
///
				//基与特征点水平间隔的去噪
				int toCheck=-1;

				foreach (int i in sumC) 
				{
					sumC[i]=0;
				}
				sM=0;
				ccm=0;
				
				//累计连续的特征点
				for (int i=2;i<(int)(nHeight/div)-1;i++) 
				{
					toCheck=-1;
					lineLabel[i]=false;
					//sumLX=0;
					pWL=pWR=1;
					getStart = true;
					for (int j=1;j<nWidth;j++)
					{
						//标记每行的第一个白点
						if (getStart) 
						{
							if (m[i,j]>0) 
							{
								getStart = false;
								pWR=pWL=j;
							}
							else
								continue;
						}

						///*
						if (mark[i,j]>0)
						{
							if (toCheck==-1) 
							{
								toCheck=j;
								continue;
							}
							else 
							{
								if (j-toCheck<=1) 
								{//////////////////////////////////////////////////////////////////////////
									if (countMatch[i,j/lv]>=0) 
									{
										countMatch[i,j/lv]+=(mark[i,toCheck]+mark[i,j]);//两个点相互匹配,累加2
									}
									toCheck=-1;
									//lineLabel[i]=true;
									continue;
								}
								else
								{
									//mark[i,toCheck]-=(int)(div*0.8);//除去该特征点
									if (mark[i,toCheck]<(div*0.7)) 
									{
										mark[i,toCheck]=0;
									}
									else
									{
										countMatch[i,j/lv]+=2*mark[i,toCheck];
									}
			
									toCheck=j;
									continue;
								}
							}
						}
					}					

				}
		
				//阀值化		
				sM=0;
				ccm=0;
				int va=(int)(lv*div/3);
				int[] countL = new int[(int)(nHeight/div)+1] ;
				
				for (int i=0;i<(int)(nHeight/div)+1;i++) 
				{
					bool ok  ;
					ok = false;
					countL[i]=0;
					lineLabel[i]=false;
					
					for(int j=0; j < (int)(nWidth/lv)+1 ; ++j ) 
					{
						//图像周边特征点为零
						if (i==0||i==(int)(nHeight/div)||j==0||j==(int)(nWidth/lv)) 
						{
							countMatch[i,j]=0;
							continue;
						}
						
						if (countMatch[i,j]>va) 
						{//阀值去噪音 
							if ( (countMatch[i,j-1]<=va&&countMatch[i,j+1]<=va)||//去除孤立点(水平)
								(countMatch[i-1,j]<=va&&(countMatch[i+1,j]<=va||(countMatch[i+1,j-1]<=va&&countMatch[i+1,j+1]<=va))) )//去除孤立点(垂直)			 
							{
								countMatch[i,j]=0;
							}
							else
							{							
								countL[i]+=countMatch[i,j];
								ok=true;
							}
						}
						else
							countMatch[i,j]=0;
					}
					
					if (ok) 
					{
						lineLabel[i]=true;   
						sM+=countL[i];
						ccm++;
					}		
				}
				
				//去除上半部分大面积的噪音
				
				int v1=0,v2=0;
				int vm1=0,vm2=0;
				int maxL=0,cv=0;
				for (int i=1;i<(int)(nHeight/div)+1;i++) 
				{
					if (lineLabel[i]==true&&lineLabel[i-1]==false) 
					{
						v1=i;
						v2=i;
					}
					else if (lineLabel[i]==false&&lineLabel[i-1]==true) 
					{
						v2=i;
						cv++;
						if (maxL<v2-v1) 
						{
							vm1=v1;
							vm2=v2;
							maxL=v2-v1;
						}	
					}
				}
				if (cv>1&&vm2-vm1>5&&vm1+(vm2-vm1+1)/2<(nHeight/div)/3||vm2-vm1>nHeight/div/2) 
				{
					for (int k=vm1;k<=vm2;k++) 
					{
						lineLabel[k]=false;
					}
				}
				int p1=0,p2=0;
				for (int i=0;i<(int)(nHeight/div)+1;i++)
				{
					if (lineLabel[i]==true) 
					{
						p1=0;p2=0;
						bool ok=false;
						for (int j=1;j<(int)(nWidth/lv)+1;j++) 
						{
							if (countMatch[i,j-1]==0&&countMatch[i,j]>0) 
							{
								p1=p2=j;
							}
							if (countMatch[i,j-1]>0&&countMatch[i,j]==0) 
							{
								p2=j-1;
								if (p2-p1>0) 
								{
									ok=true;
								}
								else
								{
									p2=p1=0;
									countMatch[i,j-1]=0;
								}
							}
						}
						if (!ok&&p2==0&&p1==0) 
						{
							lineLabel[i]=false;
						}
					}
				}


//////////////////////////////////////////////////////////////////////////
//使用2×6矩阵粗定位
//////////////////////////////////////////////////////////////////////////

				int lLenght=5,vLenght=1;

⌨️ 快捷键说明

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