详解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开发的nosql数据库CodernityDB介绍和使用实例
Oct 23 Python
Python3处理文件中每个词的方法
May 22 Python
python实现输入数字的连续加减方法
Jun 22 Python
Django中使用第三方登录的示例代码
Aug 20 Python
Numpy中对向量、矩阵的使用详解
Oct 29 Python
如何基于python操作json文件获取内容
Dec 24 Python
PIL.Image.open和cv2.imread的比较与相互转换的方法
Jun 03 Python
Python项目跨域问题解决方案
Jun 22 Python
keras 模型参数,模型保存,中间结果输出操作
Jul 06 Python
如何在mac版pycharm选择python版本
Jul 21 Python
Python将list元素转存为CSV文件的实现
Nov 16 Python
Selenium环境变量配置(火狐浏览器)及验证实现
Dec 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 求质素(素数) 的实现代码
2011/04/12 PHP
有关PHP中MVC的开发经验分享
2012/05/17 PHP
php一维二维数组键排序方法实例总结
2014/11/13 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
php指定长度分割字符串str_split函数用法示例
2017/01/30 PHP
jQuery页面加载初始化常用的三种方法
2014/06/04 Javascript
浅谈js中字符和数组一些基本算法题
2016/08/15 Javascript
easyui messager alert 三秒后自动关闭提示的实例
2016/11/07 Javascript
jQuery基于排序功能实现上移、下移的方法
2016/11/26 Javascript
JavaScript实现多栏目切换效果
2016/12/12 Javascript
JavaScript Uploadify文件上传实例
2017/02/28 Javascript
解决Node.js使用MySQL出现connect ECONNREFUSED 127.0.0.1:3306的问题
2017/03/09 Javascript
webpack独立打包和缓存处理详解
2017/04/03 Javascript
基于Vue实现timepicker
2017/04/25 Javascript
JavaScript中的回调函数实例讲解
2019/01/27 Javascript
小程序分享模块超级详解(推荐)
2019/04/10 Javascript
vue2.0 获取从http接口中获取数据,组件开发,路由配置方式
2019/11/04 Javascript
如何基于JS截获动态代码
2019/12/25 Javascript
Python3基础之函数用法
2014/08/13 Python
Python操作Access数据库基本步骤分析
2016/09/19 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
Python机器学习之SVM支持向量机
2017/12/27 Python
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
python队列原理及实现方法示例
2019/11/27 Python
python shutil文件操作工具使用实例分析
2019/12/25 Python
Python实现计算图像RGB均值方式
2020/06/04 Python
PyTorch预训练Bert模型的示例
2020/11/17 Python
BeautifulSoup中find和find_all的使用详解
2020/12/07 Python
CSS3的column-fill属性对齐列内容高度的用法详解
2016/07/01 HTML / CSS
一级方程式赛车官方网上商店:F1 Store(支持中文)
2018/01/12 全球购物
Linux中如何用命令创建目录
2015/01/12 面试题
shell程序如何生命变量?shell变量是弱变量吗?
2014/11/10 面试题
机电一体化专业推荐信
2013/12/03 职场文书
优秀少先队员主要事迹材料
2014/05/28 职场文书
2014年大班保育员工作总结
2014/12/02 职场文书
2016年大学自主招生自荐信范文
2015/03/24 职场文书