zoukankan      html  css  js  c++  java
  • c# 识别验证码


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

    using System.Net;
    using System.Web;
    using System.Drawing;
    using System.Drawing.Imaging;

    namespace PcRegister
    {
        /**//// <summary>
        /// CrMonterNetImg 的摘要说明。
        /// </summary>
        public class CrMonterNetImg
        {
            /**//// <summary>
            /// Cookie集合,使用这个cookie集合去获取验证码
            /// </summary>
            private CookieCollection Cookie=null;

            /**//// <summary>
            /// 验证码的地址
            /// </summary>
            private string ImgUrl="";

            /**//// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="StrUrl">验证码地址</param>
            /// <param name="Cookies">cookie集合</param>
            public CrMonterNetImg(string StrUrl, CookieCollection Cookies)
            {
                this.ImgUrl = StrUrl;
                this.Cookie = Cookies;
            }

            private bool _debug=false;
            /**//// <summary>
            /// 设置是否为debug,如果是debug的话,就把当前图片保存到c:.bmp
            /// </summary>
            public bool debug
            {
                set
                {
                    _debug=value;
                }
                get
                {
                    return _debug;
                }
            }

            /**//// <summary>
            /// 识别主函数
            /// </summary>
            /// <returns></returns>
            public string proc()
            {
                //图形
                Bitmap bmp=null;
                //保存深浅2种颜色
                Color[] cc = new Color[2];
                int[] left = new int[5];//左边的点
                int[] right = new int[5];//右边的点
                int[] top = new int[5];//顶点
                int[] bottom = new int[5];//底点
                string str = "";
                try
                {
                    int i=0;
                    // '抓取图片
                    while (i != 4)
                    {//一直抓到图形中有4个独立的字符

                        bmp = this.crImg();
                        if(debug)
                        {
                            bmp.Save(@"c:\1.bmp");
                        }
                        cc = this.GetDeepColor(bmp);//得到深浅颜色
                        this.FormatImg(bmp, cc);//格式话图形,去掉背景
                        Array array1 = this.GetV(bmp);//得到x轴上有黑色点的坐标
                        i = this.chkImg(array1, ref left, ref right);//分析字符个数
                    }
                    //这里分析单个字符的上下左右点,这样就可以确定范围了
                    this.getTB(bmp, left , right, ref top, ref bottom);

                    //识别出来
                    str = this.crImg(bmp, left, right, top, bottom);

                    //释放资源
                    bmp.Dispose();
                }
                catch (Exception exception2)
                {
                    //ProjectData.SetProjectError(exception2);
                    Exception exception1 = exception2;
                    //ProjectData.ClearProjectError();
                }
                finally
                {//释放资源
                    if (bmp != null)
                    {
                        bmp.Dispose();
                    }
                }
                return str;
            }


            //其他辅助函数#region 其他辅助函数
            /**//// <summary>
            /// 加载验证码
            /// </summary>
            /// <returns>验证码图形</returns>
            private Bitmap crImg()
            {
                Bitmap bmp=null;
                //响应
                HttpWebResponse response=null;
                try
                {
                    //请求
                    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(this.ImgUrl);

                    //这里附加cookie
                    request.CookieContainer = new CookieContainer();
                    if (this.Cookie != null)
                    {
                        request.CookieContainer.Add(this.Cookie);
                    }
                    //得到响应
                    response = (HttpWebResponse) request.GetResponse();
                    //从响应流直接创建图片
                    bmp = new Bitmap(response.GetResponseStream());
                }
                catch
                {
                }
                finally
                {//清理资源
                    if (response != null)
                    {
                        response.Close();
                    }
                }
                return bmp;
            }

     
            /**//// <summary>
            /// "得到垂直投影",就是得到字符在y轴上有的点
            /// </summary>
            /// <param name="img">图形</param>
            /// <returns>返回这些点所在的array</returns>
            private Array GetV(Bitmap img)
            {
                string str = "";
        
                for (int i = 0; i <= img.Width - 1; i++)
                {//在图形的x轴上进行循环
                    
                    //然后在y轴上找黑点
                    for (int h = 0; h <= img.Height - 1; h++)
                    {
                        Color c = img.GetPixel(i, h);
                        if (c.ToArgb() == Color.Black.ToArgb())
                        {//如果找到一个黑点的话,就把这个x轴的坐标给记忆下来。
                            str = str + "," + i.ToString();
                            break;
                        }
                    }
                }
                if (str.Length > 0)
                {//因为上面采用连接的方式,所以第一个字符可能是“,”,这里去掉
                    str = str.Substring(1);
                }
                return str.Split(new char[] { ',' });
            }

            /**//// <summary>
            /// 查找单个字符中图形中最上和最下的黑点。
            /// </summary>
            /// <param name="Img">图形</param>
            /// <param name="IntS">四个字符的左边点</param>
            /// <param name="IntE">四个字符的右边点</param>
            /// <param name="T">传出参数:保存四个字符顶点</param>
            /// <param name="B">传出参数:保存四个字符底点</param>
            /// <returns></returns>
            private object getTB(Bitmap Img, int[] IntS, int[] IntE, ref int[] T, ref int[] B)
            {
                //用来计数,最多四个数字。
                int i = 0;
                while (true)
                {//一个循环处理一个图形
        
                    for (int w = IntS[i]; w <= IntE[i]; w++)
                    {//对其中的一个字符从左到右开始找
                        int h = 0;
                        do
                        {//然后在上面指定的范围内查找最上黑点和最下黑点的位置
                            Color c1 = Img.GetPixel(w, h);
                            if (c1.ToArgb() == Color.Black.ToArgb())
                            {
                                if (T[i] == 0)
                                {
                                    T[i] = h;
                                }
                                if (h < T[i])
                                {
                                    T[i] = h;
                                }
                                if (h > B[i])
                                {
                                    B[i] = h;
                                }
                            }
                            h++;
                        }
                        while (h <= 0x13);
                    }


                    i++;
                    if (i > 3)
                    {
                        return null;
                    }
                }


            }

            /**//// <summary>
            /// 得到深色、浅色--深色的RGB刚好相差30
            /// </summary>
            /// <param name="Img"></param>
            /// <returns></returns>
            private Color[] GetDeepColor(Bitmap Img)
            {
                Color c=Color.White;//深色
                Color c1=Color.White;//浅色
                Color[] cc = new Color[3];
                if (Img == null)
                {//检查图片是否有效
                    return null;
                }
            
                for (int w = 0; w <= Img.Width - 1; w++)
                {//从做到右开始找。
                    int h = 4;
                    do
                    {//经过观察,y方向4-6坐标的三行绝对可以找到这2种颜色

                        Color temp = Img.GetPixel(w, h);// 当前色
                        if (temp.R < 0xff)
                        {//'有颜色的时候才在处理
                            if (c.R > 0)
                            {
                                //用找到的颜色和当前颜色比较
                                //'如果找到的颜色比当前颜色要小
                                // '那么 c就是深色
                                // 'c1就是浅色
                                if (c.R < temp.R)
                                {
                                    c1 = temp;
                                }
                                if (c.R > temp.R)
                                {
                                    c1 = c;
                                    c = temp;
                                }
                            }
                            else
                            {
                                c = temp;
                            }
                            if (c1.ToArgb() > 0)
                            {
                                break;
                            }
                        }
                        h++;
                    }
                    while (h <= 6);
                }
                cc[0] = c;
                cc[1] = c1;
                return cc;
            }

            /**//// <summary>
            /// 去背景,单色显示
            /// </summary>
            /// <param name="Img"></param>
            /// <param name="Cc"></param>
            /// <returns></returns>
            private object FormatImg(Bitmap Img, Color[] Cc)
            {
                object obj=null;
        
                //循环处理每一点
                for (int w = 0; w <= Img.Width - 1; w++)
                {            
                    for (int h = 0; h <=  Img.Height - 1; h++)
                    {
                        //如果当前颜色是深色的话,就转化成黑色
                        //否则就转化成白色
                        Color c = Img.GetPixel(w, h);
                        if (c.ToArgb() == Cc[1].ToArgb())
                        {
                            Img.SetPixel(w, h, Color.White);
                        }
                        if (c.ToArgb() == Cc[0].ToArgb())
                        {
                            Img.SetPixel(w, h, Color.Black);
                        }
                    }
                }
                return obj;
            }


            /**//// <summary>
            /// 识别图形的字符
            /// </summary>
            /// <param name="Img">图形</param>
            /// <param name="IntS">计算出来的左边点</param>
            /// <param name="Inte">计算出来的上面点</param>
            /// <param name="T">计算出来的上面点</param>
            /// <param name="B">计算出来的顶点</param>
            /// <returns>字符</returns>
            private string crImg(Bitmap Img, int[] IntS, int[] Inte, int[] T, int[] B)
            {
                string str = "";
                int i = 0;
                do
                {//依次处理4个字符

                    //获取当前范围:四个构造函数分别是x,y ,宽和高,已经可以确定字符的范围了。
                    Rectangle r = new Rectangle(IntS[i], T[i], (Inte[i] - IntS[i]) + 1, (B[i] - T[i]) + 1);
                    //裁减出来的图形
                    Bitmap bmp = Img.Clone(r, Img.PixelFormat);
                    //识别并保存出来
                    str = str + this.crImg(bmp);
                    //释放当前图片资源
                    bmp.Dispose();

                    //处理下一个。
                    i++;
                }
                while (i <= 3);
                return str;
            }


       

            /**//// <summary>
            /// 检测当前的图片是否符合社识别条件,通过分析字符数量
            /// </summary>
            /// <param name="Va"></param>
            /// <param name="IntS">ref:用来保存四个字符的左边点</param>
            /// <param name="IntE">ref:用来保存四个字符的右边点</param>
            /// <returns>字符数量</returns>
            private int chkImg(Array Va, ref int[] intS, ref int[] intE)
            {
                int IntRang=0; //一共找到多少段

                string[] str = (string[]) Va;
                intS = new int[] { -1, -1, -1, -1, -1, -1, -1 };  //保存段的开始数字,多申请几个,避免出问题
                intE = new int[] { -1, -1, -1, -1, -1, -1, -1 };  //保存段的结束数字,多申请几个,避免出问题
     
                for (int i = 0; i <= str.Length - 2; i++)
                {
                    int intCur = int.Parse(str[i]);//当前坐标
                    int IntPrew = int.Parse(str[i + 1]);//下一个坐标
                    if ((IntPrew - intCur) == 1)
                    {//如果2个数字相差一,表示这个数字还是连续的

                        if (intS[IntRang] == -1)
                        {//如果已经找到结尾了
                            intS[IntRang] = intCur;
                        }
                        if (i == (str.Length - 2))
                        { //如果到了倒数第二数字,最后一个数字就是结束了
                            intE[IntRang] = IntPrew;
                        }
                    }
                    else
                    {
                        intE[IntRang] = intCur;
                        IntRang++;
                    }
                }
                return (IntRang + 1);
            }

     
            /**//// <summary>
            /// 识别小图片中的数字
            /// </summary>
            /// <param name="Img">小图形</param>
            /// <returns>识别出来的字符</returns>
            private string crImg(Bitmap Img)
            {
                if (Img != null)
                {//检查图片
                    Color c;


                    if ((Img.Width == 6) & (Img.Height == 9))
                    {//宽6 高9的一定是1
                        return "1";
                    }


                    if ((Img.Width == 9) & (Img.Height == 12))
                    {//宽9 高12的一定是4
                        return "4";
                    }

                    if ((Img.Width == 8) & (Img.Height == 9))
                    {//如果宽是8 高是9的话

                        //找特殊点
                        Color c2 = Img.GetPixel(0, 1);
                        if (c2.ToArgb() == Color.Black.ToArgb())
                        {//如果0,1是黑点的话,就是2,否则就是0
                            return "2";
                        }
                        return "0";
                    }

                    if ((Img.Width == 8) & (Img.Height == 11))
                    {//宽8  高11
                        c = Img.GetPixel(2, 0);
                        if (c.ToArgb() == Color.Black.ToArgb())
                        {//也同样找特殊点来区分2.0
                            return "8";
                        }
                        return "6";
                    }
                    if ((Img.Width == 8) & (Img.Height == 12))
                    {//同上的方法区分3.5.7.9
                        //都可以使用特殊点来区分
                        c = Img.GetPixel(5, 2);
                        if (c.ToArgb() == Color.Black.ToArgb())
                        {
                            return "3";
                        }
                        c = Img.GetPixel(2, 4);
                        if (c.ToArgb() == Color.Black.ToArgb())
                        {
                            return "5";
                        }
                        c = Img.GetPixel(0, 0);
                        if (c.ToArgb() == Color.Black.ToArgb())
                        {
                            return "7";
                        }
                        c = Img.GetPixel(0, 5);
                        if (c.ToArgb() == Color.Black.ToArgb())
                        {
                            return "9";
                        }
                    }
                }
                return " ";
            }
         
        }
    }

  • 相关阅读:
    ZTUnity Profiler概述及Profiler window 说明
    利用反射球实现镜面效果
    (乱入)FingerGesture
    生成万花筒效果并截图
    (六)添加adb命令
    超时处理
    判断是否存在UI被触摸
    UI控件拖动失效
    (五)Unity插件生成
    (四)适配器Adapter
  • 原文地址:https://www.cnblogs.com/Fooo/p/1278416.html
Copyright © 2011-2022 走看看