php实现验证码的识别(中级篇)

 在上篇文章
<php实现验证码的识别

(初级篇

)
>
中,讲了如何识别简单的验证,这里的简单只的是验证码有数字和字母组成,格式统一,每次出现位置固定。这篇文章将继续深入研究识别验证码,这次识别的目标是,验证码有字符和数字组成,验证码存在旋转(可能左右都旋转),位置不固定,存在字符与字符之间的粘连,且验证码有更强的干扰素。这篇文章讲解的方法,并不是万能的解决方案,并且提供代码不能直接解决你的问题,这里仅仅是方法,具体需求读者自己解决,需要说明的是,识别验证码与具体的编程语言无关,这里只是使用
php
语言实现,使用这里介绍的方法,你可以使用任何语言实现。

 这篇文章逐步讲解识别验证码过程中的各个步骤。



 如上图,随后的讲解我们都围绕此图展开。
 一:拿到一个验证码的,第一眼我们首先要做的工作是,二值化。把验证码的部分用
1
表示,背景部分用
0
表示出来,识别方法很简单,我们打印出验证码正张图片的
RGB
,然后分析其规律即可,通过
RGB
码,我们很容易分辨出上面这张图片的
R
值大于
120

G

B
的值小于
80
,所以依据这个规则我们很容易把上面的图片二值化。再看初级篇中识别的两张图


 
刚看上去,感觉很复杂。验证码的图片每次背景色都不相同,且不是单色,各个验证码数字的颜色每次也各不相同。貌似很难二值化,其实我们打印出其
RGB
值很容易就发现。无论验证数字颜色如何变化,该数字的
RGB
值总有一个值小于
125
,所以通过如下判断

$rgbarray['red'] < 125 ||
$rgbarray['green']<125|| $rgbarray['blue'] < 125

我们就很容易分辨出哪里是数字,哪里是背景。

 
我们能够找到这些规律的因素是,在制作验证码的干扰素时,为了使干扰素不影响数字的显示效果,必须使用干扰素的
RGB
和数字
RGB
相互独立,互不干扰。只要懂得这个规律,我们就很容易实现二值化。

 
我们找到的
120

80

125
等阈值,可能和实际的
RGB
有出入,所以,有时二值化后,会有部分地方出现
1
,对于验证码上固定位置显示数字,这种干扰没有太大意义。但是对于验证码位置不确定的图片来说,在我们切割字符时,很可能造成干扰。所以,在二值化后要进行去噪出来。

 
二:接下来我们进行第二个步骤,出噪。出燥的原理很简单,就是把孤立的有效的值去掉,如果噪点比较高,要求的效率也比较高的话,这里面也有很多工作要做。幸好这里我们不要求这么高深,我们使用最简单的方法就可以,如果一个点为
1
则判断这个点的上下左右上左上右下左下右
8
个方位上数字是否为
1
,如果不为
1
,就认为是一个燥点,直接设置为
1
即可。

如上图所示,我们使用此方法很容易发现红色方框部分的
1
为燥点,直接设置为
1
即可。

在判断时我们使用了一个技巧,有时候的噪点可能是两个连续的
1
,所以我们

$num = 0;
if($data[$i][$j] == 1)
{
// 上
if(isset($data[$i-1][$j])){
$num = $num + $data[$i-1][$j];
}
// 下
if(isset($data[$i+1][$j])){
$num = $num + $data[$i+1][$j];
}
// 左
if(isset($data[$i][$j-1])){
$num = $num + $data[$i][$j-1];
}
// 右
if(isset($data[$i][$j+1])){
$num = $num + $data[$i][$j+1];
}
// 上左
if(isset($data[$i-1][$j-1])){
$num = $num + $data[$i-1][$j-1];
}
// 上右
if(isset($data[$i-1][$j+1])){
$num = $num + $data[$i-1][$j+1];
}
// 下左
if(isset($data[$i+1][$j-1])){
$num = $num + $data[$i+1][$j-1];
}
// 下右
if(isset($data[$i+1][$j+1])){
$num = $num + $data[$i+1][$j+1];
}
}
if($num == 0){
$data[$i][$j] = 0;
}

我们计算这个点的
8
个方向上的值之和,最后我们判断他们的和是否小于特定的阈值
 三:经过去噪后,我们就得到干净的二值化的数据,接下来要做的就是切割字符了。切割字符的方法有很多种,这里我采用最简单的一种,先垂直方向切割成为字符,然后在水平方向去掉多于的
