全自动区分计算机和人类的图灵测试(Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),俗称验证码,是一种区分用户是计算机和人的公共全自动程序。验证码的主要目的是强制人机交互来抵御机器自动化攻击,为了确保服务器系统的稳定和用户信息的安全,越来越多的网站采用了验证码技术。图片验证码是目前最常用的一种。

最近在一个爬虫项目中遇到了验证码,需要机器自动识别绕过。这些验证码大都分辨率都较低,本身信息量不大。在网上调研了资料和文献后,分别采用OCR识别和模板库匹配方法对不同类型验证码进行了识别。主要过程可以分解为三个步骤:1.图片清理,2.字符切分,3.字符识别。以下结合工作经验和调研内容讲解一些常用的验证码识别方法和过程。

1.图片清理

图片清理是为接下来的机器学习或模板匹配阶段做准备的,指通过灰度化、二值化、干扰点清理等过程,得到比较干净的图片数据,具体样例见下表。

1.1 彩色去噪

在计算机中使用最多的 RGB色彩空间,分别对应红、绿、蓝三种颜色,通过调配三个分量的比例来组成各种颜色。以最常见的32位颜色为例,一个分量是用8位来表示,最大值是255,灰度图是指组成颜色的三个分量相等。原始彩色图片包含的信息量是最大的,如果验证码图片中有一些利用颜色反差加的干扰点或者线条,最好能在该阶段做初步清理。比较简单的一种处理方法是采用3*3矩阵对图像进行平滑处理,即对每个像素取他所在3*3矩阵所有点的RGB均值,分别作为新的RGB值。稍微做点优化,取3*3矩阵中RGB三维欧式距离最接近均值的点作为新值。

1.2 灰度化

在彩色电视机系统中,通常使用一种叫 YUV 的色彩空间,其中Y表示亮度信号,对于人眼来说,亮度信号(Y)是最敏感的,如果将彩色图像转换为灰度图像,仅仅需要转换并保存亮度信号就可以。从RGB到YUV空间的Y转换有一个很著名的心理学公式:Y = 0.299R + 0.587G + 0.114B。

而实际应用时,将系数缩放1000倍来实现整数运算:Gray = (R*299 + G*587 + B*114 + 500) / 1000 。注意后面那个除法是整数除法,所以需要加上500来实现四舍五入。该公式的另一个简化变种也很流行:Gray = (R*30 + G*59 + B*11 + 50) / 100。更快的算法是采用移位代替除法,所以可以将系数缩放成 2的整数幂,再做右移操作。该整数取7从精度和速度上最合适:Gray = (R*0.299*2^7 + G*0.587*2^7 + B*0.114*2^7)>>7 = (R*38 + G*75 + B*15)>>7

1.3 二值化

为了简化接下来的计算,需要把灰度图片转化成黑白二值图。默认情况下值大于127的像素点被设置为白色,其余像素点设置为黑色。当然,这个阈值也需要根据图片的实际情况计算调整。一般采用直方图统计确定动态阈值的方法比较靠谱,白底黑字的取直方图靠左边的波谷位置作为阈值,黑底白字则取直方图右边的波谷位置作为阈值,将背景和字符作很好的区分。

1.4 底色统一

如果是黑底白字的图片,需要转换成白底黑字,如以上图B。

1.5 干扰点清理

在黑白二值图片去噪阶段,常用的去噪方法为联通性去噪,通常采用8向联通来计算连通点个数,若某个点的连通点数目小于预设的阀值,则认为这些点都是噪声点。这一简单粗暴的清理方法,通常情况下是非常有效的。

2 字符切分

该阶段对前期预处理后的图片进行切割处理,定位和分离出整幅图片中的每个孤立的字符主体部分。主要采用X轴和Y轴投影的方法,即统计对应坐标上黑色像素点的个数。对于图片

得到的X轴和Y轴投影分别如下。利用X轴投影可以切割出单独的字符,再分别利用Y轴投影,裁剪掉顶部和底部的空白部分。

3. OCR软件识别

我们使用的是开源的OCR识别引擎Tesseract,初期由HP实验室研发,后来贡献给了开源软件业,后经由Google进行优化并重新发布。调用代码以及识别效果如下:

api = tesseract.TessBaseAPI()
api.Init(".","eng",tesseract.OEM_TESSERACT_ONLY) #初始化
api.SetPageSegMode(tesseract.PSM_SINGLE_LINE) #设置为单行字符串模式
api.SetVariable("tessedit_char_whitelist", whitelist) #设置白名单
stringOCR = tesseract.ProcessPagesBuffer(mBuffer, len(mBuffer), api)

