• Aforge.net识别简易数字验证码问题


    参考:https://www.bbsmax.com/A/rV57LjWGdP/

    https://blog.csdn.net/louislong007/article/details/47683035

    简易验证码样例:

    验证码识别流程:

    首先进行图像获取:火狐浏览器,找到获取验证码地址,获取验证码图像,传递给类,直接获取到验证码!

    验证码获取:

             /// <summary>
             /// 通过GET方式获取验证码
             /// </summary>
             /// <param name="Url">url</param>
             /// <param name="postDataStr">GET数据</param>
             /// <param name="cookie">GET容器</param>
             /// <returns></returns>
             public void SendDataByGET1(string Url, ref CookieContainer cookie)
             {
                 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
                 if (cookie.Count == 0)
                 {
                     request.CookieContainer = new CookieContainer();
                     cookie = request.CookieContainer;
                 }
                 else
                 {
                     request.CookieContainer = cookie;
                 }
    
                 request.Method = "GET";
                 request.ContentType = "text/html;charset=UTF-8";
    
                 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    
    
                 MemoryStream ms = null;
                 using (var stream = response.GetResponseStream())
                 {
                     Byte[] buffer = new Byte[response.ContentLength];
                     int offset = 0, actuallyRead = 0;
                     do
                     {
                         actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);
                         offset += actuallyRead;
                     }
                     while (actuallyRead > 0);
                     ms = new MemoryStream(buffer);
                 }
    
                 b = new Bitmap(ms);
    
                 //aforge只接受像素格式为24/32bpp的像素格式图片,所以处理前,先进行格式转化
                 var bnew = new Bitmap(b.Width, b.Height,PixelFormat.Format24bppRgb);
    
                 Graphics g = Graphics.FromImage(bnew);
    
                 g.DrawImage(b, 0, 0);
    
                 g.Dispose();
           
                 pictureBox1.Image = bnew;
            
                 //b = new Threshold(50).Apply(b);
                 response.Close();
               
               string  strCookies = request.CookieContainer.GetCookieHeader(request.RequestUri); //把cookies转换成字符串
    
            textBox2.Text=new VerificationCodeProcess().GetVerificationCode(bnew).ToString();
    
                 //Stream myResponseStream = response.GetResponseStream();
                 //StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
                 //string retString = myStreamReader.ReadToEnd();
                 //myStreamReader.Close();
                 //myResponseStream.Close();
    
               //MessageBox.Show(strCookies);
             }

    验证码处理:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Drawing.Printing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    //
    using System.Net;
    using System.IO;
    using Model;
    using BLL;
    using Model;
    using AForge;
    using AForge.Imaging;
    using AForge.MachineLearning;
    using System.Drawing.Drawing2D;
    using AForge.Imaging.Filters;
    
    namespace EmsService
    {
        public class VerificationCodeProcess
        {
            public int GetVerificationCode(Bitmap bmp)
            {
                //灰度
                bmp = ToGray(bmp);
                //  MessageBox.Show(b.PixelFormat.ToString());
                //二进制//
                // pictureBox3.Image = ConvertToBinaryImage(new Bitmap(pictureBox2.Image));
                bmp = ConvertToBinaryImage(bmp);
                //   MessageBox.Show(b.PixelFormat.ToString());
                //分割
                List<Bitmap> bmList = ToResizeAndCenterIt(Crop_X(Crop_Y(bmp)));
                //二进制化
                StringBuilder sb = new StringBuilder();
                List<string> lls = PP(bmList);
                int top = Convert.ToInt32(lls[0]);
                int last = Convert.ToInt32(lls[2]);
                int result = 0;
                if (lls[1] == "-")
                {
                    result = top - last;
                }
                else
                {
                    result = top + last;
                }
                return result;
            }
            /// <summary>
            /// 灰度处理
            /// </summary>
            /// <param name="bmp"></param>
            /// <returns></returns>
            public Bitmap ToGray(Bitmap bmp)
            {
                Bitmap bm = new Bitmap(bmp.Width, bmp.Height);
    
                for (int i = 0; i < bmp.Width; i++)
                {
                    for (int j = 0; j < bmp.Height; j++)
                    {
                        // 获取该点的像素的RGB的颜色  
                        Color color = bmp.GetPixel(i, j);
                        // 利用公式计算灰度值  
                        // 根据YUV的颜色空间中,Y的分量的物理意义是点的亮度,由该值反映亮度等级,  
                        // 根据RGB和YUV颜色空间的变化关系可建立亮度Y与R、G、B三个颜色分量的对应:  
                        // Y=0.3R+0.59G+0.11B,以这个亮度值表达图像的灰度值  
                        int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
                        Color newColor = Color.FromArgb(gray, gray, gray);
                        bm.SetPixel(i, j, newColor);
                    }
                }
                return bm;
            }
            /// <summary>
            /// 二进制化
            /// </summary>
            /// <param name="bmp"></param>
            /// <returns></returns>
            public Bitmap ConvertToBinaryImage(Bitmap bmp)
            {
                Bitmap bm = new Bitmap(bmp.Width, bmp.Height);
                int average = 0;
                for (int i = 0; i < bmp.Width; i++)
                {
                    for (int j = 0; j < bmp.Height; j++)
                    {
                        Color color = bmp.GetPixel(i, j);
                        average += color.B;
                    }
                }
                average = 60;
    
                for (int i = 0; i < bmp.Width; i++)
                {
                    for (int j = 0; j < bmp.Height; j++)
                    {
                        //获取该点的像素的RGB的颜色  
                        Color color = bmp.GetPixel(i, j);
                        int value = 255 - color.B;
                        Color newColor = value > average ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255);
                        bm.SetPixel(i, j, newColor);
                    }
                }
                return bm;
            }
            /// <summary>
            /// 重置图片的指定大小并且居中
            /// </summary>
            /// <param name="list"></param>
            /// <returns></returns>
            public List<Bitmap> ToResizeAndCenterIt(List<Bitmap> list, int w = 20, int h = 20)
            {
                List<Bitmap> resizeList = new List<Bitmap>();
    
    
                for (int i = 0; i < list.Count; i++)
                {
                    //MessageBox.Show(list[i].PixelFormat.ToString());
                    //反转一下图片
                    var bnew10 = new Bitmap(list[i].Width, list[i].Height, PixelFormat.Format24bppRgb);
    
                    Graphics g10 = Graphics.FromImage(bnew10);
    
                    g10.DrawImage(list[i], 0, 0);
    
                    g10.Dispose();
                    list[i] = bnew10;
    
                    list[i] = new Invert().Apply(list[i]);
    
                    int sw = list[i].Width;
                    int sh = list[i].Height;
    
                    Crop corpFilter = new Crop(new Rectangle(0, 0, w, h));
    
                    list[i] = corpFilter.Apply(list[i]);
                    //var bnew1 = new Bitmap(list[i].Width, list[i].Height, PixelFormat.Format24bppRgb);
    
                    //Graphics g1 = Graphics.FromImage(bnew1);
    
                    //g1.DrawImage(list[i], 0, 0);
    
                    //g1.Dispose();
                    //再反转回去
                    list[i] = new Invert().Apply(list[i]);
    
                    // //计算中心位置
                    int centerX = (w - sw) / 2;
                    int centerY = (h - sh) / 2;
                    var bnew2 = new Bitmap(list[i].Width, list[i].Height, PixelFormat.Format24bppRgb);
    
                    Graphics g2 = Graphics.FromImage(bnew2);
    
                    g2.DrawImage(list[i], 0, 0);
    
                    g2.Dispose();
                    list[i] = new CanvasMove(new AForge.IntPoint(centerX, centerY), Color.White).Apply(list[i]);
    
                    resizeList.Add(list[i]);
                }
    
                return resizeList;
            }
    
            /// <summary>
            /// 按照 Y 轴线 切割
            /// (丢弃等于号)
            /// </summary>
            /// <param name="?"></param>
            /// <returns></returns>
            public List<Bitmap> Crop_Y(Bitmap b)
            {
                var list = new List<Bitmap>();
    
                //统计每一列的“1”的个数,方便切除
                int[] cols = new int[b.Width];
    
                /*
                   *  纵向切割
                   */
                for (int x = 0; x < b.Width; x++)
                {
                    for (int y = 0; y < b.Height; y++)
                    {
                        //获取当前像素点像素
                        var pixel = b.GetPixel(x, y);
    
                        //说明是黑色点
                        if (pixel.R == 0)
                        {
                            cols[x] = ++cols[x];
                        }
                    }
                }
    
                int left = 0, right = 0;
    
                for (int i = 0; i < cols.Length; i++)
                {
                    //说明该列有像素值(为了防止像素干扰,去噪后出现空白的问题,所以多判断一下,防止切割成多个)
                    if (cols[i] > 0 || (i + 1 < cols.Length && cols[i + 1] > 0))
                    {
                        if (left == 0)
                        {
                            //切下来图片的横坐标left
                            left = i;
                        }
                        else
                        {
                            //切下来图片的横坐标right
                            right = i;
                        }
                    }
                    else
                    {
                        //说明已经有切割图了,下面我们进行切割处理
                        if ((left > 0 || right > 0))
                        {
                            Crop corp = new Crop(new Rectangle(left, 0, right - left + 1, b.Height));
    
                            var small = corp.Apply(b);
    
                            //居中,将图片放在20*50的像素里面
    
                            list.Add(small);
                        }
    
                        left = right = 0;
                    }
                }
    
                return list;
            }
    
            /// <summary>
            /// 按照 X 轴线 切割
            /// </summary>
            /// <param name="b"></param>
            /// <returns></returns>
            public List<Bitmap> Crop_X(List<Bitmap> list)
            {
                var corplist = new List<Bitmap>();
    
                //再对分割的图进行上下切割,取出上下的白边
                foreach (var segb in list)
                {
                    //统计每一行的“1”的个数,方便切除
                    int[] rows = new int[segb.Height];
    
                    /*
                     *  横向切割
                       */
                    for (int y = 0; y < segb.Height; y++)
                    {
                        for (int x = 0; x < segb.Width; x++)
                        {
                            //获取当前像素点像素
                            var pixel = segb.GetPixel(x, y);
    
                            //说明是黑色点
                            if (pixel.R == 0)
                            {
                                rows[y] = ++rows[y];
                            }
                        }
                    }
                    int bottom = 0, top = 0;
    
                    for (int y = 0; y < rows.Length; y++)
                    {
                        //说明该行有像素值(为了防止像素干扰,去噪后出现空白的问题,所以多判断一下,防止切割成多个)
                        if (rows[y] > 0 || (y + 1 < rows.Length && rows[y + 1] > 0))
                        {
                            if (top == 0)
                            {
                                //切下来图片的top坐标
                                top = y;
                            }
                            else
                            {
                                //切下来图片的bottom坐标
                                bottom = y;
                            }
                        }
                        else
                        {
                            //说明已经有切割图了,下面我们进行切割处理
                            if ((top > 0 || bottom > 0) && bottom - top > 0)
                            {
                                Crop corp = new Crop(new Rectangle(0, top, segb.Width, bottom - top + 1));
    
                                var small = corp.Apply(segb);
    
                                corplist.Add(small);
                            }
                            top = bottom = 0;
                        }
                    }
                }
    
                return corplist;
            }
            //模式匹配
            public List<string> PP(List<Bitmap> list)
            {
                var files = Directory.GetFiles(Environment.CurrentDirectory + "\temp\");
    
                var templateList = files.Select(i => { return new Bitmap(i); }).ToList();
                var templateListFileName = files.Select(i => { return i.Substring(i.Length - 5).Substring(0, 1); }).ToList();
    
                var result = new List<string>();
    
                ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.9f);
    
                //这里面有四张图片,进行四张图的模板匹配
                for (int i = 0; i < 3; i++)
                {
                    float max = 0;
                    int index = 0;
    
                    for (int j = 0; j < templateList.Count; j++)
                    {
                        var compare = templateMatching.ProcessImage(list[i], templateList[j]);
    
                        if (compare.Length > 0 && compare[0].Similarity > max)
                        {
                            //记录下最相似的
                            max = compare[0].Similarity;
                            index = j;
                        }
                    }
    
                    result.Add(templateListFileName[index]);
                }
                return result;
            }
    
        }
    }

    效果图:

             /// <summary>         /// 通过GET方式获取验证码         /// </summary>         /// <param name="Url">url</param>         /// <param name="postDataStr">GET数据</param>         /// <param name="cookie">GET容器</param>         /// <returns></returns>         public void SendDataByGET1(string Url, ref CookieContainer cookie)         {             HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);             if (cookie.Count == 0)             {                 request.CookieContainer = new CookieContainer();                 cookie = request.CookieContainer;             }             else             {                 request.CookieContainer = cookie;             }
                 request.Method = "GET";             request.ContentType = "text/html;charset=UTF-8";
                 HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                 MemoryStream ms = null;             using (var stream = response.GetResponseStream())             {                 Byte[] buffer = new Byte[response.ContentLength];                 int offset = 0, actuallyRead = 0;                 do                 {                     actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);                     offset += actuallyRead;                 }                 while (actuallyRead > 0);                 ms = new MemoryStream(buffer);             }
                 b = new Bitmap(ms);
                 //aforge只接受像素格式为24/32bpp的像素格式图片,所以处理前,先进行格式转化             var bnew = new Bitmap(b.Width, b.Height,PixelFormat.Format24bppRgb);
                 Graphics g = Graphics.FromImage(bnew);
                 g.DrawImage(b, 0, 0);
                 g.Dispose();         //    //                    ////灰度         //    Bitmap temp;         //    temp = AForge.Imaging.Image.Clone(b, b.PixelFormat);         //    b = new Grayscale(0.2125, 0.7154, 0.0721).Apply(b);         //    //二值化            // b = new Threshold(50).Apply(b);                  pictureBox1.Image = bnew;                     //b = new Threshold(50).Apply(b);             response.Close();                      string  strCookies = request.CookieContainer.GetCookieHeader(request.RequestUri); //把cookies转换成字符串
            textBox2.Text=new VerificationCodeProcess().GetVerificationCode(bnew).ToString();
                 //Stream myResponseStream = response.GetResponseStream();             //StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));             //string retString = myStreamReader.ReadToEnd();             //myStreamReader.Close();             //myResponseStream.Close();
               //MessageBox.Show(strCookies);         }

  • 相关阅读:
    金刚经与心经之比较
    ECMWF 和 GFS 模型
    LSTM之父Jürgen Schmidhuber评图灵
    STM32相关知识点
    最全C++11/14/17/20/23 的新特性代码案例
    C++ 在线工具
    如何在 Proteus 中设计 PCB
    STM32电源框图解析
    【新特性速递】填一个坑
    【新特性速递】表格加载速度足足 3 倍提升,爱了爱了
  • 原文地址:https://www.cnblogs.com/wangzhenghua/p/8994305.html
Copyright © 2020-2023  润新知