0000
,如下图

第一步切割红线部分,第二步切割蓝线部分,这样就可以得到独立的字符了。但是像下面这种情况



按上面的方法会把
dw
字符切割成一个字符,这是错误的切割,所以这里我们涉及到粘连字符的切割。
 四:粘连字符切割,制作验证码时,规则字符的粘连很容易分割开,如果字符本身有缩放,变形就很难处理,经过分析,我们可以发现,上面的字符粘连属于很简单的方式,只是规则字符的粘连,所以处理这种情况,我们也使用很简单的处理方式。当完成分割操作后,我们不能马上确定分割的部分就为一个字符,要进行验证,验证的关键因素就是,切割下来的字符的宽是否大于阈值,这个阈值的取舍标准是,一个字符无论怎么旋转变形都不会大于这个阈值,所以,如果我们切割的块大于这个阈值,就可以认为这是一个粘连字符;如果大于两个阈值之和,就认为是三个字符粘连,以此类推。知道这个规则后,切割粘连字符也就很简单了。如果我们发现是粘连字符块,直接平分这个块为两个或者多个新的块就可以。当然为了更好的还原字符,我一般都采用平分
+1

-1
对字符块的部分进行适当的补充。
 五:经过上面四个步骤,我们就可以提取出比较纯的字符块了,接下来要做就是匹配字符了。对于旋转字符的特征码建立,有很多种方法,这里就不做深入研究了。我这里使用的最简单的方式,为所有字符的所有情况建立匹配库,所以在我提供的代码种增加了
study
操作,其目的就是,先有人手工识别图片的验证码,然后通过
study
方法,写入特征码库。这样写入的图片数据越多,验证识别的准确行也就越高。
 好了,经过以上步骤,我们基本上可以识别现在互联网上大部分的验证码,这里我们都是使用的最简单的方法,没有使用任何
OCR
知识。这些方法,应该属于非
OCR
领域的顶峰了,要想识别更加复杂的验证码,那就需要更多的
OCR
知识了。有机会的话,我会在高级篇中一一做介绍。
 下面是一些容易识别的验证码,希望引起网站管理者的重视。

 

 

 

制作验证码的一些建议
 对于识别验证码的程序来说,最难得部分是验证字符的切割和特征码的建立,而国内很多程序员只做验证码时,总是喜欢在验证码加很多干扰素,干扰线,影响效果不说,还达不到很好的效果;所以,要想使自己验证码难于本识别,只做下面两点就够了

1
:字符粘连,最好所有的字符都有粘连的部分;

2
:不要使用规格字符,验证码的各个部分使用不同比例的缩放或者旋转。
只要做到这两点,或者这两点的变形,识别程序就很难识别。我们看看,
yahoo

google
的验证码就知道,白字黑底,却很难被识别。

Goole:

yahoo:

源文件下:点击下载

