使用C#的aforge类库识别验证码实例

时间过得真快啊,转眼今年就要过去了,大半年都没有写博客了,要说时间嘛,花在泡妹子和搞英语去了,哈哈。。。前几天老大问我

怎么这么长时间都没写博客了,好吧,继续坚持,继续分享我的心得体会。

  这个系列我们玩玩aforge.net,套用官方都话就是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的

资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域,这个系列研究的重点

就是瞎几把搞下AForge.Imaging这个命名空间下面的东东,下载网址:http://www.aforgenet.com/framework/downloads.html

对了,不知道有多少公司是用得仕卡作为员工的福利卡,我们公司就是这样的,每个月公司都会充值一些money,然后我们这些屁码农每个月15号就都开心的去看看发了多少。

上去看了后,哟呵~ 还有个90年代的验证码,我想这年头估计找到这样验证码的网站已经不多了,如果懂一点图像处理都话,这张验证码

跟没有一个样,谢谢。。。这篇我们看看怎么去识别它。

一: 验证码处理

1.  一般处理原则

这种验证码为什么说跟没有一样,第一点:字体规范工整,第二点:不旋转扭曲粘连,第三点:字体颜色单一,下面看处理步骤。

这里要注意的是,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();

<1>图片灰度化

这是图像识别通常都要走的第一步,图片灰度化有助于减少后续对rgb的计算量,同时也方便我们进行二值化,在aforge中我们有专门的类一步搞定,简洁方便。

代码如下:

//灰度化
            b = new Grayscale(0.2125, 0.7154, 0.0721).Apply(b);

<2>二值化

二值化顾名思义就是二种值,比如非白即黑,非黑即白,那么白和黑的标准就需要提供一个阈值,大于或者小于怎么样,在aforge同样也有相似的类进行处理

代码如下:

//二值化
            b = new Threshold(50).Apply(b);

<3> 去噪点

从上面的图片可以发现有很多红点点,搞得像皮肤病一样,仔细观察可以看到这种噪点具有独立,体积小的特征,所以判断的标准就是如果图中某个区块的大小在我设置的阈值内,就将其去掉,同样也有专门的类进行处理。

代码如下:

//去噪点
            new BlobsFiltering(1, 1, b.Width, b.Height).Apply(b);

这里具体怎么传递参数,后续系列会慢慢解读。

<4>切割图片

切图片的好处在于我们需要知道真正要识别的元素的有效范围是多大,同时也方便我们将这些图片作为模板保存下来。

代码如下:

代码如下:

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

<5> 图片精处理

  这里要注意的是,比如数字“2”,切除上下左右的空白后,再加上噪点的干扰,不一定每次切下来的图片大小都一样,所以这里为了方便更好的识别,我们需要重置下图片的大小,并且将“数字2”进行文字居中。

代码如下:

/// <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++)
            {
                //反转一下图片
                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]);

//再反转回去
                list[i] = new Invert().Apply(list[i]);

//计算中心位置
                int centerX = (w - sw) / 2;
                int centerY = (h - sh) / 2;

list[i] = new CanvasMove(new IntPoint(centerX, centerY), Color.White).Apply(list[i]);

resizeList.Add(list[i]);
            }

return resizeList;
        }

其实精处理后,这些图片就可以作为我们的模板库的图片了,可以将每张模板图都标记下具体的数字,后续我们再遇到时,计算下其相似度就可以了,下面就是已经制作好的模板。

<6> 模板匹配识别

  既然模板图片都制作好了,一切都差不多水到渠成了,下次来的验证码我都切好后做成精图片后跟模板进行匹配,在afroge里面

有一个ExhaustiveTemplateMatching,专门用来进行模板匹配用的,很方便。

代码如下:

ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.9f);

这里的0.9f就是设定的阈值,只有大于0.9的阈值,我才认为该模板与目标图片相似,然后在所有大于0.9的相似度中取到最大的一个作为

我们最后识别的图像。

代码如下:

var files = Directory.GetFiles(Environment.CurrentDirectory + "\\Template\\");

var templateList = files.Select(i => { return new Bitmap(i); }).ToList();
            var templateListFileName = files.Select(i => { return i.Substring(30, 1); }).ToList();

var result = new List<string>();

ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.9f);

//这里面有四张图片,进行四张图的模板匹配
            for (int i = 0; i < list.Count; 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]);
            }

最后的效果还是不错的,识别率基本100%吧。

(0)

