简单验证码的识别:Bitmap类的使用
验证码的智能识别是一项比较复杂的工作,甚至需要掌握点图像学的知识。
当然对于写程序的来说不用那么深入,只需要掌握几个常规步骤就行了。
验证码图像识别步骤:1、获取图像 2、清除边框 3、灰度处理 4、二值化处理 5、噪点处理 6、图像分割 7、识别单个数字 8、拼接验证码
一、获取图像
图像一般是远程的,所以需要用到WebRequest:
public Bitmap GetImg(string imgUrl)
{
WebRequest wreq = WebRequest.Create(imgUrl);
wreq.Timeout = ;
HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse();
Stream s = wresp.GetResponseStream();
return new Bitmap(s);
}
二、清除边框
很多验证码周围都有一圈黑色的边框,因此需要用到以下操作:
public Bitmap ClearBorder(Bitmap bm)
{
//去边框 width
for (int i = ; i < bm.Width; i++)
{
bm.SetPixel(i, , Color.White);
bm.SetPixel(i, bm.Height - , Color.White);
}
//去边框 height
for (int j = ; j < bm.Height; j++)
{
bm.SetPixel(, j, Color.White);
bm.SetPixel(bm.Width - , j, Color.White);
}
return bm;
}
三、灰度处理
所谓的灰度处理即让五彩缤纷的图像变成深浅度不同的灰色图像。之所以如此是为了接下去的二值化处理。先看灰度处理:
public Bitmap MakeGray(Bitmap bm)
{
for (int i = ; i < bm.Width; i++)
{
for (int j = ; j < bm.Height; j++)
{
Color c = bm.GetPixel(i, j);//原始背景颜色
int gray = (int)(c.R * 0.11 + c.G * 0.59 + c.B * 0.3);//计算灰度
bm.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
}
}
return bm;
}
它的原理是遍历图像上的像素点,根据当前像素点的RGB颜色得到灰度,然后将灰度重新赋给当前像素点。
灰度处理通常有以下三个方法(本例采用的公式2.2):
(2.1)
(2.2)
(2.3)
公式(2.1)取RGB通道的平均值,得到的图像相对比较柔和,同时也缩小了目标和背景的平均亮度差,不利于后续的阀值处理。
公式(2.2)考虑了人眼对绿色的适应度最强,蓝色次之,红色最差。在处理绿色调和蓝色调的验证码图像时,公式(2.2)的效果令人满意,但在处理红色调的图像时,因为公式中红色的权值很小,灰度化后目标像素和背景像素的亮度差值被严重缩小,效果还不如公式(2.1)。
公式(2.3)基于一个前提,那就是有限保留目标像素的亮度信息,利于后续的阀值分割。
有关理论方面的可以参考此链接:http://www.cnblogs.com/chaosimple/archive/2013/07/18/3197720.html (感谢作者提供宝贵的资料)
四、二值化处理
二值化处理即让所有深浅度不同的灰色像素点变为黑白两种像素点,即二值化。
在此需要找到一个临界值。大于该值的为白(背景),小于的为白(验证码)。
public Bitmap MakeBlackWhite(Bitmap bm)
{
for (int i = ; i < bm.Width; i++)
{
for (int j = ; j < bm.Height; j++)
{
Color c = bm.GetPixel(i, j);//背景颜色
if (c.B > ) //当前像素点与临界值判断
{
bm.SetPixel(i, j, Color.White);
}
else
{
bm.SetPixel(i, j, Color.Black);
}
}
}
return bm;
}
五、噪点处理
所谓的噪点处理,就是把一些零零碎碎的点去掉,使其得到干净整洁的图像。
public Bitmap ClearPieces(Bitmap bm)
{
for (int i = ; i < bm.Width - ; i++)
{
for (int j = ; j < bm.Height - ; j++)
{
Color c = bm.GetPixel(i, j);//原始背景颜色
Color cUp = bm.GetPixel(i, j - );
Color cDown = bm.GetPixel(i, j + );
Color cLeft = bm.GetPixel(i - , j);
Color cRight = bm.GetPixel(i + , j);
//Response.Write(c.R + " " + c.G + " " + c.B + " <br />");
if (c.R == && cUp.R != && cDown.R != && cLeft.R != && cRight.R != )
{
bm.SetPixel(i, j, Color.White);
}
}
}
return bm;
}
六、图像切割
public Bitmap SplitImg(Bitmap bm,int pointX,int pointY)
{
Bitmap first = new Bitmap(cutWidth, cutHeight, PixelFormat.Format32bppRgb);for (int i = ; i < first.Width; i++)
{
for (int j = ; j < first.Height; j++)
{
Color c = bm.GetPixel(pointX + i, pointY + j);
first.SetPixel(i, j, c);
}
}
return first;
}
这样就得到了验证码中的只包含一个数字的图片。
七、识别单个数字
public string GetOneNumber(Bitmap first)
{
StringBuilder strFir = new StringBuilder("");
for (int i = ; i < first.Width; i++)
{
for (int j = ; j < first.Height; j++)
{
Color c = bm.GetPixel( i, j);
if (c.R == )
{
strFir.Append("");
}
else
{
strFir.Append("");
}
}
}
int result = ;
string num = "";
List<string> numbers = verifyHelper.GetList();
for (int j = ; j < numbers.Count(); j++)
{
result = ;
for (int i = ; i < strFir.Length; i++)
{
if (strFir[i] == numbers[j][i])
{
result++;
}
if (result > )
{
num = j.ToString();
return num;
} }
}
return "-1";
八、最后拼接
result += GetOneNumber(bm, , );
result += GetOneNumber(bm, , );
result += GetOneNumber(bm, , );
result += GetOneNumber(bm, , );
综合起来需要做的操作是
public string GetNumbers(string imgUrl)
{
Bitmap bm = new Bitmap(GetImgStream(imgUrl)); bm = ClearBorder(bm);
bm = MakeGray(bm);
bm = MakeBlackWhite(bm);
bm = ClearPieces(bm); string result = "";
result += GetOneNumber(bm, , );
result += GetOneNumber(bm, , );
result += GetOneNumber(bm, , );
result += GetOneNumber(bm, , );
if(result.Contains("-1"))
{
return "-1";
}
else
{
return result;
}
}
简单验证码的识别:Bitmap类的使用的更多相关文章
- Java简单验证码的识别
1. 需求 因为项目需要,需要多次登录某网站抓取信息.所以学习了验证码的一些小知识.文章参考http://blog.csdn.net/problc/article/details/5794460的部分 ...
- python简单验证码识别
在学习python通过接口自动登录网站时,用户名密码.cookies.headers都好解决但是在碰到验证码这个时就有点棘手了:于是通过网上看贴,看官网完成了对简单验证码的识别,如果是复杂的请看大神的 ...
- 开发工具类API调用的代码示例合集:六位图片验证码生成、四位图片验证码生成、简单验证码识别等
以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 六位图片验证码生成:包括纯数字.小写字母.大写字母.大小写混合.数 ...
- 简单验证码识别(matlab)
简单验证码识别(matlab) 验证码识别, matlab 昨天晚上一个朋友给我发了一些验证码的图片,希望能有一个自动识别的程序. 1474529971027.jpg 我看了看这些样本,发现都是很规则 ...
- 基于TensorFlow的简单验证码识别
TensorFlow 可以用来实现验证码识别的过程,这里识别的验证码是图形验证码,首先用标注好的数据来训练一个模型,然后再用模型来实现这个验证码的识别. 生成验证码 首先生成验证码,这里使用 Pyth ...
- Python3 简单验证码识别思路及实例
1.介绍 在爬虫中经常会遇到验证码识别的问题,现在的验证码大多分计算验证码.滑块验证码.识图验证码.语音验证码等四种.本文就是识图验证码,识别的是简单的验证码,要想让识别率更高, 识别的更加准确就需要 ...
- python 验证码识别示例(五) 简单验证码识别
今天介绍一个简单验证的识别. 主要是标准的格式,没有扭曲和变现.就用 pytesseract 去识别一下. 验证码地址:http://wscx.gjxfj.gov.cn/zfp/webroot/xfs ...
- python 验证码识别示例(四) 简单验证码识别
今天介绍一个简单验证的识别. 主要是标准的格式,没有扭曲和变现.就用 pytesseract 去识别一下. 验证码地址:http://wsxf.mca.gov.cn/zfp/Random.cmd?d= ...
- python 验证码识别示例(三) 简单验证码识别
今天介绍一个简单验证的识别. 主要是标准的格式,没有扭曲和变现.就用 pytesseract 去识别一下. 验证码地址:https://user.www.gov.cn/sso/verifyimg_ed ...
随机推荐
- Cocos2D:塔防游戏制作之旅(四)
让我们看一下项目的结构.在TowerDefense文件夹,你将找到: 含有Cocos2D文件的libs文件夹 含有所有图片和声音的资源文件夹 现在,你已经准备就绪准备开始建造炮台之旅了 ;) 放置炮塔 ...
- 读书笔记 - reword (重来)
reword (重来) 虽然我是一个不是很喜欢看书的人,但是公认的是看书对提高个人的水平是很有帮助的. 而且我想,如果我要写一本书,我一定会经过多次校验.经过长时间思考确保无误后才会出版的.所以我想看 ...
- 一个CSS+jQuery的放大缩小动画效果
日期: 2013年9月23日 作者:铁锚 // 今天帮朋友写了一些代码,自己觉得写着写着,好几个版本以后,有点满意,于是就贴出来. // 都是定死了的.因为需求就只有4个元素.如果是要用CSS的cla ...
- 【leetcode75】Intersection of Two Arrays(数组的交集)
题目描述: 给定两个数组求他们的公共部分,输出形式是数组,相同的元素只是输出一次 例如: nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2]. 原文描述: ...
- webview与js交互
对于android初学者应该都了解webView这个组件.之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用we ...
- C语言之统计输入字符数量
这个程序市委了统计所输入的数字或者英文字母的数字的数量,当然稍加改动便可以统计特殊字符的个数,在此不再冗叙. 代码如下: #include <iostream> using namespa ...
- 【Unity Shaders】Using Textures for Effects——通过修改UV坐标来滚动textures
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- JAVA之旅(五)——this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块
JAVA之旅(五)--this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块 周末收获颇多,继续学习 一.this关键字 用于区分局部变量和成员变量同名的情况 ...
- 放yy直播点赞动画
最近在做直播相关的东西,这个动画是IOS先撸出来的,后来android这边要模仿,大部分直播应用都有很炫酷的点赞动画,所以也没什么好稀奇的.如果有现成的轮子了,就没必要自己再造了,后来参照了程序亦非猿 ...
- 《java入门第一季》之参数引用
Java中的参数传递问题: 基本类型:形式参数的改变对实际参数没有影响. 引用类型:形式参数的改变直接影响实际参数. */ class ArgsDemo { public static void ma ...