python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别


Posted in Python onJune 04, 2018

前言

写爬虫有一个绕不过去的问题就是验证码,现在验证码分类大概有4种:

  1. 图像类
  2. 滑动类
  3. 点击类
  4. 语音类

今天先来看看图像类,这类验证码大多是数字、字母的组合,国内也有使用汉字的。在这个基础上增加噪点、干扰线、变形、重叠、不同字体颜色等方法来增加识别难度。

相应的,验证码识别大体可以分为下面几个步骤:

  1. 灰度处理
  2. 增加对比度(可选)
  3. 二值化
  4. 降噪
  5. 倾斜校正分割字符
  6. 建立训练库
  7. 识别

由于是实验性质的,文中用到的验证码均为程序生成而不是批量下载真实的网站验证码,这样做的好处就是可以有大量的知道明确结果的数据集。

当需要真实环境下需要获取数据时,可以使用结合各个大码平台来建立数据集进行训练。

生成验证码这里我使用Claptcha (本地下载)这个库,当然Captcha(本地下载)这个库也是个不错的选择。

为了生成最简单的纯数字、无干扰的验证码,首先需要将claptcha.py的285行_drawLine做一些修改,我直接让这个函数返回None,然后开始生成验证码:

from claptcha import Claptcha

c = Claptcha("8069","/usr/share/fonts/truetype/freefont/FreeMono.ttf")
t,_ = c.write('1.png')

这里需要注意ubuntu的字体路径,也可以在网上下载其他字体使用。生成验证码如下:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

可以看出,验证码有形变。对于这类最简单的验证码,可以直接使用谷歌开源的tesserocr来识别。

首先安装:

apt-get install tesseract-ocr libtesseract-dev libleptonica-dev
pip install tesserocr

然后开始识别:

from PIL import Image
import tesserocr

p1 = Image.open('1.png')
tesserocr.image_to_text(p1)

'8069\n\n'

可以看出,对于这种简单的验证码,基本什么都不做识别率就已经很高了。有兴趣的小伙伴可以用更多的数据来测试,这里我就不展开了。

接下来,在验证码背景添加噪点来看看:

c = Claptcha("8069","/usr/share/fonts/truetype/freefont/FreeMono.ttf",noise=0.4)
t,_ = c.write('2.png')

生成验证码如下:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

识别:

p2 = Image.open('2.png')
tesserocr.image_to_text(p2)
'8069\n\n'

效果还可以。接下来生成一个字母数字组合的:

c2 = Claptcha("A4oO0zZ2","/usr/share/fonts/truetype/freefont/FreeMono.ttf")
t,_ = c2.write('3.png')

生成验证码如下:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

第3个为小写字母o,第4个为大写字母O,第5个为数字0,第6个为小写字母z,第7个为大写字母Z,最后一个是数字2。人眼已经跪了有木有!但现在一般验证码对大小写是不做严格区分的,看自动识别什么样吧:

p3 = Image.open('3.png')
tesserocr.image_to_text(p3)
'AMOOZW\n\n'

人眼都跪的计算机当然也废了。但是,对于一些干扰小、形变不严重的,使用tesserocr还是十分简单方便的。然后将修改的claptcha.py的285行_drawLine还原,看添加干扰线的情况。

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

p4 = Image.open('4.png')
tesserocr.image_to_text(p4)
''

加了条干扰线就完全识别不出来了,那么有没有什么办法去除干扰线呢?

虽然图片看上去是黑白的,但还需要进行灰度处理,否则使用load()函数得到的是某个像素点的RGB元组而不是单一值了。处理如下:

def binarizing(img,threshold):
 """传入image对象进行灰度、二值处理"""
 img = img.convert("L") # 转灰度
 pixdata = img.load()
 w, h = img.size
 # 遍历所有像素,大于阈值的为黑色
 for y in range(h):
  for x in range(w):
   if pixdata[x, y] < threshold:
    pixdata[x, y] = 0
   else:
    pixdata[x, y] = 255
 return img

处理后的图片如下:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

可以看出处理后图片锐化了很多,接下来尝试去除干扰线,常见的4邻域、8邻域算法。所谓的X邻域算法,可以参考手机九宫格输入法,按键5为要判断的像素点,4邻域就是判断上下左右,8邻域就是判断周围8个像素点。如果这4或8个点中255的个数大于某个阈值则判断这个点为噪音,阈值可以根据实际情况修改。

def depoint(img):
 """传入二值化后的图片进行降噪"""
 pixdata = img.load()
 w,h = img.size
 for y in range(1,h-1):
  for x in range(1,w-1):
   count = 0
   if pixdata[x,y-1] > 245:#上
    count = count + 1
   if pixdata[x,y+1] > 245:#下
    count = count + 1
   if pixdata[x-1,y] > 245:#左
    count = count + 1
   if pixdata[x+1,y] > 245:#右
    count = count + 1
   if pixdata[x-1,y-1] > 245:#左上
    count = count + 1
   if pixdata[x-1,y+1] > 245:#左下
    count = count + 1
   if pixdata[x+1,y-1] > 245:#右上
    count = count + 1
   if pixdata[x+1,y+1] > 245:#右下
    count = count + 1
   if count > 4:
    pixdata[x,y] = 255
 return img

