详解Python验证码识别


Posted in Python onJanuary 25, 2016

以前写过一个刷校内网的人气的工具,Java的(以后再也不行Java程序了),里面用到了验证码识别,那段代码不是我自己写的:-) 校内的验证是完全单色没有任何干挠的验证码,识别起来比较容易,不过从那段代码中可以看到基本的验证码识别方式。这几天在写一个程序的时候需要识别验证码,因为程序是Python写的自然打算用Python进行验证码的识别。

以前没用Python处理过图像,不太了解PIL(Python Image Library)的用法,这几天看了看PIL,发现它太强大了,简直和ImageMagic,PS可以相比了。(这里有PIL不错的文档)

由于上面的验证码是24位的jpeg图像,并且包含了噪点,所以我们要做的就是去噪和去色,我拿PS找了张验证码试了试,使用PS滤镜中的去噪效果还行, 但是没有在PIL找到去噪的函数,后来发现中值过滤后可以去掉大部分的噪点,而且PIL里有现成的函数,接下来我试着直接把图像转换为单色,结果发现还是 会有不过的噪点留了下来,因为中值过滤时把不少噪点淡化了,但转换为音色时这些噪点又被强化显示了,于是在中值过滤后对图像亮度进行加强处理,然后再转换 为单色,这样验证码图片就变得比较容易识别了:

上面这些处理使用Python才几行:

im = Image.open(image_name)
im = im.filter(ImageFilter.MedianFilter())
enhancer = ImageEnhance.Contrast(im)
im = enhancer.enhance(2)
im = im.convert('1')
im.show()

接下来就是提取这些数字的字模,使用shell脚本下载100幅图片,抽出三张图片获取字模:

#!/usr/bin/env python
#encoding=utf-8
import Image,ImageEnhance,ImageFilter
import sys
image_name = "./images/81.jpeg"
im = Image.open(image_name)
im = im.filter(ImageFilter.MedianFilter())
enhancer = ImageEnhance.Contrast(im)
im = enhancer.enhance(2)
im = im.convert('1')
#im.show()
#all by pixel
s = 12 #start postion of first number
w = 10 #width of each number
h = 15 #end postion from top
t = 2 #start postion of top
im_new = []
#split four numbers in the picture
for i in range(4):
im1 = im.crop((s+w*i+i*2,t,s+w*(i+1)+i*2,h))
im_new.append(im1)
f = file("data.txt","a")
for k in range(4):
l = []
#im_new[k].show()
for i in range(13):
for j in range(10):
if (im_new[k].getpixel((j,i)) == 255):
l.append(0)
else:
l.append(1)
f.write("l=[")
n = 0
for i in l:
if (n%10==0):
f.write("/n")
f.write(str(i)+",")
n+=1
f.write("]/n")

把字模保存为list,用于接下来的匹配;

提取完字模后剩下来的就是对需要处理的图片进行与数据库中的字模进行匹配了,基本的思路就是看相应点的重合率,但是由于噪点的影响在对(6,8) (8,3)(5,9)的匹配时容易出错,俺自己针对已有的100幅图片数据采集进行分析,采用了双向匹配(图片与字模分别作为基点),做了半天的测试终于 可以实现100%的识别率。

#!/usr/bin/env python
#encoding=utf-8
import Image,ImageEnhance,ImageFilter
import Data
DEBUG = False
def d_print(*msg):
global DEBUG
if DEBUG:
for i in msg:
print i,
print
else:
pass
def Get_Num(l=[]):
min1 = []
min2 = []
for n in Data.N:
count1=count2=count3=count4=0
if (len(l) != len(n)):
print "Wrong pic"
exit()
for i in range(len(l)):
if (l[i] == 1):
count1+=1
if (n[i] == 1):
count2+=1
for i in range(len(l)):
if (n[i] == 1):
count3+=1
if (l[i] == 1):
count4+=1
d_print(count1,count2,count3,count4)
min1.append(count1-count2)
min2.append(count3-count4)
d_print(min1,"/n",min2)
for i in range(10):
if (min1[i] <= 2 or min2[i] <= 2):
if ((abs(min1[i] - min2[i])) <10):
return i
for i in range(10): 
if (min1[i] <= 4 or min2[i] <= 4):
if (abs(min1[i] - min2[i]) <= 2):
return i
for i in range(10):
flag = False
if (min1[i] <= 3 or min2[i] <= 3):
for j in range(10):
if (j != i and (min1[j] <5 or min2[j] <5)):
flag = True
else:
pass
if (not flag):
return i
for i in range(10): 
if (min1[i] <= 5 or min2[i] <= 5):
if (abs(min1[i] - min2[i]) <= 10):
return i
for i in range(10):
if (min1[i] <= 10 or min2[i] <= 10):
if (abs(min1[i] - min2[i]) <= 3):
return i
#end of function Get_Num
def Pic_Reg(image_name=None):
im = Image.open(image_name)
im = im.filter(ImageFilter.MedianFilter())
enhancer = ImageEnhance.Contrast(im)
im = enhancer.enhance(2)
im = im.convert('1')
im.show()
#all by pixel
s = 12 #start postion of first number
w = 10 #width of each number
h = 15 #end postion from top
t = 2 #start postion of top
im_new = []
#split four numbers in the picture
for i in range(4):
im1 = im.crop((s+w*i+i*2,t,s+w*(i+1)+i*2,h))
im_new.append(im1)
s = ""
for k in range(4):
l = []
#im_new[k].show()
for i in range(13):
for j in range(10):
if (im_new[k].getpixel((j,i)) == 255):
l.append(0)
else:
l.append(1)
s+=str(Get_Num(l))
return s
print Pic_Reg("./images/22.jpeg")

