详解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中的Null模式与桥接模式编程
Feb 02 Python
Python通过RabbitMQ服务器实现交换机功能的实例教程
Jun 29 Python
Python基于datetime或time模块分别获取当前时间戳的方法实例
Feb 19 Python
python之信息加密题目详解
Jun 26 Python
python实现单链表的方法示例
Sep 03 Python
python列表推导式操作解析
Nov 26 Python
Python谱减法语音降噪实例
Dec 18 Python
python正则表达式匹配IP代码实例
Dec 28 Python
django实现模型字段动态choice的操作
Apr 01 Python
Jupyter Notebook打开任意文件夹操作
Apr 14 Python
python logging模块的使用
Sep 07 Python
python文件与路径操作神器 pathlib
Apr 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
Yii使用Captcha验证码的方法
2015/12/28 PHP
js jquery数组介绍
2012/07/15 Javascript
JavaScript隐式类型转换
2016/03/15 Javascript
Bootstrap 模态框实例插件案例分析
2016/12/28 Javascript
微信小程序五星评分效果实现代码
2017/04/06 Javascript
Vue.js进行查询操作的实例详解
2017/08/25 Javascript
JavaScript实现简单生成随机颜色的方法
2017/09/21 Javascript
nodejs结合Socket.IO实现的即时通讯功能详解
2018/01/12 NodeJs
基于vue-cli 打包时抽离项目相关配置文件详解
2018/03/07 Javascript
vue轮播组件实现$children和$parent 附带好用的gif录制工具
2019/09/26 Javascript
js获取图片的base64编码并压缩
2020/12/05 Javascript
[12:29]2018国际邀请赛 开幕秀
2018/08/22 DOTA
Python实现的下载8000首儿歌的代码分享
2014/11/21 Python
Python中常用操作字符串的函数与方法总结
2016/02/04 Python
Django中使用celery完成异步任务的示例代码
2018/01/23 Python
python保存数据到本地文件的方法
2018/06/23 Python
详解pandas.DataFrame中删除包涵特定字符串所在的行
2019/04/04 Python
详解pandas使用drop_duplicates去除DataFrame重复项参数
2019/08/01 Python
Windows平台Python编程必会模块之pywin32介绍
2019/10/01 Python
Python unittest工作原理和使用过程解析
2020/02/24 Python
python pandas.DataFrame.loc函数使用详解
2020/03/26 Python
django下创建多个app并设置urls方法
2020/08/02 Python
Python利用matplotlib绘制折线图的新手教程
2020/11/05 Python
Python应用自动化部署工具Fabric原理及使用解析
2020/11/30 Python
利用HTML5画出一个坦克的形状具体实现代码
2013/06/20 HTML / CSS
美国知名的旅游网站:OneTravel
2018/10/09 全球购物
环境科学专业优秀毕业生自荐书
2014/02/03 职场文书
运动会稿件300字
2014/02/14 职场文书
护士求职信范文
2014/05/24 职场文书
计算机科学与技术专业求职信
2014/09/03 职场文书
旅行社计调工作总结
2015/08/12 职场文书
2016幼儿园毕业感言
2015/12/08 职场文书
2019年年中职场激励人心语录30条
2019/08/07 职场文书
导游词之重庆钓鱼城
2019/09/19 职场文书
关于nginx 实现jira反向代理的问题
2021/09/25 Servers
MySQL约束(创建表时的各种条件说明)
2022/06/21 MySQL