详解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 fileinput模块使用介绍
Nov 30 Python
详解Python 模拟实现生产者消费者模式的实例
Aug 10 Python
使用Python的Django和layim实现即时通讯的方法
May 25 Python
python requests post多层字典的方法
Dec 27 Python
Python 监测文件是否更新的方法
Jun 10 Python
python networkx 根据图的权重画图实现
Jul 10 Python
对Django 转发和重定向的实例详解
Aug 06 Python
Python检查图片是否损坏及图片类型是否正确过程详解
Sep 30 Python
Python如何用wx模块创建文本编辑器
Jun 07 Python
pycharm中使用request和Pytest进行接口测试的方法
Jul 31 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
Jan 21 Python
python如何正确使用yield
May 21 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
PHP的FTP学习(二)
2006/10/09 PHP
ThinkPHP中的关联模型注意点
2014/06/16 PHP
php封装的smarty类完整实例
2016/10/19 PHP
PHP Socket网络操作类定义与用法示例
2017/08/30 PHP
php-msf源码详解
2017/12/25 PHP
解决Laravel自定义类引入和命名空间的问题
2019/10/15 PHP
window.open关于浏览器拦截问题分析及解决方法
2013/02/05 Javascript
利用webqq协议使用python登录qq发消息源码参考
2013/04/08 Javascript
JS、jquery实现几分钟前、几小时前、几天前等时间差显示效果的代码实例分享
2014/04/11 Javascript
javascript+html5实现绘制圆环的方法
2015/07/28 Javascript
基于 Node.js 实现前后端分离
2016/04/23 Javascript
BootStrap中Tab页签切换实例代码
2016/05/30 Javascript
JavaScript实现输入框与清空按钮联动效果
2016/09/09 Javascript
微信小程序实现给嵌套template模板传递数据的方式总结
2017/12/18 Javascript
微信小程序textarea层级过高的解决方法
2019/03/04 Javascript
利用原生JS实现欢乐水果机小游戏
2020/04/23 Javascript
JS 5种遍历对象的方式
2020/06/16 Javascript
vue中重定向redirect:‘/index‘,不显示问题、跳转出错的完美解决
2020/09/28 Javascript
Python模块学习 re 正则表达式
2011/05/19 Python
Python的randrange()方法使用教程
2015/05/15 Python
python 默认参数问题的陷阱
2016/02/29 Python
Django中login_required装饰器的深入介绍
2017/11/24 Python
Python绘制的二项分布概率图示例
2018/08/22 Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
2019/06/18 Python
Python学习笔记之lambda表达式用法详解
2019/08/08 Python
Shopee越南:东南亚与台湾电商平台
2019/02/03 全球购物
图库照片、免版税图片、矢量艺术、视频片段:Depositphotos
2019/08/02 全球购物
资生堂英国官网:Shiseido英国
2020/12/30 全球购物
DBA的职责都有哪些
2012/05/16 面试题
会计专业推荐信
2013/10/29 职场文书
小学少先队活动方案
2014/02/18 职场文书
家长写给老师的建议书
2014/03/13 职场文书
消防标语大全
2014/06/07 职场文书
实习指导教师评语
2014/12/30 职场文书
如何拟写通知正文?
2019/04/02 职场文书
Python list去重且保持原顺序不变的方法
2021/04/03 Python