星期一, 三月 8th, 2010


强大的图片验证码识别代码

今天想刷个投票页面,需要识别验证码,网上搜啊,找到一个图片验证码识别类,改动一下用起来很舒服啊^_^
因为每种类验证码的字符表都不一样,所以需要事先得到此种验证码的字符表
方法呢,就是在调试模式输出一下就看到了
代码如下
UnCodeBase.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace BallotAiying2
{
    class UnCodebase
    {
        public Bitmap bmpobj;
        public UnCodebase(Bitmap pic)
        {
            //       if (pic.PixelFormat == PixelFormat.Format8bppIndexed)
            bmpobj = new Bitmap(pic);    //转换为Format32bppRgb
        }

        ///

        /// 根据RGB,计算灰度值
        /// 

        ///
Color值
        /// 灰度值,整型
        private int GetGrayNumColor(System.Drawing.Color posClr)
        {
            return (posClr.R * 19595 + posClr.G * 38469 + posClr.B * 7472) >> 16;
        }

        ///

        /// 灰度转换,逐点方式
        /// 

        public void GrayByPixels()
        {
            for (int i = 0; i < bmpobj.Height; i++)
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    int tmpValue = GetGrayNumColor(bmpobj.GetPixel(j, i));
                    bmpobj.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue));
                }
            }
        }

        ///

        /// 去图形边框
        /// 

        ///

        public void ClearPicBorder(int borderWidth)
        {
            for (int i = 0; i < bmpobj.Height; i++)
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    if (i < borderWidth || j < borderWidth || j > bmpobj.Width - 1 - borderWidth || i > bmpobj.Height - 1 - borderWidth)
                        bmpobj.SetPixel(j, i, Color.FromArgb(255, 255, 255));
                }
            }
        }

        ///

        /// 灰度转换,逐行方式
        /// 

        public void GrayByLine()
        {
            Rectangle rec = new Rectangle(0, 0, bmpobj.Width, bmpobj.Height);
            BitmapData bmpData = bmpobj.LockBits(rec, ImageLockMode.ReadWrite, bmpobj.PixelFormat);// PixelFormat.Format32bppPArgb);
            //    bmpData.PixelFormat = PixelFormat.Format24bppRgb;
            IntPtr scan0 = bmpData.Scan0;
            int len = bmpobj.Width * bmpobj.Height;
            int[] pixels = new int[len];
            Marshal.Copy(scan0, pixels, 0, len);

            //对图片进行处理
            int GrayValue = 0;
            for (int i = 0; i < len; i++)
            {
                GrayValue = GetGrayNumColor(Color.FromArgb(pixels[i]));
                pixels[i] = (byte)(Color.FromArgb(GrayValue, GrayValue, GrayValue)).ToArgb();      //Color转byte
            }

            bmpobj.UnlockBits(bmpData);

            ////输出
            //GCHandle gch = GCHandle.Alloc(pixels, GCHandleType.Pinned);
            //bmpOutput = new Bitmap(bmpobj.Width, bmpobj.Height, bmpData.Stride, bmpData.PixelFormat, gch.AddrOfPinnedObject());
            //gch.Free();
        }

        ///

        /// 得到有效图形并调整为可平均分割的大小
        /// 

        ///
灰度背景分界值
        ///
