GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母

由于网页上的验证码图片都是通过程序产生的,因此,各个字母之间也都比较规则,进行识别其中的字符的话,也比较简单,只要将图片进行相减后,看看和那个字母的图片接近即可.

下面,我就那我们公司的外网邮箱:http://mail.lida-oe.com.cn的网页中的验证码为例子,我写了一个程序.

【网通】点击这里下载全部源程序    【电信、网通】点击这里下载源程序

【下载说明】
1、单击上面这个地址,打开下载页面。
2、点普通下载--等待30秒--点“下载”按钮--保存

整个程序的过程是这样的:

1 获取网页中的图片的地址,并下载到本地

2 对图像的像素中的A(透明度)值,来对图像进行二值化处理

3 对整个图片进行裁剪,仅裁剪出包含字符的区域

4 使用投影法对图像进行分割,从而保证每个分割区域仅包含一个字符

5 对分割出来的图片,再次进行裁剪,使得整个字符充满图片框,并大小一致

6 因此对分割出来的字符图片与图片库中的图片进行比较,相差最小的仅为字符.

我首先是搜集了多幅的验证码图片,以便能够得到所有的字符的图片. 然后,对这些搜集来的图片进行分割,从而得到包含26个字母的图片. 将这些图片作为图片库, 之后将从网页中获取的图片分割出来的字符图片,与此对比,从而得到识别结果.

截图如下:

GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母_第1张图片

获取网页中验证码图片之后,如上图。

GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母_第2张图片

将图片进行“二值化”之后的图片,如上图。

GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母_第3张图片

之后,对图片进行剪裁,如上图。

GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母_第4张图片

再使用投影法,分割出每个字符,如上图。

GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母_第5张图片

将分割出来的字符进行剪裁,如上图。

GetAlpha:C#实现获取网页验证码图片,并识别出其中的字母_第6张图片

最终,通过与样本库的字符图片进行对比,识别出图片中的字母。

部分源程序:

主要源程序(由于做的比较急,并未对程序结构进行优化):

 /*
 * 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;
   }
  }

【更多阅读】

  1. [译]在C# .NET2.0实现单实例应用程序
  2. [原]ManageStartUpApps:C#操作注册表来读取和修改开机启动项
  3. [原]PjCleanSystemTrash:C#清除系统盘垃圾
  4. [原]ManageApps:C#读取Windows系统中的已经安装的程序并卸载软件
  5. [原]WMICodeCreator:C#产生WMI代码的工具
  6. [原]《The C Programming Language》电子书下载
  7. [原]Baidu:C#利用百度来搜索网页、图片、视频等等
  8. [原]WMICodeCreator:C#产生WMI代码的工具
  9. [原]PjConvertImageFormat:用FreeImage.NET写的一个35种图像格式转换程序
  10. [原]DownloadWebImages:下载某页面上的所有图片

你可能感兴趣的:(object,list,C#,null,button,Constructor)