Aforge.net之旅——开篇:从识别验证码开始
时间过得真快啊,转眼今年就要过去了,大半年都没有写博客了,要说时间嘛,花在泡妹子和搞英语去了,哈哈。。。前几天老大问我
怎么这么长时间都没写博客了,好吧,继续坚持,继续分享我的心得体会。
这个系列我们玩玩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之旅——开篇:从识别验证码开始的更多相关文章
- 【转载】loadrunner使用system()函数调用Tesseract-OCR识别验证码遇到的问题
俗话说前人栽树,后人乘凉,此话一点不假,结合云层的一遍文章:http://bbs.51testing.com/thread-533920-1-1.html,知道还有一个Tesseract-OCR可以用 ...
- C#识别验证码技术-Tesseract
相信大家在开发一些程序会有识别图片上文字(即所谓的OCR)的需求,比如识别车牌.识别图片格式的商品价格.识别图片格式的邮箱地址等等,当然需求最多的还是识别验证码.如果要完成这些OCR的工作,需要你掌握 ...
- java识别验证码
所需资源下载链接(资源免费,重在分享) Tesseract:http://download.csdn.net/detail/chenyangqi/9190667 jai_imageio-1.1-alp ...
- loadrunner使用system()函数调用Tesseract-OCR识别验证码遇到的问题
俗话说前人栽树,后人乘凉,此话一点不假,结合云层的一遍文章:http://bbs.51testing.com/thread-533920-1-1.html,知道还有一个Tesseract-OCR可以用 ...
- python识别验证码——一般的数字加字母验证码识别
1.验证码的识别是有针对性的,不同的系统.应用的验证码区别有大有小,只要处理好图片,利用好pytesseract,一般的验证码都可以识别 2.我在识别验证码的路上走了很多弯路,重点应该放在怎么把图片处 ...
- python识别验证码——PIL,pytesser,pytesseract的安装
1.使用Python识别验证码需要安装Python的图像处理模块(PIL.pytesser.pytesseract) (安装过程需要pip,在我的Python中已经安装pip了,pip的安装就不在赘述 ...
- Python爬虫入门教程 60-100 python识别验证码,阿里、腾讯、百度、聚合数据等大公司都这么干
常见验证码 之前的博客中已经解决了一些常见验证码的问题,但是验证码是层出不穷的,目前解决验证码除了通过常规手段解决以外,还可以通过人工智能领域的深度学习去解决 深度学习?! 无疑对爬虫coder提高了 ...
- Java使用J4L识别验证码
1.首先要下载j4l的相应文件和jar 下载地址:http://www.java4less.com/ocrtools/ocrtools.php?info=download 2.下载完成之后解压,文件目 ...
- python 基于机器学习识别验证码
1.背景 验证码自动识别在模拟登陆上使用的较为广泛,一直有耳闻好多人在使用机器学习来识别验证码,最近因为刚好接触这方面的知识,所以特定研究了一番.发现网上已有很多基于machine learni ...
随机推荐
- Asp.net Mvc模块化开发之“部分版本部分模块更新(上线)”
项目开发从来就不是一个简单的问题.更难的问题是维护其他人开发的项目,并且要修改bug.如果原系统有重大问题还需要重构. 怎么重构系统不是本文探讨的问题,但是重构后如何上线部署和本文关系密切.这个大家可 ...
- mvc 修改 删除 linq
Models文件夹里面可以Linq,Entity两种映射框架,也允许有ADO的操作,甚至可以ADO代码和映射代码一起操作 控制器当中允许有相同的方法名,类似在做修改时有两个Modify方法,但是MVC ...
- C++静态库和动态库的区别
转自http://www.cnblogs.com/skynet/p/3372855.html 什么是库? 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人 ...
- R语言XML格式数据导入与处理
数据解析 XML是一种可扩展标记语言,它被设计用来传输和存储数据.XML是各种应用程序之间进行数据传输的最常用的工具.它与Access,Oracle和SQL Server等数据库不同,数据库提供了更强 ...
- [css] CSS3中的单位
FROM http://www.qianduan.net/understand-the-unit-of-length-in-the-css.html CSS3中的单位: css3中引入了一些新的单位: ...
- mysql Access denied for user root@localhost错误解决方法总结(转)
mysql Access denied for user root@localhost错误解决方法总结(转) mysql Access denied for user \'root\'@\'local ...
- Linux更改主机名-适用于abuntu
今天复制了个ubuntu虚拟机,于是想更改下主机名以作区别.这是搜到的比较完整的资料,适用abuntu,不过其他linux系统还有待求证. 1.查看主机名 在Ubuntu系统中,快速查看主机名有多种方 ...
- MVC初认
初探MVC 何谓MVC 简单来说就是开发程序时所使用的一种“架构(框架)”.它就是开发的一种观念,或者说是存在已久的设计规则.我们知道在开发过程中总会伴随着需求.技术.客户.老板等因素的变化,给开发带 ...
- JavaScript实战(带收放动画效果的导航菜单)
虽然有很多插件可用,但为了共同提高,我做了一系列JavaScript实战系列的实例,分享给大家,前辈们若有好的建议,请务必指出,免得误人子弟啊! ( 原创文章,转摘请注明:苏福:http://www. ...
- MySql基本概念(一)
MySQL基本概念 一. 数据库系统概述: mysql是数据库系统的一种,下面是所有数据库系统中主要的组件. 数据库系统由硬件部分和软件部分构成,硬件主要用于存储数据库中的数据,包括计算机.存储设备. ...