该方法的优点是:开发量少;比较通用,适合于各种变形较少的验证码;对于扭曲不严重的字母和数字识别率高。缺点也很明显:对于扭曲的字母和数字识别率大大降低;对于字符间有粘连的验证码几乎难以正确识别;很难针对特定网站的验证码做定制开发。

4.模板库匹配

4.1 建立字符模板库

首先需要针对目标网站收集大量的验证码;然后根据上一章节的方法,进行图片清理;最后按照固定的长宽值切分出字符模板图,保存文件名带上对应字符的标记。

4.2 字符匹配

首先,把目标验证码图片按字符个数切分,这里的图片切分方法必须与模板制作时的切分方法一致,得到与模板图同样大小的字符图。接下来通常的做法是使用汉明距离或编辑距离定义相似度,并用KNN方法得到K个最相似的字符,最后从K个字符中选取出现次数最多的那个作为匹配结果。参考了文献[1]中K取值和字符识别率的变化关系(如下图)。

然后,我们把K取值为5。并且把相似度重新定义为:matchScore = dotMatch^2 / (dotCaptcha * dotTemplate),其中dotMatch为验证码字符图与模板图对应位置都是黑色点的个数,dotCaptcha为验证码字符图中黑色点个数,而dotTemplate为模板图中黑色点个数。取这个分母是为了防止某些黑色点较多的模板图在匹配度计算中始终得到较大值。识别效果如下表:

该方法的优点是:原理简单直观;可以针对不同网站定制优化;对于扭曲的字母和数字识别率较高。缺点是:开发量大,需要定制开发;需要收集大量的字符图片库;字符变化很多的情况,匹配次数增加速度下降;对于字符有粘连的图片识别率低;

5. 支持向量机

支持向量机通俗来讲是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。实际应用上,往往遇到的是非线性可分得情况,因此通过核函数把低维向量映射到更高维空间,使得样本满足线性可分。

验证码识别问题实际上是其中单个字符识别问题,而在字符可穷举的情况下,比如只有英文字符和数字,单个字符识别问题其实是一个分类问题。一个英文字母或数字表示一类,而验证码中切分后得到的单个字符需要被机器自动分到某一类。一般情况下,把单个字符的灰度图片转成整形数组,数组的每一个元素表示图片的一个像素,即一个特征维度。我们切分得到的图片大小为10x16=160像素,即有160个特征,当特征数量多且特征之间关系不明确时,采用支持向量机分类比较合适。

6. 神经网络

以上验证码识别都依赖于字符切分,切分的好坏几乎直接决定识别的准确程度。而对于有字符粘连的图片,往往识别率就会低很多。目前验证码识别最先进的是谷歌在识别“街景”图像中门牌号码中使用的一套的算法。该算法将定位、分割和识别等几个步骤统一起来,采用一种“深度卷积神经网络”(deep convolutional neural network)方法进行识别,准确率可以达到99%以上。谷歌拿自有的reCAPTCHA验证码做了测试,结果发现,对于难度最大的reCAPTCHA验证码,新算法的准确率都达到 99.8%,这可能也好于大多数人为验证。

验证码作为一种辅助安全手段在Web安全中有着特殊的地位,了解验证码识别的方法和原理,不仅有利于绕过验证码抓取网站内容,而且有利于设计更安全合理的验证码。

网易云安全(易盾)行为式验证码超10亿次完美验证,坚固守卫网站安全第一道防线。网易云易盾提供新一代网站验证码,包括智能验证码、滑动验证码等形式,验证码接口稳定性 99.9%,感知威胁可智能切换验证难度,告别繁琐验证,保护业务安全,点击可免费试用。

相关文章:
【推荐】 初识Continuation

