详解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中的XML库4Suite Server的介绍
Apr 14 Python
Django Admin实现上传图片校验功能
Mar 06 Python
基于python元祖与字典与集合的粗浅认识
Aug 23 Python
使用Python操作excel文件的实例代码
Oct 15 Python
django限制匿名用户访问及重定向的方法实例
Feb 07 Python
python使用folium库绘制地图点击框
Sep 21 Python
在python中利用GDAL对tif文件进行读写的方法
Nov 29 Python
Python实现分段线性插值
Dec 17 Python
python3 字符串/列表/元组(str/list/tuple)相互转换方法及join()函数的使用
Apr 03 Python
Python中的类与类型示例详解
Jul 10 Python
PythonPC客户端自动化实现原理(pywinauto)
May 28 Python
解决pytorch 数据类型报错的问题
Mar 03 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批量生成缩略图的代码
2008/07/19 PHP
PHP闭包(Closure)使用详解
2013/05/02 PHP
ThinkPHP模板之变量输出、自定义函数与判断语句用法
2014/11/01 PHP
linux中cd命令使用详解
2015/01/08 PHP
php判断一个数组是否为有序的方法
2015/03/27 PHP
通用javascript脚本函数库 方便开发
2009/10/13 Javascript
利用JQuery+EasyDrag 实现弹出可拖动的Div,同时向Div传值,然后返回Div选中的值
2009/10/24 Javascript
javascript 动态生成私有变量访问器
2009/12/06 Javascript
关于IE浏览器以及Firefox下的javascript冒泡事件的响应层级
2010/10/14 Javascript
jQuery Clone Bug解决代码
2010/12/22 Javascript
两种方法实现在HTML页面加载完毕后运行某个js
2014/06/16 Javascript
js用Date对象的setDate()函数对日期进行加减操作
2014/09/18 Javascript
使用JS实现jQuery的addClass, removeClass, hasClass函数功能
2014/10/31 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
2015/12/03 Javascript
JS把内容动态插入到DIV的实现方法
2016/07/19 Javascript
javascript实现页面滚屏效果
2017/01/17 Javascript
如何使用three.js 制作一个三维的推箱子游戏
2020/07/29 Javascript
用Python实现斐波那契(Fibonacci)函数
2016/03/25 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
2018/08/31 Python
python字符串切割:str.split()与re.split()的对比分析
2019/07/16 Python
twilio python自动拨打电话,播放自定义mp3音频的方法
2019/08/08 Python
pyhton中__pycache__文件夹的产生与作用详解
2019/11/24 Python
Python如何避免文件同名产生覆盖
2020/06/09 Python
浅谈python锁与死锁问题
2020/08/14 Python
网易微博Web App用HTML5开发的过程介绍
2012/06/13 HTML / CSS
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
聚网科技C++面试笔试题
2015/09/01 面试题
元旦活动感言
2014/03/08 职场文书
社区党务公开实施方案
2014/03/18 职场文书
自我鉴定总结
2014/03/24 职场文书
中国入世承诺
2014/04/01 职场文书
工作态度不端正检讨书
2014/10/04 职场文书
说谎欺骗人检讨书300字
2014/11/18 职场文书
2015年乡镇环保工作总结
2015/04/22 职场文书
卖车协议书范文
2016/03/23 职场文书
导游词创作书写原则以及开场白技巧怎么学?
2019/09/25 职场文书