作者
:
逸学堂(
ugg

转帖请注明:http://blog.csdn.net/ugg/archive/2009/03/09/3972368.aspx

时间: 2024-10-31 02:57:22

php实现验证码的识别(中级篇)的相关文章

php实现验证码的识别(初级篇)

近期研究一些突破验证码方面的知识,记录下来.一方面算是对这几天学习知识的总结帮助自己理解:另一方面希望对研究这方面的技术同学有所帮助:另外也希望引起网站管理者的注意,在提供验证码时多些考虑进去.由于刚刚接触这方面的知识,理解比较浅显,有错误再所难免,欢迎拍砖.验证码的作用: 有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试.其实现代的验证码一般是防止机器批量注册的,防止机器批量发帖回复.目前,不少网站为了防止用户利用机器人自动注册.登录.灌水,都采用了验证码技术.所谓

浅谈验证码的识别技术

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 这些天出于一些需要,要求做程序识别某网站的验证码,于是潜心研究了一番,颇有心得,特此分享. 编辑推荐:学习网络赚钱.网站运营 .网络营销推广请登录--选学网 http://www.xuanxue.com 验证码识别这项工作不适合浮躁的人,它需要足够的技术和耐心.由于此技术的特殊性,任何一个被公开识别技术的验证码都会很快地失效,相关网站都会很快

Python 正则表达式入门(中级篇)_python

初级篇链接:http://www.jb51.net/article/99372.htm 上一篇我们说在这一篇里,我们会介绍子表达式,向前向后查找,回溯引用.到这一篇开始前除了回溯引用在一些场合不可替代以外,大部分情况下的正则表达式你应该都会写了. 1.子表达式 子表达式的概念特别好理解.其实它就是将几个字符的组合形式看做一个大的"字符".不好理解?举个栗子:我们要匹配类似IP地址这种形式的字符(暂且不考虑数值范围的合理性,这个留作学完之后的思考题吧).形如192.168.1.1这样的地

这个验证码如何识别?

问题描述 [img=http://218.22.29.210/SHPWeb/ValidateCode.aspx][/img] 解决方案 解决方案二:中间有一个横线,各位大牛帮忙搞一下哇!解决方案三:引用1楼netciw2012的回复: 中间有一个横线,各位大牛帮忙搞一下哇! 横线只是画出来的而已,你只需要输入字符就行了啊解决方案四:我的意思是验证码识别解决方案五:先把横线去掉,横线的特点就是比正常字母的线条更细,如何去掉这样的干扰线,可以参考我写的去除扑克片里面的干扰线:解决方案六:学习了下,不

想用HttpClient登录某个外国网站,验证码已经识别出来了,但是用post登录总是跳转回登录页面

问题描述 我想模拟登录一个界面,登陆界面有验证码,我就通过get获取验证码保存到本地,通过ocr识别了验证码,再通过post填写表单数据,发送出去,响应回来的是200,不是302:通过html源码,返回回来的是验证码错误,难道get请求和post请求的不是一张验证码,难道是cookie不一致,httpclient应该具有自动处理cookie的功能啊,搞了一天没成功,郁闷的要死,求大神给点解决的方法,如何保证get和post请求的是同一张验证码下面是我的代码publicclassImitateLo

浅谈图形验证码的识别!

    本问所讲的技术只是验证码识别的初级技术,只能识别一些简单的验证码,比如符合下列部分条件的:字体工整.位置固定.颜色统一.没有干扰点.背静单纯,初步体现了OCR原理(非常弱智:)      本文讲的是通过抓特征点来达到识别目的.图片由一个一个的点(像素)组成,点的颜色变化就组成了我们看见的图片,呈现一个图象就是那几个点按照一定的顺序排列而已.         比如csdn使用的验证码(下图),去掉上下左右的白边,每个数字使用8*12=96个像素,兰色的点就是我们看到的数字了,0-9这10个

JAVA规则——中级篇

本文介绍的JAVA规则的说明分为3个主要级别,中级是平时开发用的比较多的级别,在今后将陆续写出其他的规则.遵守了这些规则可以提高程序的效率.使代码又更好的可读性等.(1) 在finally方法里关掉input或者output 资源再方法体里面定义了input或者output流的话,需要在finally里面把它关掉.以下这几种调用不需要遵守这条规则,因为colse()方法不起作用:)java.io.StringWriter java.io.ByteArrayOutputStream java.io

初级-中级-高级-神级的SEO进化论 — 中级篇(2)

自从上次写了初级SEOER的标准之后,得到大家的认可及期许这里先谢谢大家.今天笔者为大家分享一下中级SEOER所要具备些什么和需要学习些什么. 所谓中级的SEOER,我觉得应该理解为已在SEO这个岗位中工作半年或半年以上时间的人,如果工作出色的话应该可以成为岗位主管级职务的人群. 同样,中级SEOER需要具备哪些呢? 1.稳健的基础和独立实践能力 作为中级SEOER,这类人必须要熟知SEO的原理以及概念,并且在团队中有过站内优化和站外优化的经验,要求高的甚至要具备单打独斗的能力,可以独挡一面,应

Entity Framework学习中级篇1—EF支持复杂类型的实现

本节,将介绍如何手动构造复杂类型(ComplexType)以及复杂类型的简单操作. 通常,复杂类型是指那些由几个简单的类型组合而成的类型.比如:一张Customer表,其中有FristName和LastName字段,那么对应的Customer实体类将会有FristName和LastName这两个属性.当我们想把FirstName和LastName合成一个名为CustomerName属性时,此时,如果要在EF中实现这个目的,那么我们就需要用到复杂类型. 目前,由于EF不能显示支持复杂类型,所以我们