处理后的图片如下:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

好像……根本没卵用啊?!确实是这样的,因为示例中的图片干扰线的宽度和数字是一样的。对于干扰线和数据像素不同的,比如Captcha生成的验证码:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

从左到右依次是原图、二值化、去除干扰线的情况,总体降噪的效果还是比较明显的。另外降噪可以多次执行,比如我对上面的降噪后结果再进行依次降噪,可以得到下面的效果:

python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别

再进行识别得到了结果:

p7 = Image.open('7.png')
tesserocr.image_to_text(p7)
'8069 ,,\n\n'

另外,从图片来看,实际数据颜色明显和噪点干扰线不同,根据这一点可以直接把噪点全部去除,这里就不展开说了。
第一篇文章,先记录如何将图片进行灰度处理、二值化、降噪,并结合tesserocr来识别简单的验证码,剩下的部分在下一篇文章中和大家一起分享。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python中序列的修改、散列与切片详解
Aug 27 Python
Python使用sort和class实现的多级排序功能示例
Aug 15 Python
widows下安装pycurl并利用pycurl请求https地址的方法
Oct 15 Python
windows下 兼容Python2和Python3的解决方法
Dec 05 Python
详解python中自定义超时异常的几种方法
Jul 29 Python
Python学习笔记之函数的定义和作用域实例详解
Aug 13 Python
python实现批量文件重命名
Oct 31 Python
Pytorch损失函数nn.NLLLoss2d()用法说明
Jul 07 Python
详解Tensorflow不同版本要求与CUDA及CUDNN版本对应关系
Aug 04 Python
基于Python采集爬取微信公众号历史数据
Nov 27 Python
python 爬虫网页登陆的简单实现
Nov 30 Python
Python 中的函数装饰器和闭包详解
Feb 06 Python
实用自动化运维Python脚本分享
Jun 04 #Python
python中验证码连通域分割的方法详解
Jun 04 #Python
python 匹配url中是否存在IP地址的方法
Jun 04 #Python
Python实现ping指定IP的示例
Jun 04 #Python
用Python3创建httpServer的简单方法
Jun 04 #Python
Python3之简单搭建自带服务器的实例讲解
Jun 04 #Python
Python闭包执行时值的传递方式实例分析
Jun 04 #Python
You might like
php curl 登录163邮箱并抓取邮箱好友列表的代码(经测试)
2011/04/07 PHP
Ping服务的php实现方法,让网站快速被收录
2012/02/04 PHP
PHP实现的简单对称加密与解密方法实例小结
2017/08/28 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
javascript教程:关于if简写语句优化的方法
2014/05/17 Javascript
url中的特殊符号有什么含义(推荐)
2016/06/17 Javascript
Javascript 5种方法实现过滤删除前后所有空格
2016/06/22 Javascript
JS实现隔行换色的表格排序
2017/03/27 Javascript
JS仿QQ好友列表展开、收缩功能(第二篇)
2017/07/07 Javascript
JavaScript解析任意形式的json树型结构展示
2017/07/23 Javascript
微信小程序使用swiper组件实现层叠轮播图
2018/11/04 Javascript
JS实现将对象转化为数组的方法分析
2019/01/21 Javascript
[03:56]显微镜下的DOTA2第十一期——鬼畜的死亡先知播音员
2014/06/23 DOTA
[02:19]DOTA2上海特级锦标赛 观赛指南 Spectator Guide
2016/02/04 DOTA
Python应用库大全总结
2018/05/30 Python
Python 字符串与数字输出方法
2018/07/16 Python
python安装numpy和pandas的方法步骤
2019/05/27 Python
Python Celery多队列配置代码实例
2019/11/22 Python
解决pytorch DataLoader num_workers出现的问题
2020/01/14 Python
Python 解决相对路径问题:&quot;No such file or directory&quot;
2020/06/05 Python
Python编写单元测试代码实例
2020/09/10 Python
python 基于opencv操作摄像头
2020/12/24 Python
第二层交换机和路由器的区别?第三层交换机和路由器的区别?
2013/05/23 面试题
网络技术专业求职信
2014/02/18 职场文书
历史专业学生的自我评价
2014/02/28 职场文书
网站推广策划方案
2014/06/04 职场文书
欢度春节标语
2014/07/01 职场文书
开展创先争优活动总结
2014/08/28 职场文书
班级活动总结格式
2014/08/30 职场文书
道路交通事故人身损害赔偿协议书
2014/11/19 职场文书
小学班主任个人总结
2015/03/03 职场文书
复兴之路纪录片观后感
2015/06/02 职场文书
教师节大会主持词
2015/07/06 职场文书
中学后勤工作总结2015
2015/07/22 职场文书
2016年万圣节家长开放日活动总结
2016/04/05 职场文书
2019暑期安全倡议书!
2019/06/27 职场文书