这里再提一下验证码识别的基本方法:截图,二值化、中值滤波去噪、分割、紧缩重排(让高矮统一)、字库特征匹配识别。
这里只是针对一般的验证码,高级验证码的识别这里有篇不错的文章,太复杂的话涉及的东西就多了,那俺就没兴趣了,人工智能(好恐怖),俺只喜欢简单的东西。

Python 相关文章推荐
python魔法方法-属性访问控制详解
Jul 25 Python
Python采用Django制作简易的知乎日报API
Aug 03 Python
python数据类型判断type与isinstance的区别实例解析
Oct 31 Python
Python学习笔记之open()函数打开文件路径报错问题
Apr 28 Python
python3学习之Splash的安装与实例教程
Jul 09 Python
详解Python中的type和object
Aug 15 Python
在python3中实现更新界面
Feb 21 Python
AUC计算方法与Python实现代码
Feb 28 Python
Django实现celery定时任务过程解析
Apr 21 Python
python 读txt文件,按‘,’分割每行数据操作
Jul 05 Python
利用Python的folium包绘制城市道路图的实现示例
Aug 24 Python
Python创建SQL数据库流程逐步讲解
Sep 23 Python
Python网站验证码识别
Jan 25 #Python
谈谈Python进行验证码识别的一些想法
Jan 25 #Python
基于Python Shell获取hostname和fqdn释疑
Jan 25 #Python
21行Python代码实现拼写检查器
Jan 25 #Python
Python字符串、元组、列表、字典互相转换的方法
Jan 23 #Python
Python随手笔记第一篇(2)之初识列表和元组
Jan 23 #Python
Python爬虫模拟登录带验证码网站
Jan 22 #Python
You might like
在CentOS系统上从零开始搭建WordPress博客的全流程记录
2016/04/21 PHP
图文详解PHP环境搭建教程
2016/07/16 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
php array_map使用自定义的函数处理数组中的每个值
2016/10/26 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
jquery $.ajax()取xml数据的小问题解决方法
2010/11/20 Javascript
jQuery的Ajax的自动完成功能控件简要说明
2013/02/22 Javascript
js动态设置div的值下例子
2013/10/29 Javascript
解决WordPress使用CDN后博文无法评论的错误
2015/12/15 Javascript
轻松掌握JavaScript代理模式
2016/08/26 Javascript
jQuery利用sort对DOM元素进行排序操作
2016/11/07 Javascript
简单实现JS计算器功能
2016/12/21 Javascript
JS正则替换去空格的方法
2017/03/24 Javascript
详解Vue2.0配置mint-ui踩过的那些坑
2018/04/23 Javascript
小程序scroll-view组件实现滚动的示例代码
2018/09/20 Javascript
Javascript实现一朵从含苞到绽放的玫瑰
2019/03/30 Javascript
使用RxJS更优雅地进行定时请求详析
2019/06/02 Javascript
javascript function(函数类型)使用与注意事项小结
2019/06/10 Javascript
微信小程序开发(二):页面跳转并传参操作示例
2020/06/01 Javascript
详解在IDEA中将Echarts引入web两种方式(使用js文件和maven的依赖导入)
2020/07/11 Javascript
[01:31]DOTA2上海特级锦标赛 SECRET战队完整宣传片
2016/03/16 DOTA
Python基础入门之seed()方法的使用
2015/05/15 Python
Python tkinter模块弹出窗口及传值回到主窗口操作详解
2017/07/28 Python
浅谈pandas中shift和diff函数关系
2018/04/08 Python
python自动重试第三方包retrying模块的方法
2018/04/24 Python
Python中的 is 和 == 以及字符串驻留机制详解
2019/06/28 Python
Pycharm使用远程linux服务器conda/python环境在本地运行的方法(图解))
2019/12/09 Python
python接口自动化之ConfigParser配置文件的使用详解
2020/08/03 Python
英国水族馆和池塘用品购物网站:Warehouse Aquatics
2019/08/29 全球购物
请用用Java代码写一个堆栈
2012/01/26 面试题
医学院护理专业应届生求职信
2013/11/12 职场文书
教育专业毕业生推荐信
2014/07/10 职场文书
股东合作协议书
2014/09/12 职场文书
2014高中生入党思想汇报范文
2014/09/13 职场文书
聘任合同书
2015/09/21 职场文书
JavaScript实现登录窗体
2021/06/22 Javascript