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);         }

原文地址:https://www.cnblogs.com/wangzhenghua/p/8994305.html

时间: 2024-10-04 00:42:39

Aforge.net识别简易数字验证码问题的相关文章

如何识别高级的验证码

==Ph4nt0m Security Team== Issue 0x02, Phile #0x09 of 0x0A |=---------------------------------------------------------------------------=| |=-----------------------=[ 如何识别高级的验证码 ]=------------------------=| |=------------------------------------------

Python——pytessercat识别简单的验证码

什么是验证码 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computersand Humans Apart” (全自动区分计算机和人类的图灵测试)的缩写, 是一种区分用户是计算机还是人的公共全自动程序.可以防止:恶意破解密码.刷票.论坛灌水, 有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试. 这个问题可以由计算机生成并评判,但是必须只有人类才能解答.由于计算机无法解答CAPTCHA的问

Python 实现识别弱图片验证码

目前,很多网站为了防止爬虫肆意模拟浏览器登录,采用增加验证码的方式来拦截爬虫.验证码的形式有多种,最常见的就是图片验证码.其他验证码的形式有音频验证码,滑动验证码等.图片验证码越来越高级,识别难度也大幅提高,就算人为输入也经常会输错.本文主要讲解识别弱图片验证码. 1 图片验证码强度 图片验证码主要采用加干扰线.字符粘连.字符扭曲方式来增强识别难度. 加干扰线 加干扰线也分为两种,一种是线条跟字符同等颜色,另一种则线条的颜色是五颜六色. 字符粘连 各个字符之间的间隔比较小,互相依靠,能以分割.

简易数字钟设计

简易数字钟设计 一.摘要 信息时代,时间观念深入人心,所以掌握数字钟的设计具有一定的时代意义,并且使用Multisim进行分立元件设计数字钟,可以大大提升个人数字电路的素养. 设计思路是从上至下,先进行数字钟整体框架的设计,考虑各个子芯片的预留端口,再逐个设计各个子电路模块.最终完成了时钟显示,调时,闹钟,定点报时以及万年历的功能.并且总的控制点预留了新功能的接入口,这样子就可以十分方便的进行新功能的加入. 目录 简易数字钟设计... 1 一.摘要... 1 二.前期准备... 2 1.数电知识

随机生成数字验证码

protected void Page_Load(object sender, EventArgs e) { // 生成验证码 string checkCode = RandLetter(4); // 把新的验证码保存到Session中 Session["CheckCode"] = checkCode; // 输入验证码 CreateImages(checkCode); } /// <summary> /// 生成验证图片 /// </summary> ///

PHP 数字验证码

在php中实现验证码还是很方便的,关键点在于掌握php gd库与session的用法. 纵观网上php 生成验证码的例子,无不是php gd库与session相结合,并利用php 生成随机数的方法来完成. PHP验证码,可以分为很多种,包括 php 图片验证码,php 随机验证码,以及php 中文验证码等,根据不同的应用场合来使用不同的验证码. 这里分享一个php数字验证码,供大家参考. 1,数字验证码 /* *Filename:authpage.php */ session_start();

纯数字验证码

登录时常常要用到验证码验证,下面是一个简单的纯数字验证码,详细代码见image.jsp,将每次生成的验证码文本直接存入session中,登录时方便后台从session中取值验证: <%@ page contentType="image/jpeg" import="java.awt.*, java.awt.image.*,java.util.*,javax.imageio.*" pageEncoding="utf-8"%> <%!

servlet生成数字验证码

servlet生成一个数字验证码 1.设置背景 private void setBackGround(Graphics g) { g.setColor(Color.orange); g.fillRect(0, 0, WIDTH, HEIGHT); } 2.得到图片框 private void setBorder(Graphics g) { g.setColor(Color.black); g.drawRect(1, 1, WIDTH - 2, HEIGHT - 2); } 3.画干扰线 priv

python利用selenium库识别点触验证码

利用selenium库和超级鹰识别点触验证码(学习于静谧大大的书,想自己整理一下思路) 一.超级鹰注册:超级鹰入口 1.首先注册一个超级鹰账号,然后在超级鹰免费测试地方可以关注公众号,领取1000积分,基本上就够学习使用了.如果想一直用可以用,可以充值,不是很贵. 2.下载超级鹰的python库代码.代码 3.然后有测试案例,自己可以试着跑一跑代码. 二.使用selenium库来识别点触式验证码: 1.首先是找一个使用点触式二维码的网站:(这个真的是比较难找了,由于静谧大大书上的网站被封了,我找