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

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

  这个系列我们玩玩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, , ); g.Dispose();

<1>图片灰度化

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

专门的类一步搞定,简洁方便。

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

<2>二值化

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

也有相似的类进行处理

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

<3> 去噪点

从上面的图片可以发现有很多红点点,搞得像皮肤病一样,仔细观察可以看到这种噪点具有独立,体积小的特征,所以判断的标准就是如果

图中某个区块的大小在我设置的阈值内,就将其去掉,同样也有专门的类进行处理。

            //去噪点
new BlobsFiltering(, , 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 = ; x < b.Width; x++)
{
for (int y = ; y < b.Height; y++)
{
//获取当前像素点像素
var pixel = b.GetPixel(x, y); //说明是黑色点
if (pixel.R == )
{
cols[x] = ++cols[x];
}
}
} int left = , right = ; for (int i = ; i < cols.Length; i++)
{
//说明该列有像素值(为了防止像素干扰,去噪后出现空白的问题,所以多判断一下,防止切割成多个)
if (cols[i] > || (i + < cols.Length && cols[i + ] > ))
{
if (left == )
{
//切下来图片的横坐标left
left = i;
}
else
{
//切下来图片的横坐标right
right = i;
}
}
else
{
//说明已经有切割图了,下面我们进行切割处理
if ((left > || right > ))
{
Crop corp = new Crop(new Rectangle(left, , right - left + , b.Height)); var small = corp.Apply(b); //居中,将图片放在20*50的像素里面 list.Add(small);
} left = right = ;
}
} 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 = ; y < segb.Height; y++)
{
for (int x = ; x < segb.Width; x++)
{
//获取当前像素点像素
var pixel = segb.GetPixel(x, y); //说明是黑色点
if (pixel.R == )
{
rows[y] = ++rows[y];
}
}
} int bottom = , top = ; for (int y = ; y < rows.Length; y++)
{
//说明该行有像素值(为了防止像素干扰,去噪后出现空白的问题,所以多判断一下,防止切割成多个)
if (rows[y] > || (y + < rows.Length && rows[y + ] > ))
{
if (top == )
{
//切下来图片的top坐标
top = y;
}
else
{
//切下来图片的bottom坐标
bottom = y;
}
}
else
{
//说明已经有切割图了,下面我们进行切割处理
if ((top > || bottom > ) && bottom - top > )
{
Crop corp = new Crop(new Rectangle(, top, segb.Width, bottom - top + )); var small = corp.Apply(segb); corplist.Add(small);
} top = bottom = ;
}
}
} return corplist;
}

<5> 图片精处理

  这里要注意的是,比如数字“2”,切除上下左右的空白后,再加上噪点的干扰,不一定每次切下来的图片大小都一样,所以这里

为了方便更好的识别,我们需要重置下图片的大小,并且将“数字2”进行文字居中。

         /// <summary>
/// 重置图片的指定大小并且居中
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public List<Bitmap> ToResizeAndCenterIt(List<Bitmap> list, int w = , int h = )
{
List<Bitmap> resizeList = new List<Bitmap>(); for (int i = ; 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(, , w, h)); list[i] = corpFilter.Apply(list[i]); //再反转回去
list[i] = new Invert().Apply(list[i]); //计算中心位置
int centerX = (w - sw) / ;
int centerY = (h - sh) / ; 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(, ); }).ToList(); var result = new List<string>(); ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.9f); //这里面有四张图片,进行四张图的模板匹配
for (int i = ; i < list.Count; i++)
{
float max = ;
int index = ; for (int j = ; j < templateList.Count; j++)
{
var compare = templateMatching.ProcessImage(list[i], templateList[j]); if (compare.Length > && compare[].Similarity > max)
{
//记录下最相似的
max = compare[].Similarity;
index = j;
}
} result.Add(templateListFileName[index]);
}

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

