由于网页上的验证码图片都是通过程序产生的,因此,各个字母之间也都比较规则,进行识别其中的字符的话,也比较简单,只要将图片进行相减后,看看和那个字母的图片接近即可.
下面,我就那我们公司的外网邮箱:http://mail.lida-oe.com.cn的网页中的验证码为例子,我写了一个程序.
【网通】点击这里下载全部源程序 【电信、网通】点击这里下载源程序
【下载说明】
1、单击上面这个地址,打开下载页面。
2、点普通下载--等待30秒--点“下载”按钮--保存
整个程序的过程是这样的:
1 获取网页中的图片的地址,并下载到本地
2 对图像的像素中的A(透明度)值,来对图像进行二值化处理
3 对整个图片进行裁剪,仅裁剪出包含字符的区域
4 使用投影法对图像进行分割,从而保证每个分割区域仅包含一个字符
5 对分割出来的图片,再次进行裁剪,使得整个字符充满图片框,并大小一致
6 因此对分割出来的字符图片与图片库中的图片进行比较,相差最小的仅为字符.
我首先是搜集了多幅的验证码图片,以便能够得到所有的字符的图片. 然后,对这些搜集来的图片进行分割,从而得到包含26个字母的图片. 将这些图片作为图片库, 之后将从网页中获取的图片分割出来的字符图片,与此对比,从而得到识别结果.
截图如下:
获取网页中验证码图片之后,如上图。
将图片进行“二值化”之后的图片,如上图。
之后,对图片进行剪裁,如上图。
再使用投影法,分割出每个字符,如上图。
将分割出来的字符进行剪裁,如上图。
最终,通过与样本库的字符图片进行对比,识别出图片中的字母。
部分源程序:
主要源程序(由于做的比较急,并未对程序结构进行优化): /* * Created by SharpDevelop. * User: Administrator * Date: 2012-6-11 * Time: 11:46 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Net; using System.Windows.Forms; namespace GetAlpha { /// <summary> /// Description of MainForm. /// </summary> public partial class MainForm : Form { private Bitmap bitmap=null; private string fileName=string.Empty; private List<Bitmap> alphaBmp=new List<Bitmap>(); public MainForm() { // // The InitializeComponent() call is required for Windows Forms designer support. // InitializeComponent(); // // TODO: Add constructor code after the InitializeComponent() call. // this.toolStripStatusLabel1.Text=""; this.toolStripStatusLabel2.Text=""; } void Button1Click(object sender, EventArgs e) { OpenFileDialog ofd=new OpenFileDialog(); ofd.Filter="All Image Files|*.bmp;*.png;*.jpg;*.gif"; ofd.RestoreDirectory=false; if(ofd.ShowDialog()==DialogResult.OK) { pictureBox1.Image=Image.FromFile(ofd.FileName); if(this.bitmap!=null) { this.bitmap.Dispose(); this.bitmap=null; } this.bitmap=new Bitmap(Image.FromFile(ofd.FileName),pictureBox1.Width,pictureBox1.Height); this.Text="GetAlpha("+System.IO.Path.GetFileName(ofd.FileName)+")"; this.fileName=System.IO.Path.GetFileNameWithoutExtension(ofd.FileName); } } void PictureBox1MouseHover(object sender, EventArgs e) { } void PictureBox1MouseClick(object sender, MouseEventArgs e) { if(this.bitmap==null) return; this.toolStripStatusLabel1.Text=e.Location.ToString(); Color mouse_clr=bitmap.GetPixel(e.X,e.Y); this.toolStripStatusLabel2.Text=mouse_clr.ToString(); } void Button2Click(object sender, EventArgs e) { int bmp_width=this.bitmap.Width; int bmp_height=this.bitmap.Height; for(int i=0;i<bmp_height;i++) { for(int j=0;j<bmp_width;j++) { Color clr=this.bitmap.GetPixel(j,i); if(clr.R!=0 && clr.G!=0 && clr.B!=0) { int a=(clr.A>120)?255:0; Color tmp=Color.FromArgb(a,255,255,255); this.bitmap.SetPixel(j,i,tmp); } } } pictureBox1.Image=this.bitmap; } void Button3Click(object sender, EventArgs e) { int bmp_width=this.bitmap.Width; int bmp_height=this.bitmap.Height; List<Point> pt1_list=new List<Point>(); List<Point> pt2_list=new List<Point>(); //统计每行的第一个和最后一个白色像素点 bool isFirstPixelInLine=false; for(int i=0;i<bmp_height;i++) { isFirstPixelInLine=false; Point pt1=new Point(0,0); Point pt2=new Point(0,0); for(int j=0;j<bmp_width;j++) { Color clr=this.bitmap.GetPixel(j,i); if(clr.R==255 && clr.G==255 && clr.B==255) { if(isFirstPixelInLine==false) { isFirstPixelInLine=true; pt1.X=j; pt1.Y=i; } else { pt2.X=j; pt2.Y=i; } } } pt1_list.Add(pt1); pt2_list.Add(pt2); } //找出裁剪区域的左上角和右下角点的坐标 Point ptt1=new Point(this.bitmap.Width,this.bitmap.Height); Point ptt2=new Point(0,0); for(int i=0;i<pt1_list.Count;i++) { if(pt1_list[i].X!=0 && pt1_list[i].Y!=0) { if(pt1_list[i].X<ptt1.X) ptt1.X=pt1_list[i].X; if(pt1_list[i].Y<ptt1.Y) ptt1.Y=pt1_list[i].Y; if(pt2_list[i].X>ptt2.X) ptt2.X=pt2_list[i].X; if(pt2_list[i].Y>ptt2.Y) ptt2.Y=pt2_list[i].Y; } } //画出红色竖线以分割图片 // for(int i=0;i<pt1_list.Count;i++) // { // Debug.WriteLine("pt1="+pt1_list[i].ToString()); // this.bitmap.SetPixel(pt1_list[i].X,pt1_list[i].Y,Color.FromArgb(255,255,0,0)); // Debug.WriteLine("pt2="+pt2_list[i].ToString()); // this.bitmap.SetPixel(pt2_list[i].X,pt2_list[i].Y,Color.FromArgb(255,255,0,0)); // } // // this.bitmap.SetPixel(ptt1.X,ptt1.Y,Color.FromArgb(255,0,255,0)); // this.bitmap.SetPixel(ptt2.X,ptt2.Y,Color.FromArgb(255,0,255,0)); //裁剪图片 int new_width=ptt2.X-ptt1.X; int new_height=ptt2.Y-ptt1.Y; Bitmap temp=new Bitmap(new_width,new_height,PixelFormat.Format32bppArgb); for(int i=ptt1.Y,h=0;i<ptt2.Y;i++,h++) { for(int j=ptt1.X,w=0;j<ptt2.X;j++,w++) { Color clr=this.bitmap.GetPixel(j,i); temp.SetPixel(w,h,Color.FromArgb(clr.A,clr.R,clr.G,clr.B)); } } this.bitmap.Dispose(); this.bitmap=new Bitmap(temp,pictureBox1.Width,pictureBox1.Height); pictureBox1.Image=this.bitmap; } void MainFormSizeChanged(object sender, EventArgs e) { } void MainFormResize(object sender, EventArgs e) { if(this.WindowState==FormWindowState.Maximized || this.WindowState==FormWindowState.Normal) { if(this.bitmap!=null) { this.bitmap.Dispose(); this.bitmap=new Bitmap(this.pictureBox1.Image,this.pictureBox1.Width,this.pictureBox1.Height); } } } void Button4Click(object sender, EventArgs e) { SaveFileDialog sfd=new SaveFileDialog(); sfd.Filter="JPG File|*.jpg|GIF File|*.gif"; if(sfd.ShowDialog()==DialogResult.OK) { this.pictureBox1.Image.Save(sfd.FileName); } } void Button5Click(object sender, EventArgs e) { int bmpWidth=this.bitmap.Width; int bmpHeight=this.bitmap.Height; int[] whitePoints=new int[bmpWidth]; //统计在水平方向上的非0像素的个数 for(int j=0;j<bmpWidth;j++) { whitePoints[j]=0; for(int i=0;i<bmpHeight;i++) { Color clr=this.bitmap.GetPixel(j,i); if(clr.A==255&&clr.R==255&&clr.G==255&&clr.B==255) { whitePoints[j]++; } } Trace.WriteLine(j.ToString()+","+whitePoints[j].ToString()); } //找出0的转变点 List<int> splitPoints=new List<int>(); for(int j=0;j<bmpWidth-1;j++) { if(whitePoints[j]==0) { if(whitePoints[j+1]!=0) { Trace.Write((j+1).ToString()+","); splitPoints.Add(j+1); } } else { if(whitePoints[j+1]==0) { Trace.Write((j+1).ToString()+","); splitPoints.Add(j+1); } } } //画出红色竖线 // for(int j=0;j<splitPoints.Count;j++) // { // for(int i=0;i<bmpHeight;i++) // { // this.bitmap.SetPixel(splitPoints[j],i,Color.FromArgb(255,255,0,0)); // } // } // // this.pictureBox1.Image=this.bitmap; //分割各个字符到下面的图片框中 for(int k=0;k<4;k++) { Bitmap tmp=new Bitmap(splitPoints[2*k+1]-splitPoints[2*k],bmpHeight,PixelFormat.Format32bppArgb); for(int j=0,h=0;j<bmpHeight;j++,h++) { for(int i=splitPoints[2*k],w=0;i<splitPoints[2*k+1];i++,w++) { Color clr=this.bitmap.GetPixel(i,j); tmp.SetPixel(w,h,Color.FromArgb(clr.A,clr.R,clr.G,clr.B)); } } if(k==0) this.pictureBox2.Image=tmp; if(k==1) this.pictureBox3.Image=tmp; if(k==2) this.pictureBox4.Image=tmp; if(k==3) this.pictureBox5.Image=tmp; } }
【更多阅读】