详解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的random模块及加权随机算法的python实现方法
Jan 04 Python
python 限制函数执行时间,自己实现timeout的实例
Jan 12 Python
在Python 不同级目录之间模块的调用方法
Jan 19 Python
Python3.5运算符操作实例详解
Apr 25 Python
Python+Selenium使用Page Object实现页面自动化测试
Jul 14 Python
Python Opencv任意形状目标检测并绘制框图
Jul 23 Python
在tensorflow中实现屏蔽输出的log信息
Feb 04 Python
关于Tensorflow使用CPU报错的解决方式
Feb 05 Python
pyecharts在数据可视化中的应用详解
Jun 08 Python
Python 整行读取文本方法并去掉readlines换行\n操作
Sep 03 Python
安装不同版本的tensorflow与models方法实现
Feb 20 Python
Python如何使用神经网络进行简单文本分类
Feb 25 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/10/30 PHP
PHP中全局变量global和$GLOBALS[]的区别分析
2012/08/06 PHP
php计算到指定日期还有多少天的方法
2015/04/14 PHP
java微信开发之上传下载多媒体文件
2016/06/24 PHP
PHP中-&gt;和=&gt;的含义及使用示例解析
2020/08/06 PHP
广告切换效果(缓动切换)
2009/05/27 Javascript
如何确保JavaScript的执行顺序 之jQuery.html并非万能钥匙
2011/03/03 Javascript
jquery 淡入淡出效果的简单实现
2014/02/07 Javascript
jquery实现适用于门户站的导航下拉菜单效果代码
2015/08/24 Javascript
JS实现的竖向折叠菜单代码
2015/10/21 Javascript
关于react-router的几种配置方式详解
2017/07/24 Javascript
详解webpack + react + react-router 如何实现懒加载
2017/11/20 Javascript
小程序实现授权登陆的解决方案
2018/12/02 Javascript
js实现继承的方法及优缺点总结
2019/05/08 Javascript
微信小程序中显示倒计时代码实例
2019/05/09 Javascript
jQuery实现的图片点击放大缩小功能案例
2020/01/02 jQuery
JavaScript中继承原理与用法实例入门
2020/05/09 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
[02:38]DOTA2英雄基础教程 噬魂鬼
2014/01/03 DOTA
Python实现基于多线程、多用户的FTP服务器与客户端功能完整实例
2017/08/18 Python
python实现ip代理池功能示例
2019/07/05 Python
pytorch实现保证每次运行使用的随机数都相同
2020/02/20 Python
python 日志 logging模块详细解析
2020/03/31 Python
Pycharm Plugins加载失败问题解决方案
2020/11/28 Python
HTML5学习笔记之History API
2015/02/26 HTML / CSS
英国比较机场停车场网站:Airport Parking Essentials
2019/12/01 全球购物
小区文明倡议书
2014/05/16 职场文书
体育节口号
2014/06/19 职场文书
代领毕业证委托书
2014/08/02 职场文书
停车位租赁协议书
2014/09/24 职场文书
2014乡镇党委副书记对照检查材料思想汇报
2014/10/09 职场文书
干部个人考察材料
2014/12/24 职场文书
2015年个人剖析材料范文
2014/12/29 职场文书
管理失职检讨书范文
2015/05/05 职场文书
2015年乡镇工会工作总结
2015/05/19 职场文书
使用Redis做预定库存缓存功能
2022/04/02 Redis