详解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中实现php的var_dump函数功能
Jan 21 Python
Python中使用pprint函数进行格式化输出的教程
Apr 07 Python
Django基础之Model操作步骤(介绍)
May 27 Python
深入浅出分析Python装饰器用法
Jul 28 Python
PyQt5实现拖放功能
Apr 25 Python
基于Django URL传参 FORM表单传数据 get post的用法实例
May 28 Python
谈谈Python中的while循环语句
Mar 10 Python
使用selenium模拟登录解决滑块验证问题的实现
May 10 Python
使用python实现ftp的文件读写方法
Jul 02 Python
Pandas聚合运算和分组运算的实现示例
Oct 17 Python
解决python ThreadPoolExecutor 线程池中的异常捕获问题
Apr 08 Python
python中openpyxl和xlsxwriter对Excel的操作方法
Mar 01 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
百事可乐也出咖啡了 双倍咖啡因双倍快乐
2021/03/03 咖啡文化
实时抓取YAHOO股票报价的代码
2006/10/09 PHP
php 动态多文件上传
2009/01/18 PHP
thinkphp实现图片上传功能分享
2014/03/04 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十一)
2014/06/25 PHP
PHP 获取ip地址代码汇总
2015/07/05 PHP
php并发加锁示例
2016/10/17 PHP
jQuery AnythingSlider滑动效果插件
2010/02/07 Javascript
js操作textarea 常用方法总结
2012/12/03 Javascript
你必须知道的Javascript知识点之&quot;字面量和对应类型&quot;说明介绍
2013/04/23 Javascript
JS数组去重与取重的示例代码
2014/01/24 Javascript
Ajax请求在数据量大的时候出现超时的解决方法
2014/02/27 Javascript
JavaScript调试技巧之console.log()详解
2014/03/19 Javascript
Jquery实现图片预加载与延时加载的方法
2014/12/22 Javascript
JavaScript实现广告的关闭与显示效果实例
2015/07/02 Javascript
浅谈javascript的Array.prototype.slice.call
2015/08/31 Javascript
JQuery通过AJAX从后台获取信息显示在表格上并支持行选中
2015/09/15 Javascript
深究AngularJS中$sce的使用
2017/06/12 Javascript
详解10分钟学会vue滚动行为
2017/09/21 Javascript
微信小程序实现团购或秒杀批量倒计时
2020/11/01 Javascript
python3.3使用tkinter开发猜数字游戏示例
2014/03/14 Python
Python数组条件过滤filter函数使用示例
2014/07/22 Python
python处理PHP数组文本文件实例
2014/09/18 Python
python Pygame的具体使用讲解
2017/11/03 Python
ubuntu 16.04下python版本切换的方法
2019/06/14 Python
Django框架之登录后自定义跳转页面的实现方法
2019/07/18 Python
Python定时器线程池原理详解
2020/02/26 Python
Python xlrd模块导入过程及常用操作
2020/06/10 Python
Python爬虫抓取论坛关键字过程解析
2020/10/19 Python
基于注解实现 SpringBoot 接口防刷的方法
2021/03/02 Python
HTML5录音实践总结(Preact)
2020/05/07 HTML / CSS
2014两会优秀的心得体会范文
2014/03/17 职场文书
商务英语专业大学生职业生涯规划书
2014/09/14 职场文书
毕业生党员个人总结
2015/02/14 职场文书
投标售后服务承诺书
2015/04/29 职场文书
会计做账心得体会
2016/01/22 职场文书