详解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中正则表达式的使用详解
Oct 17 Python
pygame学习笔记(3):运动速率、时间、事件、文字
Apr 15 Python
Python的Flask框架及Nginx实现静态文件访问限制功能
Jun 27 Python
详解python中的json的基本使用方法
Dec 21 Python
mac下给python3安装requests库和scrapy库的实例
Jun 13 Python
Python3爬虫学习入门教程
Dec 11 Python
eclipse创建python项目步骤详解
May 10 Python
kali中python版本的切换方法
Jul 11 Python
使用Python完成15位18位身份证的互转功能
Nov 06 Python
Python pickle模块实现对象序列化
Nov 22 Python
pytorch+lstm实现的pos示例
Jan 14 Python
windows系统Tensorflow2.x简单安装记录(图文)
Jan 18 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
德生BCL3000的电路分析和打磨
2021/03/02 无线电
PHP基本语法实例总结
2016/09/09 PHP
Laravel5中Cookie的使用详解
2017/05/03 PHP
Iframe thickbox2.0使用的方法
2009/03/05 Javascript
关于取不到由location.href提交而来的上级页面地址的解决办法
2009/07/30 Javascript
javascript 类型判断代码分析
2010/03/28 Javascript
jquery插件制作 手风琴Panel效果实现
2012/08/17 Javascript
JS小功能(offsetLeft实现图片滚动效果)实例代码
2013/11/28 Javascript
二叉树先序遍历的非递归算法具体实现
2014/01/09 Javascript
iframe实用操作锦集
2014/04/22 Javascript
js 中将多个逗号替换为一个逗号的代码
2014/06/07 Javascript
js显示文本框提示文字的方法
2015/05/07 Javascript
javascript实现倒计时并弹窗提示特效
2015/06/05 Javascript
分享12个实用的jQuery代码片段
2016/03/09 Javascript
jquery radio的取值_radio的选中_radio的重置方法
2016/09/20 Javascript
JS 组件系列之Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案
2017/06/30 Javascript
Angular使用cli生成自定义文件、组件的方法
2018/09/04 Javascript
vue-cli 3.0 自定义vue.config.js文件,多页构建的方法
2018/09/19 Javascript
ES2020系列之空值合并运算符 '??'
2020/07/22 Javascript
解决Mac下首次安装pycharm无project interpreter的问题
2018/10/29 Python
Python3 安装PyQt5及exe打包图文教程
2019/01/08 Python
python-itchat 统计微信群、好友数量,及原始消息数据的实例
2019/02/21 Python
keras导入weights方式
2020/06/12 Python
sqlalchemy实现时间列自动更新教程
2020/09/02 Python
canvas绘制树形结构可视图形的实现
2020/04/03 HTML / CSS
数据库设计的包括哪两种,请分别进行说明
2016/07/15 面试题
数学专业推荐信范文
2013/11/21 职场文书
物流管理专业毕业生自荐信
2014/03/04 职场文书
三年级上册科学教学计划
2015/01/21 职场文书
设备技术员岗位职责
2015/04/11 职场文书
大学三好学生主要事迹范文
2015/11/03 职场文书
企业内部管理控制:采购授权审批制度范本
2020/01/19 职场文书
Nginx如何配置Http、Https、WS、WSS的方法步骤
2021/05/11 Servers
Spring Data JPA使用JPQL与原生SQL进行查询的操作
2021/06/15 Java/Android
win11高清晰音频管理器在哪里?win11找不到高清晰音频管理器解决办法
2022/04/08 数码科技
Win11安全功能升级:内置防网络钓鱼功能
2022/04/08 数码科技