详解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 相关文章推荐
python3使用urllib示例取googletranslate(谷歌翻译)
Jan 23 Python
简单的通用表达式求10乘阶示例
Mar 03 Python
Python通过DOM和SAX方式解析XML的应用实例分享
Nov 16 Python
Python中pip更新和三方插件安装说明
Jul 08 Python
Python使用装饰器模拟用户登陆验证功能示例
Aug 24 Python
使用python生成杨辉三角形的示例代码
Aug 29 Python
python 返回列表中某个值的索引方法
Nov 07 Python
解决使用export_graphviz可视化树报错的问题
Aug 09 Python
解决torch.autograd.backward中的参数问题
Jan 07 Python
Python3 多线程(连接池)操作MySQL插入数据
Jun 09 Python
python使用torch随机初始化参数
Mar 22 Python
Python列表的索引与切片
Apr 07 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 购物车实例(申精)
2009/05/11 PHP
浅谈PHP中的数据传输CURL
2016/09/06 PHP
PHP单文件上传原理及上传函数的封装操作示例
2019/09/02 PHP
js 学习笔记(三)
2009/12/29 Javascript
JQuery循环滚动图片代码
2011/12/08 Javascript
JQuery触发radio或checkbox的change事件
2012/12/18 Javascript
jQuery.clean使用方法及思路分析
2013/01/07 Javascript
快速查找数组中的某个元素并返回下标示例
2013/09/03 Javascript
jquery 快速回到页首的方法
2013/12/05 Javascript
javascript+ajax实现产品页面加载信息
2015/07/09 Javascript
基于Bootstrap里面的Button dropdown打造自定义select
2016/05/30 Javascript
AngularJS 工作原理详解
2016/08/18 Javascript
Node.js用readline模块实现输入输出
2016/12/16 Javascript
详解Angular的内置过滤器和自定义过滤器【推荐】
2016/12/26 Javascript
node.js 抓取代理ip实例代码
2017/04/30 Javascript
vue-cli单页应用改成多页应用配置详解
2017/07/14 Javascript
layui select动态添加option的实例
2018/03/07 Javascript
JavaScript累加、迭代、穷举、递归等常用算法实例小结
2018/05/08 Javascript
使用jQuery给Table动态增加行、清空table的方法
2018/09/05 jQuery
node实现生成带参数的小程序二维码并保存到本地功能示例
2018/12/05 Javascript
在mpvue框架中使用Vant WeappUI组件库的注意事项【推进】
2019/06/09 Javascript
移动端 Vue+Vant 的Uploader 实现上传、压缩、旋转图片功能
2019/06/10 Javascript
Node 使用express-http-proxy 做api网关的实现
2020/10/15 Javascript
使用pyecharts无法import Bar的解决方案
2020/04/23 Python
python程序快速缩进多行代码方法总结
2019/06/23 Python
Python随机数函数代码实例解析
2020/02/09 Python
Python线程协作threading.Condition实现过程解析
2020/03/12 Python
如何在sublime编辑器中安装python
2020/05/20 Python
Coccinelle官网:意大利的著名皮具品牌
2019/05/15 全球购物
暑期社会实践方案
2014/02/05 职场文书
奥巴马当选演讲稿
2014/09/10 职场文书
2014年小学重阳节活动策划方案
2014/09/16 职场文书
2014年机关作风建设工作总结
2014/10/23 职场文书
辩护词范文大全
2015/05/21 职场文书
地雷战观后感
2015/06/09 职场文书
实验室安全管理制度
2015/08/05 职场文书