用 aforge.net 小试一下验证码识别

今天来小玩一下 aforge.net 套用官方的话就是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域,下载网址:http://www.aforgenet.com/framework/downloads.html

对了,不知道有多少公司是用得仕卡作为员工的福利卡,我们公司就是这样的,每个月公司都会充值一些money????????????。

上去看了后,哟呵~ 还有个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){//切下来图片的横坐标leftleft = i;}else{//切下来图片的横坐标rightright = 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% 吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309068.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国标转区位码电路设计及汉字显示

区位码国际码-2020H&#xff0c;由于采用加法器实现&#xff0c;因此用补码形式进行表示&#xff0c;区位码 国际码FFFF-2020H0001H国际码dfe0。 从网上找下机内码转化的软件&#xff0c;将一段自选文字输入该软件&#xff0c;进行十六进制的机内码转化。由于一个汉字是由四个十…

【WPF】DataGrid多表头的样式设计

需求在使用WPF开发时&#xff0c;使用DataGrid列表显示数据时&#xff0c;有些字段可以进行分组显示&#xff0c;用于更好的表达它们之间存在的某种关系&#xff0c;因此就考虑到要对DataGrid的表头进行扩展&#xff0c;可以显示多行表头&#xff0c;让这些有关联的字段内容显示…

如何使用ABP进行软件开发之基础概览

ABP框架简述1&#xff09;简介在.NET众多的技术框架中&#xff0c;ABP框架&#xff08;本系列中指aspnetboilerplate项目&#xff09;以其独特的魅力吸引了一群优秀开发者广泛的使用。在该框架的赋能之下&#xff0c;开发者可根据需求通过官方网站【https://aspnetboilerplate.…

模2加法,模2减法,模2除法

十进制的除法&#xff0c;大家都会做&#xff1a;列个竖式&#xff0c;商&#xff0c;写在上面&#xff0c;上个几&#xff0c;再用被除数减去积&#xff0c;求得余数…。 二进制的除法&#xff0c;和十进制的计算方法相同&#xff0c;也要列出个竖式计算。 二进制的除法&…

《Unit Testing》2.1 伦敦学派如何做隔离

针对单元测试的定义&#xff0c;主要有两种看法&#xff1a;经典学派。经典学派之所以经典&#xff0c;是因为这原本就是人们做单元测试和测试驱动开发的方式伦敦学派。伦敦学派扎根于伦敦的编程社区。单元测试的定义单元测试有很多定义&#xff0c;但是所有的定义都有三个重要…

C++实现数组模拟链表(实现链表的增删功能)

代码如下: #include <iostream> using namespace std; const int N 100;struct Node {int data;int next; };class ArrayList { private:Node node[N];int maxSize;//数组容量int idx;//接下来要插入的结点的下标int len;//链表长度public:void initList(){node[0].nex…

Gartner:容器采用将迅速增长,但不会很快有利可图

导语容器的未来可期&#xff0c;到2024年&#xff0c;所有应用程序中的15&#xff05;将在容器中运行&#xff0c;而这一数据今天仅为5&#xff05;&#xff0c;但当前变现还比较难。正文近日&#xff0c;Gartner公司发表其首次为软件容器管理软件和服务市场做的预测。Gartner说…

【Azure Show】|第三期 人工智能大咖与您分享!嘉宾陈海平胡浩陈堰平

欢迎来到Azure Show!Azure ShowHello,大家好&#xff0c;又来到新的一期的Azure Show!本期是人工智能专场&#xff0c;我们邀请到微软Data&AI的解决方案架构师陈堰平&#xff0c;Tensorflow.NET 作者陈海平&#xff0c;还有微软人工智能方向最有价值专家胡浩和大家分享人工…

深入探究ASP.NET Core异常处理中间件

前言全局异常处理是我们编程过程中不可或缺的重要环节。有了全局异常处理机制给我们带来了很多便捷&#xff0c;首先我们不用满屏幕处理程序可能出现的异常&#xff0c;其次我们可以对异常进行统一的处理&#xff0c;比如收集异常信息或者返回统一的格式等等。ASP.NET Core为我…

.NET Core加解密实战系列之——消息摘要与数字签名算法

简介加解密现状&#xff0c;编写此系列文章的背景&#xff1a;需要考虑系统环境兼容性问题&#xff08;Linux、Windows&#xff09;语言互通问题&#xff08;如C#、Java等&#xff09;&#xff08;加解密本质上没有语言之分&#xff0c;所以原则上不存在互通性问题&#xff09;…

造轮子-AgileConfig一个基于.NetCore开发的轻量级配置中心

微服务确实是行业的一个趋势&#xff0c;我自己也在把一些项目往微服务架构迁移。玩微服务架构配置中心是一个绕不过去的东西&#xff0c;有很多大牌的组件可以选&#xff0c;比如spring-cloud-config&#xff0c;apoll&#xff0c;disconf等等。而我为什么还要造一个轮子呢&am…

SQL Server 分页+json分享

1。SQL Server 版本2012 新增SQL分页的写法最近封装一个轻量级的ORM用到了分页&#xff0c;以前只知道使用Row_Number函数&#xff0c;现在发现sqlserver 新增的 {orderBy} offset {start} rows fetch next {pageSize} rows only 也挺好用的。简单回顾下 sqlserver 各个版本支持…

用十行代码快速创建权限管理系统

&#xff08;坚持做自己&#xff09;为了防止说是标题党&#xff0c;我先展示下真是就需要十行代码&#xff1a;当然还有appsettings.json配置文件&#xff0c;和种子数据文件&#xff0c;这个不算代码之内。1、项目背景介绍Blog.Core项目开源也两年了&#xff0c;经过了很多许…

ERP的配置管理实践

源宝导读&#xff1a;随着ERP系统的日益复杂&#xff0c;应用部署的方式越来越复杂&#xff0c;应用的配置也变得越来越庞杂&#xff0c;难以维护和管理。本文将介绍配置中心服务通过集中化、可离线的架构设计&#xff0c;解决ERP配置问题的实践经验。一、背景随着ERP业务的日益…

《LIO-SAM阅读笔记》1.IMU预积分模块

前言&#xff1a; LIO-SAM是一个多传感器融合的紧耦合SLAM框架&#xff0c;融合的传感器类型有雷达、IMU和GPS&#xff0c;其中雷达和IMU在LIO-SAM框架中必须使用的。LIO-SAM的优化策略采用了GTSAM库&#xff0c;GTSAM库采用了因子图的优化方法&#xff0c;其提供了一些列C的外…

EntityFramework Core 迁移忽略主外键关系

【导读】本文来源于一位公众号童鞋私信我的问题&#xff0c;在我稍加思索后给出了如下一种方案&#xff0c;在此之前我也思考过这个问题&#xff0c;借此机会我稍微看了下&#xff0c;目前能够想到的也只是本文所述方案。为何要忽略主外键关系我们不仅疑惑为何要忽略主外键关系…

你很可能需要知道这个调试小技巧

缘起 最近在调试的时候&#xff0c;需要观察第三方容器中每一个元素的值。默认情况下&#xff0c;vs 并不知道如何显示第三方容器的内容&#xff0c;只能手动观察容器中的每一个值&#xff0c;超级不方便。我找到一个非常给力的好办法&#xff0c;你还知道其它好办法吗&#xf…

全宇宙首本 VS Code 中文书,来了!

大家好&#xff01;我是韩骏&#xff0c;VS Code 中文社区创始人&#xff0c;VS Code 的代码贡献者。2013 年&#xff0c;毕业于上海交通大学软件学院&#xff0c;现在是微软开发平台事业部的软件工程师。写过 20 多款 VS Code 插件&#xff0c;其中最热门的 Code Runner 插件有…

C# 从1到Core--委托与事件

委托与事件在C#1.0的时候就有了&#xff0c;随着C#版本的不断更新&#xff0c;有些写法和功能也在不断改变。本文温故一下这些改变&#xff0c;以及在NET Core中关于事件的一点改变。一、C#1.0 从委托开始1. 基本方式什么是委托&#xff0c;就不说概念了&#xff0c;用例子说话…

开源导入导出库Magicodes.IE 多sheet导入教程

多Sheet导入教程说明本教程主要说明如何使用Magicodes.IE.Excel完成多个Sheet数据的Excel导入。要点多个相同格式的Sheet数据导入多个不同格式的Sheet数据导入主要步骤1. 多个相同格式的Sheet数据导入1.1 创建导入Sheet的Dto主要代码如下所示&#xff1a;学生数据Dto/// <su…