Aforge.net之旅——开篇:从识别验证码开始的更多相关文章

  1. 【转载】loadrunner使用system()函数调用Tesseract-OCR识别验证码遇到的问题

    俗话说前人栽树,后人乘凉,此话一点不假,结合云层的一遍文章:http://bbs.51testing.com/thread-533920-1-1.html,知道还有一个Tesseract-OCR可以用 ...

  2. C#识别验证码技术-Tesseract

    相信大家在开发一些程序会有识别图片上文字(即所谓的OCR)的需求,比如识别车牌.识别图片格式的商品价格.识别图片格式的邮箱地址等等,当然需求最多的还是识别验证码.如果要完成这些OCR的工作,需要你掌握 ...

  3. java识别验证码

    所需资源下载链接(资源免费,重在分享) Tesseract:http://download.csdn.net/detail/chenyangqi/9190667 jai_imageio-1.1-alp ...

  4. loadrunner使用system()函数调用Tesseract-OCR识别验证码遇到的问题

    俗话说前人栽树,后人乘凉,此话一点不假,结合云层的一遍文章:http://bbs.51testing.com/thread-533920-1-1.html,知道还有一个Tesseract-OCR可以用 ...

  5. python识别验证码——一般的数字加字母验证码识别

    1.验证码的识别是有针对性的,不同的系统.应用的验证码区别有大有小,只要处理好图片,利用好pytesseract,一般的验证码都可以识别 2.我在识别验证码的路上走了很多弯路,重点应该放在怎么把图片处 ...

  6. python识别验证码——PIL,pytesser,pytesseract的安装

    1.使用Python识别验证码需要安装Python的图像处理模块(PIL.pytesser.pytesseract) (安装过程需要pip,在我的Python中已经安装pip了,pip的安装就不在赘述 ...

  7. Python爬虫入门教程 60-100 python识别验证码,阿里、腾讯、百度、聚合数据等大公司都这么干

    常见验证码 之前的博客中已经解决了一些常见验证码的问题,但是验证码是层出不穷的,目前解决验证码除了通过常规手段解决以外,还可以通过人工智能领域的深度学习去解决 深度学习?! 无疑对爬虫coder提高了 ...

  8. Java使用J4L识别验证码

    1.首先要下载j4l的相应文件和jar 下载地址:http://www.java4less.com/ocrtools/ocrtools.php?info=download 2.下载完成之后解压,文件目 ...

  9. python 基于机器学习识别验证码

    1.背景    验证码自动识别在模拟登陆上使用的较为广泛,一直有耳闻好多人在使用机器学习来识别验证码,最近因为刚好接触这方面的知识,所以特定研究了一番.发现网上已有很多基于machine learni ...

随机推荐

  1. 【C#进阶系列】17 委托

    委托主要是为了实 现回调函数机制,可以理解为函数指针(唯一不同的在于多了委托链这个概念). 然而用的时候可以这么理解,但是委托的内部机制是比较复杂的. 一个委托的故事 delegate void ra ...

  2. php实现中文字符串截取各种问题

    用php截取中文字符串会出现各种问题,做一简单汇总,文中的问题暂时还未解决,有大神解决了问题欢迎指教 <?php header('Content-Type:text/html;charset=u ...

  3. C++析构函数调用异常问题研究

    最近又遇到一个奇葩问题,程序在自己的开发机器和某些机器上运行完好,但是在测试人员的几台机器上运行就直接推出了.开始以为是出现了野指针,因为delete野指针时程序会直接退出.代码翻来覆去过来即便确认没 ...

  4. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  5. svn利用钩子实现代码同步到web目录

    思路:  找 到SVN Server中的仓库(Repositories)文件夹的位置,在相应的项目文件夹中找到hooks文件夹.在该文件夹中添加一个post- commit文件:当有commit动作发 ...

  6. go语言 新手学习笔记 go基础教程

    目前这方面的资料相对较少,自己手动整理汇集. 第一章:安装 第一节:下载go语言 第二节:windows 安装 go语言 第三节: 第二章:基本语法 第一节:类型 .

  7. vue单页面程序

    gitHub地址:https://github.com/lily1010/vue_singlePage 举个栗子: <!DOCTYPE html> <html> <hea ...

  8. C语言 指针例解

    在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值.由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元 ...

  9. SAP 录屏BDC使用—实例

    1)  输入TCode:SHDB进入BDC录制初始界面,该界面可以实现已创建BDC Session信息的查看.删除及锁定等操作 2)  单击工具栏 Newrecording 按钮创建一个新的BDC,系 ...

  10. 电商CRM的痛点在哪里?

    观电商风云,风起云涌,如何寻找新客户及维护老客户,抢占市场,此时迫在眉睫.在大家所认为的CRM就是发发短信,发发邮件等形式去推送活动信息,但在三疯看来,做CRM的关键词是“互动”,而不是简单的促销. ...