有效字符数
        /// 
        public void GetPicValidByValue(int dgGrayValue, int CharsCount)
        {
            int posx1 = bmpobj.Width; int posy1 = bmpobj.Height;
            int posx2 = 0; int posy2 = 0;
            for (int i = 0; i < bmpobj.Height; i++)      //找有效区
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    int pixelValue = bmpobj.GetPixel(j, i).R;
                    if (pixelValue < dgGrayValue)     //根据灰度值
                    {
                        if (posx1 > j) posx1 = j;
                        if (posy1 > i) posy1 = i;

                        if (posx2 < j) posx2 = j;
                        if (posy2 < i) posy2 = i;
                    };
                };
            };
            // 确保能整除
            int Span = CharsCount - (posx2 - posx1 + 1) % CharsCount;   //可整除的差额数
            if (Span < CharsCount)
            {
                int leftSpan = Span / 2;    //分配到左边的空列 ,如span为单数,则右边比左边大1
                if (posx1 > leftSpan)
                    posx1 = posx1 - leftSpan;
                if (posx2 + Span - leftSpan < bmpobj.Width)
                    posx2 = posx2 + Span - leftSpan;
            }
            //复制新图
            Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);
            bmpobj = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);
        }

        ///

        /// 得到有效图形,图形为类变量
        /// 

        ///
灰度背景分界值
        ///
有效字符数
        /// 
        public void GetPicValidByValue(int dgGrayValue)
        {
            int posx1 = bmpobj.Width; int posy1 = bmpobj.Height;
            int posx2 = 0; int posy2 = 0;
            for (int i = 0; i < bmpobj.Height; i++)      //找有效区
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    int pixelValue = bmpobj.GetPixel(j, i).R;
                    if (pixelValue < dgGrayValue)     //根据灰度值
                    {
                        if (posx1 > j) posx1 = j;
                        if (posy1 > i) posy1 = i;

                        if (posx2 < j) posx2 = j;
                        if (posy2 < i) posy2 = i;
                    };
                };
            };
            //复制新图
            Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);
            bmpobj = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);
        }

        ///

        /// 得到有效图形,图形由外面传入
        /// 

        ///
灰度背景分界值
        ///
有效字符数
        /// 
        public Bitmap GetPicValidByValue(Bitmap singlepic, int dgGrayValue)
        {
            int posx1 = singlepic.Width; int posy1 = singlepic.Height;
            int posx2 = 0; int posy2 = 0;
            for (int i = 0; i < singlepic.Height; i++)      //找有效区
            {
                for (int j = 0; j < singlepic.Width; j++)
                {
                    int pixelValue = singlepic.GetPixel(j, i).R;
                    if (pixelValue < dgGrayValue)     //根据灰度值
                    {
                        if (posx1 > j) posx1 = j;
                        if (posy1 > i) posy1 = i;

                        if (posx2 < j) posx2 = j;
                        if (posy2 < i) posy2 = i;
                    };
                };
            };
            //复制新图
            Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);
            return singlepic.Clone(cloneRect, singlepic.PixelFormat);
        }

        ///

        /// 平均分割图片
        /// 

        ///
水平上分割数
        ///
垂直上分割数
        /// 分割好的图片数组
        public Bitmap [] GetSplitPics(int RowNum,int ColNum)
        {
            if (RowNum == 0 || ColNum == 0)
                return null;
            int singW = bmpobj.Width / RowNum;
            int singH = bmpobj.Height / ColNum;
            Bitmap [] PicArray=new Bitmap[RowNum*ColNum];

            Rectangle cloneRect;
            for (int i = 0; i < ColNum; i++)      //找有效区
            {
                for (int j = 0; j < RowNum; j++)
                {
                    cloneRect = new Rectangle(j*singW, i*singH, singW , singH);
                    PicArray[i*RowNum+j]=bmpobj.Clone(cloneRect, bmpobj.PixelFormat);//复制小块图
                }
            }
            return PicArray;
        }

        ///

        /// 返回灰度图片的点阵描述字串,1表示灰点,0表示背景
        /// 

        ///
灰度图
        ///
背前景灰色界限
        /// 
        public string GetSingleBmpCode(Bitmap singlepic, int dgGrayValue)
        {
            Color piexl;
            string code = "";
            for (int posy = 0; posy < singlepic.Height; posy++)
                for (int posx = 0; posx < singlepic.Width; posx++)
                {
                    piexl = singlepic.GetPixel(posx, posy);
                    if (piexl.R < dgGrayValue)    // Color.Black )
                        code = code + "1";
                    else
                        code = code + "0";
                }
            return code;
        }

    }

}

