详解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实现倒计时的示例
Feb 14 Python
Python实现子类调用父类的方法
Nov 10 Python
python list排序的两种方法及实例讲解
Mar 20 Python
python中利用zfill方法自动给数字前面补0
Apr 10 Python
python实现根据指定字符截取对应的行的内容方法
Oct 23 Python
对python中字典keys,values,items的使用详解
Feb 03 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
Aug 10 Python
python return逻辑判断表达式实现解析
Dec 02 Python
python global和nonlocal用法解析
Feb 03 Python
Python3的socket使用方法详解
Feb 18 Python
Matplotlib使用Cursor实现UI定位的示例代码
Mar 12 Python
Python实现自动签到脚本的示例代码
Aug 19 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
Laravel5.* 打印出执行的sql语句的方法
2017/07/24 PHP
jQuery ajax cache缓存问题
2010/07/01 Javascript
jQuery的.live()和.die() 使用介绍
2011/09/10 Javascript
基于jquery的bankInput银行卡账号格式化
2012/08/22 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
jquery通过visible来判断标签是否显示或隐藏
2014/05/08 Javascript
table insertRow、deleteRow定义和用法总结
2014/05/14 Javascript
一个仿糯米弹框效果demo
2014/07/22 Javascript
jQuery修改CSS伪元素属性的方法
2014/07/30 Javascript
常用的Javascript数据验证插件
2015/08/04 Javascript
基于BootStrap Metronic开发框架经验小结【九】实现Web页面内容的打印预览和保存操作
2016/05/12 Javascript
js实现精确到秒的倒计时效果
2016/05/29 Javascript
Seajs是什么及sea.js 由来,特点以及优势
2016/10/13 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
小程序组件之仿微信通讯录的实现代码
2018/09/12 Javascript
ztree加载完成后显示勾选节点的实现代码
2018/10/22 Javascript
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
2019/10/15 Javascript
vue中defineProperty和Proxy的区别详解
2020/11/30 Vue.js
Python中Threading用法详解
2017/12/27 Python
浅析Python3爬虫登录模拟
2018/02/07 Python
python实现事件驱动
2018/11/21 Python
PyQt打开保存对话框的方法和使用详解
2019/02/27 Python
django fernet fields字段加密实践详解
2019/08/12 Python
python多进程(加入进程池)操作常见案例
2019/10/21 Python
Python中的xlrd模块使用原理解析
2020/05/21 Python
HTML5中input[type='date']自定义样式与日历校验功能的实现代码
2017/07/11 HTML / CSS
美国饼干礼物和美食甜点购买网站:Cheryl’s
2020/05/28 全球购物
征婚广告词
2014/03/17 职场文书
中文专业毕业生自荐信
2014/05/24 职场文书
经济国贸专业求职信
2014/06/18 职场文书
科级干部群众路线教育实践活动对照检查材料思想汇报
2014/09/20 职场文书
村干部群众路线教育活动对照检查材料
2014/10/01 职场文书
初三学生语文考试作弊检讨书
2014/12/14 职场文书
教师个人培训总结
2015/02/11 职场文书
保外就医申请书范文
2015/08/06 职场文书
mysql 直接拷贝data 目录下文件还原数据的实现
2021/07/25 MySQL