详解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的加密模块md5、sha、crypt使用实例
Sep 28 Python
Ruby元编程基础学习笔记整理
Jul 02 Python
利用Python自动监控网站并发送邮件告警的方法
Aug 24 Python
python中利用Future对象回调别的函数示例代码
Sep 07 Python
Flask实现跨域请求的处理方法
Sep 27 Python
Matplotlib中文乱码的3种解决方案
Nov 15 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
Jul 11 Python
Python selenium 自动化脚本打包成一个exe文件(推荐)
Jan 14 Python
使用Python实现牛顿法求极值
Feb 10 Python
通过代码实例解析Pytest运行流程
Aug 20 Python
Python中BeautifulSoup通过查找Id获取元素信息
Dec 07 Python
一行代码python实现文件共享服务器
Apr 22 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/12/22 PHP
关于session在PHP5的配置文件中的详细设置参数说明
2011/04/20 PHP
php实现按指定大小等比缩放生成上传图片缩略图的方法
2014/12/15 PHP
使用Thinkphp框架开发移动端接口
2015/08/05 PHP
php简单备份与还原MySql的方法
2016/05/09 PHP
自己开发Dojo的建议框架
2008/09/24 Javascript
JavaScript 拾碎[三] 使用className属性
2010/10/16 Javascript
网页中返回顶部代码(多种方法)另附注释说明
2013/04/24 Javascript
jquery 获取表单元素里面的值示例代码
2013/07/28 Javascript
DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)
2016/11/09 Javascript
webpack打包js文件及部署的实现方法
2017/12/18 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
解决vue单页使用keep-alive页面返回不刷新的问题
2018/03/13 Javascript
vue项目部署到Apache服务器中遇到的问题解决
2018/08/24 Javascript
浅谈layer弹出层按钮颜色修改方法
2019/09/11 Javascript
详解如何在Javascript和Sass之间共享变量
2019/11/13 Javascript
vue新建项目并配置标准路由过程解析
2019/12/09 Javascript
使用React-Router实现前端路由鉴权的示例代码
2020/07/26 Javascript
Vue使用Proxy代理后仍无法生效的解决
2020/11/13 Javascript
python使用wmi模块获取windows下的系统信息 监控系统
2015/10/27 Python
对numpy Array [: ,] 的取值方法详解
2018/07/02 Python
python使用turtle绘制国际象棋棋盘
2019/05/23 Python
Python学习笔记之抓取某只基金历史净值数据实战案例
2019/06/03 Python
python批量解压zip文件的方法
2019/08/20 Python
Python如何用filter函数筛选数据
2020/03/05 Python
使用python+poco+夜神模拟器进行自动化测试实例
2020/04/23 Python
使用Keras预训练模型ResNet50进行图像分类方式
2020/05/23 Python
保险专业大专生求职信
2013/10/26 职场文书
高分子材料与工程专业推荐信
2013/12/01 职场文书
幼儿园校车司机的岗位职责
2014/01/30 职场文书
秸秆管理实施方案
2014/03/15 职场文书
市政管理求职信范文
2014/05/07 职场文书
中学学校门卫岗位职责
2014/08/15 职场文书
计划生育诚信协议书
2014/11/02 职场文书
2019年手机市场的调研报告2篇
2019/10/10 职场文书
idea搭建可运行Servlet的Web项目
2021/06/26 Java/Android