unCodeAiYing.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace BallotAiying2
{
    class unCodeAiYing : UnCodebase
    {
        //字符表
        string[,] CodeArray = new string[,] {{"1","00100111000010000100001000010000100001000010011111"},
{"4","000100000100001100010100100100100100111111000100000100001111"},
{"B","1111110010000101000010100010011110001000100100001010000101000011111110"},
{"N","1110111011001001100100101010010101001010100100110010011001001101110010"},
{"0","011110100001100001101101101101101101101101100001100001011110"},
{"M","111011011011011011011011010101010101010101010101010101110101"},
{"F","1111110010000101001000100100011110001001000100100010000001000001110000"},
{"E","1111110010000101001000100100011110001001000100100010000001000011111110"},
{"A","0001000000100000101000010100001010000101000111110010001001000101110111"},
{"G","001111010001100001100000100000100000100011100001010001001110"},
{"K","1110111010001001001000101000011100001010000100100010010001000101110111"},
{"T","1111111100100100010000001000000100000010000001000000100000010000011100"},
{"C","0011111010000110000011000000100000010000001000000100000101000100011100"},
{"4","00010000100011001010100101001011111000100001000111"},
{"9","011100100010100001100001100011011101000001000001100010011100"},
{"S","011111100001100001100000011000000110000001100001100001111110"},
{"Z","111111100010000010000100000100001000001000010000010001111111"},
{"3","011110100001100001000010001100000010000001100001100001011110"},
{"M","1110111011011001101100110110010101001010100101010010101001010101101011"},
{"Q","0011100010001010000011000001100000110000011000001101100101001100011101"},
{"L","1110000010000001000000100000010000001000000100000010000001000011111111"},
{"W","1101011010101001010100101010010101001101100010100001010000101000010100"},
{"D","111110010001010000010000010000010000010000010000010001111110"},
{"I","11111001000010000100001000010000100001000010011111"},
{"U","1110111010001001000100100010010001001000100100010010001001000100011100"},
{"6","00111010001000010000101111100010000100001000001111"},
{"B","111111010000010000010001011110010001010000010000010000111111"},
{"8","011110100001100001100001011110010010100001100001100001011110"},
{"P","1111110010000101000010100001011111001000000100000010000001000001110000"},
{"N","111011011001011001010101010101010101010011010011010011111001"},
{"X","1110111010001000101000010100000100000010000010100001010001000101110111"},
{"X","111011010001001010001010000100000100001010001010010001111011"},
{"D","1111100010001001000010100001010000101000010100001010000101000101111100"},
{"U","111011010001010001010001010001010001010001010001010001001110"},
{"H","1110111010001001000100100010011111001000100100010010001001000101110111"},
{"R","1111100010001001000100100010011110001010000100100010010001000101110011"},
{"V","111011010001010001010001001010001010001010001010000100000100"},
{"O","0011100010001010000011000001100000110000011000001100000101000100011100"},
{"T","111111100100000100000100000100000100000100000100000100001110"},
{"2","011110100001100001000001000010000100001000010000100001111111"},
{"6","001110010001100000100000101110110001100001100001100001011110"},
{"Z","11111100010000100010000100010000100010000100011111"},
{"Y","111011010001010001001010001010000100000100000100000100001110"},
{"Y","1110111010001001000100010100001010000010000001000000100000010000011100"},
{"5","11111100001000010111110000000000000100001000001111"},
{"R","111110010001010001010001011110010100010010010010010001111001"},
{"W","110101010101010101010101010101011011001010001010001010001010"},
{"H","111011010001010001010001011111010001010001010001010001111011"},
{"5","111111100000100000101110110001000001000001100001100001011110"},
{"V","1110111010001001000100100010001010000101000010100001010000010000001000"},
{"J","001111000010000010000010000010000010000010000010100010111100"},
{"7","111111100010100010000100000100001000001000001000001000001000"},
{"O","001110010001100000100000100000100000100000100000010001001110"},
{"F","111111010000010010010010011110010010010010010000010000111000"},
{"C","001111010000100000100000100000100000100000100000010001001110"},
{"Q","001110010001100000100000100000100000100000101100010011001110"},
{"J","0011111000010000001000000100000010000001000000100000010010001001111000"},
{"9","01110100011000010000100010111000000000001000101110"}};

        public unCodeAiYing(Bitmap pic)
            : base(pic)
        {
        }

        public string getPicnum()
        {
            GrayByPixels(); //灰度处理
            GetPicValidByValue(128, 4); //得到有效空间
            Bitmap[] pics = GetSplitPics(4, 1);     //分割

            if (pics.Length != 4)
            {
                return ""; //分割错误
            }
            else  // 重新调整大小
            {
                pics[0] = GetPicValidByValue(pics[0], 128);
                pics[1] = GetPicValidByValue(pics[1], 128);
                pics[2] = GetPicValidByValue(pics[2], 128);
                pics[3] = GetPicValidByValue(pics[3], 128);
            }

            //      if (!textBoxInput.Text.Equals(""))
            string result = "";
            string dddd = "";
            char singleChar = ' ';
            {
                for (int i = 0; i < 4; i++)
                {
                    string code = GetSingleBmpCode(pics[i], 128);   //得到代码串
                    System.Diagnostics.Debug.WriteLine(code);
                    for (int arrayIndex = 0; arrayIndex < CodeArray.Length/2; arrayIndex++)
                    {
                        if (CodeArray[arrayIndex,1].Equals(code))  //相等
                        {
                            dddd = CodeArray[arrayIndex, 0];
                            //if (arrayIndex < 10)   // 0..9
                            //    singleChar = (char)(48 + arrayIndex);
                            //else if (arrayIndex < 36) //A..Z
                            //    singleChar = (char)(65 + arrayIndex - 10);
                            //else
                            //    singleChar = (char)(97 + arrayIndex - 36);
                            //result = result + singleChar;
                            result = result + dddd;
                        }
                    }
                }
            }
           return result;
        }
    }
}