如何识别图片验证码?相关推荐

  1. 用Python模拟识别图片验证码并发送手机验证码

    1.导语 大家好,好久不见.又到每日分享Python小技能的时候了.最近因为疫情影响,所以更新内容比较慢-今天周一,就来更新一波,心血来潮,是时候上线经营了.其实也没想到有啥好分享的,不如分享一些干货 ...

  2. python—简单数据抓取四(利用超级鹰的ocr识别图片验证码模拟登录超级鹰网站、利用百度云的ocr识别自如租房网价格图片获取到自如网的价格)

    学习目标: python学习二十四 -简单数据抓取四 学习内容: 1.利用超级鹰的ocr识别图片验证码模拟登录超级鹰网站 2.利用百度云的ocr识别自如租房网的价格图片,获取到自如网的价格数据 1.利 ...

  3. python selenium 验证码识别_Python网络爬虫之如何用代码识别图片验证码

    验证码 当我们在爬取某些网站的时候,对于一些频繁请求,网站会识别你是机器还是人.如果是机器,直接不允许你访问这个网站了,直接返回404或者禁止访问. 最常见的方式就是验证码.验证码的主要功能就是区分当 ...

  4. python 识别图形验证码_python爬虫20 | 小帅b教你如何用python识别图片验证码

    当你在爬取某些网站的时候 对于你的一些频繁请求 对方会阻碍你 常见的方式就是使用验证码 验证码的主要功能 就是区分你是人还是鬼(机器人) 人 想法设法的搞一些手段来对付技术 而 技术又能对付人们的想法 ...

  5. 易语言python识别图片验证码_图片识别-打码平台-打码网站-识别验证码-图鉴网络科技有限公司...

    Android脚本 Import "Cjson.lua" Import "ttddm.lua" Import "ShanHai.lua" / ...

  6. 百度云 OCR 识别图片验证码

    操作系统:Mac OS Python版本:3.7.2 OCR:百度云 遇到的问题: API测试过程中,遇到API Resopnse 为图片验证码的情况,需要对图片进行识别得到text code,进行断 ...

  7. python爬虫20 | 小帅b教你如何使用python识别图片验证码

    当你在爬取某些网站的时候 对于你的一些频繁请求 对方会阻碍你 常见的方式就是使用验证码 验证码的主要功能 就是区分你是人还是鬼(机器人) 人 想法设法的搞一些手段来对付技术 而 技术又能对付人们的想法 ...

  8. 教程 | 用Python识别图片验证码中的文字

    作者 | 老表 来源 | 简说Python(ID:xksnh888xksnh888) [导语]在今天这篇文章中,作者分享给大家一个有趣又干货满满的 Python 项目.通过这份教程,大家不仅又多了一个 ...

  9. Python OCR识别图片验证码(二)

    操作系统:Windows Python:3.5 欢迎加入学习交流QQ群:657341423 上节讲到验证码的简单识别 但对于一些复杂的验证码,我们需要做一些简单的图片处理才能识别. 例如,我要识别这些 ...

  10. python实现OCR识别图片验证码

    用cv2模块读取和显示模块 #导包cv2拓展模块 import cv2#先给窗体起名字 cv2.namedWindow("ShowImage1") cv2.namedWindow( ...

最新文章

  1. 信息处理进入了计算机领域,信 息 处 理 进 入 了 计 算 机 领 域 ,实 质 是 进 入 了()的 领 域 。...
  2. python窗体设置italic_007萝卜头学python:Python GUI 之Tkinter
  3. Python 国产库推荐之 musicpy
  4. 浪潮在美发布InCloudRail超融合一体机,助力数据中心平滑上云
  5. Ubuntu 下JDK安装
  6. 变速更顺滑_CVT变速箱中的小弱鸡?10万公里必坏?变速箱该如何养护?
  7. 吴恩达机器学习(十)支持向量机(SVM)
  8. 作为互联网面临的最大危险之一,当前的 DDoS 趋势如何?
  9. 二叉树 中序遍历 python_leetcode No.105 从前序与中序遍历序列构造二叉树
  10. oracle flex asm ceph,ORACLE 12C Flex ASM转换
  11. java日期互转:LocalDateTime、String、Instant、Date
  12. Android之简单的BMI计算器(运用两个界面跳转显示)
  13. 诡异的问题“该字符串未被识别为有效的 DateTime”
  14. PHP-利用阿里云邮件推送免费发邮件详细步骤
  15. blender中常用快捷键的总结
  16. VMware workstation环境下opnsense的安装
  17. 熊猫烧香病毒 杀毒记
  18. scala项目的全局配置实践
  19. 《“ 追梦人” 的逐梦路:探寻大学生创客群体的发展之道》
  20. ios浏览器无法播放视频-node.js文件传输问题

热门文章

  1. 湘潭python培训_湘潭Python 黑帽SEO
  2. ubuntu18.04+gtx1660ti+nvidia驱动+cuda10.1+cudnn7.6
  3. 一句话总结—打发无聊的时间
  4. BUAA 软件工程 第一次作业
  5. 干货 | 聊聊这些年总结的一些学习方法
  6. php 保留两位小数
  7. html5的经典特效思路
  8. 手机制式入门级知识点
  9. GitHub education pack申请流程及云主机相关介绍
  10. mysql collect_set_spark sql concat_ws() collect_set() collect_list() 字段值拼接