相关推荐

  • C#结合AForge实现摄像头录像

    输出为MP4需要用到ffmpeg相关的文件,我打包的库已经带了,去官网找的库可以在这个目录找到: 2: 添加这些引用: 3: 两个全局变量: //用来操作摄像头 private VideoCaptureDevice Camera = null; //用来把每一帧图像编码到视频文件 private VideoFileWriter VideoOutPut = new VideoFileWriter(); 开始代码: //获取摄像头列表 var devs = new FilterInfoCollect

  • 使用C#的aforge类库识别验证码实例

    时间过得真快啊,转眼今年就要过去了,大半年都没有写博客了,要说时间嘛,花在泡妹子和搞英语去了,哈哈...前几天老大问我 怎么这么长时间都没写博客了,好吧,继续坚持,继续分享我的心得体会. 这个系列我们玩玩aforge.net,套用官方都话就是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的 资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域,这个系列研究的重点 就是瞎几把搞下AForge.Imaging这个命

  • Python验证码识别处理实例

    一.准备工作与代码实例 (1)安装PIL:下载后是一个exe,直接双击安装,它会自动安装到C:\Python27\Lib\site-packages中去, (2)pytesser:下载解压后直接放C:\Python27\Lib\site-packages(根据你安装的Python路径而不同),同时,新建一个pytheeer.pth,内容就写pytesser,注意这里的内容一定要和pytesser这个文件夹同名,意思就是pytesser文件夹,pytesser.pth,及内容都要一样! (3)Te

  • Python完全识别验证码自动登录实例详解

    1.直接贴代码 #!C:/Python27 #coding=utf-8 from selenium import webdriver from selenium.webdriver.common.keys import Keys from pytesser import * from PIL import Image,ImageEnhance,ImageFilter from selenium.common.exceptions import NoSuchElementException,Tim

  • Selenium+Tesseract-OCR智能识别验证码爬取网页数据的实例

    目录 1.项目需求描述 2.整体思路 3.功能实现 1.项目需求描述 通过订单号获取某系统内订单的详细数据,不需要账号密码的登录验证,但有图片验证码的动态识别,将获取到的数据存到数据库. 2.整体思路 1.通过Selenium技术,无窗口模式打开浏览器 2.在输入框中动态输入订单号 3.将图片验证码截图保存到本地 4.通过Tesseract-OCR技术去本地识别验证码转化为文字 5.将获取的验证码输入输入框 6.点击查询获取列表数据 3.功能实现 1.下载并安装Google浏览器,安装Googl

  • python验证码识别的实例详解

    其实关于验证码识别涉及很多方面的内容,入手难度大,但是入手后,可拓展性又非常广泛,可玩性极强,成就感也很足,对这感兴趣的朋友们下面跟着小编一起来学习学习吧. 依赖 sudo apt-get install python-imaging sudo apt-get install tesseract-ocr pip install pytesseract 利用google ocr来识别验证码 from PIL import Image import pytesseract image = Image

  • python识别验证码图片实例详解

    在编写自动化测试用例的时候,每次登录都需要输入验证码,后来想把让python自己识别图片里的验证码,不需要自己手动登陆,所以查了一下识别功能怎么实现,做一下笔记. 首选导入一些用到的库,re.Image.pytesseract.selenium.time import re # 用于正则 from PIL import Image # 用于打开图片和对图片处理 import pytesseract # 用于图片转文字 from selenium import webdriver # 用于打开网站

  • python识别验证码的思路及解决方案

    1.介绍 在爬虫中经常会遇到验证码识别的问题,现在的验证码大多分计算验证码.滑块验证码.识图验证码.语音验证码等四种.本文就是识图验证码,识别的是简单的验证码,要想让识别率更高,识别的更加准确就需要花很多的精力去训练自己的字体库. 识别验证码通常是这几个步骤: (1)灰度处理 (2)二值化 (3)去除边框(如果有的话) (4)降噪 (5)切割字符或者倾斜度矫正 (6)训练字体库 (7)识别 这6个步骤中前三个步骤是基本的,4或者5可根据实际情况选择是否需要. 经常用的库有pytesseract(

  • 基于Django的python验证码(实例讲解)

    验证码 在用户注册.登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻一些服务器的压力 使用验证码也是一种有效的防止crsf的方法 验证码效果如下图: 验证码视图 新建viewsUtil.py,定义函数verifycode 此段代码用到了PIL中的Image.ImageDraw.ImageFont模块,需要先安装Pillow(3.4.1)包, 详细文档参考 http://pillow.readthedocs.io/en/3.4.x/ Image表示画布对象

  • SpringMVC下获取验证码实例详解

    SpringMVC下获取验证码实例详解 前言: 1.用户一开始登录的时候, 不建议出现验证码, 这一点在很多网站上已经体现的很好了, 只有当用户连续输错三次或者以上才会要求用户输入验证码. 2.记录用户输错次数最好不要使用 session 来记录, 因为 session 是跟客户端浏览器会话有关的, 如果用重启浏览器或者换新的浏览器再来登录或者试错, 就是新的回话了, 原来记录的错误次数就失效了. 建议此处采用缓存机制来实现, 简单处理就是采用 Map<用户登录id, 错误次数> 来实现, 如

  • java仿Servlet生成验证码实例详解

    java仿Servlet生成验证码实例详解 实现原理:使用BufferedImage对象的Graphics来进行绘制,然后输出成一张图片进行保存 实现代码及详解: public class validateCode{ private static Random rand = new Random(); public static void main(String[] args){ int val1 = rand.nextInt(9); int val2 = rand.nextInt(9); in

随机推荐