使用方式

HtmlDocument doc = webBrowser1.Document;
              //  IHTMLDocument2 doc2 = (IHTMLDocument2)webBrowser1.Document.DomDocument;
                //      HtmlElement ImgeTag =(HtmlElement) doc2.images.item(0, 0);

                HtmlElement ImgeTag = doc.Forms[0].GetElementsByTagName("IMG")[0];

                Image numPic = GetWebImage(webBrowser1, ImgeTag); // 得到验证码图片
                pictureBox1.Image = numPic;
                unCodeAiYing UnCheckobj = new unCodeAiYing((Bitmap)numPic);
                string strNum = UnCheckobj.getPicnum();     //识别图片
                System.Diagnostics.Debug.WriteLine(strNum);
                for (int i = 0; i < doc.All.Count; i++)
                {
                    if (doc.All[i].TagName.ToUpper().Equals("INPUT"))
                    {
                        switch (doc.All[i].Name)
                        {
                            case "Vcode":
                                doc.All[i].InnerText = strNum;
                                break;
                            case "Submit":
                                ClickBtn = doc.All[i]; //提交
                                break;
                        }
                    }

                }
                ClickBtn.InvokeMember("Click");   //执行按扭操作

如果你是第一次来这儿,欢迎订阅 RSS feed。 第一时间看到更多精彩内容,谢谢你的访问!
原文地址:http://ai-2.cn/2010/03/validcodeshibie/
转载请注明出处,非常感谢!

Category: c#
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response

2010/03/09
花儿朵朵

就是System.Diagnostics.Debug.WriteLine(code)吧,就看到字符串了