记得很早以前,我对如携程飞猪等第三方平台购买火车票不用输入验证码感到很……牛!百度后发现其可能是实现了自动打码,或者说机器自动识别验证码,我很好奇。

后来,当我觉得我必须要给自己找些有趣的知识来学习的时候,脑海里萌生了去实现一个简单的验证码识别程序的想法。在一切未知以前,我觉得很难,甚至望而却步。但,真正一点点地行动下来,我发现,其实慢慢深入后,无论多么困难的问题,都能一点点解决。

不要着急,不要慌张,一点点地啃下来,一个方式不通,换个思路解决,不要轻易放弃。这个过程中,世上无难事,只怕有心人,古人诚不欺我。任何事情,流于表面而不做,是永远不会成长的——谨以告诫自己。

好了,废话不多说。

-----------------------------------------------------我是萌萌的分割线--------------------------------------------------------准备:

  • 语言:python
  • python库:opencv,sklearn,requests等

流程:整体大致流程为四部分,预处理,字符分割,字符标记分类,字符识别

  • 预处理:对原始验证码图片进行如灰度处理,二值化,降噪等处理,为下一步的字符分割提供一个好的素材
  • 字符分割:将预处理后的图片中的每个字符单独分割出来,本次分割的图片比较取巧,当预处理后,图片中各个字符的位置是相对固定的,所以,采用的分割方法为等距分割。
  • 字符标记分类:当字符分割好后,需要人为为字符进行分类标记,这个过程属于体力活,比较繁琐。我尝试过直接调用谷歌的ocr(光学字符识别)工具库pytesseract来代替人工识别,但是结果非常不好,无奈,还是只能先人工仔细分类。
  • 字符识别:分类好后,图片经过二值化转换为01的数据,写入一个txt格式文件中,作为训练集,其结果类似如下所示:

图片转换为可训练的数字文本数据

再利用机器学习算法对之进行训练,本文使用的是经典的svm(支持向量机)算法对图片验证码进行训练。支持向量机的原理以及优势百度谷歌均可详细查到。

实现:

  • 获取图片验证码

巧妇难为无米之炊,首先,我们要有原材料。在网上,我们可以很轻易地找到图片验证码。本文找的是csdn上的图片验证码。当然了,我们需要的验证码素材至少也要百张以上吧。如果傻乎乎地鼠标刷新保存图片,那效率太低了。要充分利用好可以利用的工具,python中的url库,requests库等都是很强大的工具库。用来爬取网络资源数据可以说是无往不利,哈哈,莫笑我略装*哈~

# coding=utf8
import requestsres = requests.get('img_code_url') # 这是一个get请求,获取图片资源
with open(file_path + "/%d.jpg" % num, "wb") as f: # 将图片保存在本地f.write(res.content)print("%d" % num + "获取成功")

如何获取图片验证码呢,我们可以利用浏览器的开发者模式(一般F12快捷键即可打开)或者利用专业的抓包软件如Charles(收费)等来查看获取。以上是个简单地将网上的图片验证码保存到本地的程序代码。

如果我们选择的图片验证码本身是十分清晰的没有太多混淆的状态,我们可以考虑用pytesseract直接对它进行识别。比如此类图片:

可以看出,以上这张图片验证码并未经过太多复杂处理,文本清晰,所以可以很容易ocr直接识别。但是如此类验证码则不然:

可以看出,这类验证码被经过了很多噪声处理,很多像素点在混淆,如果不经过处理直接用ocr识别会很糟糕。

  • 图片预处理

对图片进行灰度化,二值化,等距切割。

# coding=utf8
import cv2def pre_img(file_name):  # 图片灰度,二值化处理img = cv2.imread(file_name, 0)img = cv2.threshold(img, 180, 255, 1)

以上是对图片进行灰度化以及二值化的处理程序,利用的opencv库,opencv的使用方法可以看它的官方文档,或者百度搜索相应的博客等等。

然后,图片变成这样的了:

我们可以看出,此时图片上依然存在许多混淆的噪点,所以我们需要将这个噪点给去掉。通过观察图片,多数噪点是孤立的,非联通的,所以我们可以根据噪点周边的区域存在点的个数来判断其是否为噪点。

# coding=utf8
import numpy as np# 计算像素周边的点的个数
def sum_9_region(img, x, y):cur_pixel = img.getpixel((x, y))  # 当前像素点的值width = img.widthheight = img.heightif cur_pixel == 255:  # 如果当前点为白色区域,则不统计邻域值return 10if y == 0:  # 第一行if x == 0:  # 左上顶点,4邻域# 中心点旁边3个点sum = cur_pixel \+ img.getpixel((x, y + 1)) \+ img.getpixel((x + 1, y)) \+ img.getpixel((x + 1, y + 1))return 4 - sum / 255elif x == width - 1:  # 右上顶点sum = cur_pixel \+ img.getpixel((x, y + 1)) \+ img.getpixel((x - 1, y)) \+ img.getpixel((x - 1, y + 1))return 4 - sum / 255else:  # 最上非顶点,6邻域sum = img.getpixel((x - 1, y)) \+ img.getpixel((x - 1, y + 1)) \+ cur_pixel \+ img.getpixel((x, y + 1)) \+ img.getpixel((x + 1, y)) \+ img.getpixel((x + 1, y + 1))return 6 - sum / 255elif y == height - 1:  # 最下面一行if x == 0:  # 左下顶点# 中心点旁边3个点sum = cur_pixel \+ img.getpixel((x + 1, y)) \+ img.getpixel((x + 1, y - 1)) \+ img.getpixel((x, y - 1))return 4 - sum / 255elif x == width - 1:  # 右下顶点sum = cur_pixel \+ img.getpixel((x, y - 1)) \+ img.getpixel((x - 1, y)) \+ img.getpixel((x - 1, y - 1))return 4 - sum / 255else:  # 最下非顶点,6邻域sum = cur_pixel \+ img.getpixel((x - 1, y)) \+ img.getpixel((x + 1, y)) \+ img.getpixel((x, y - 1)) \+ img.getpixel((x - 1, y - 1)) \+ img.getpixel((x + 1, y - 1))return 6 - sum / 255else:  # y不在边界if x == 0:  # 左边非顶点sum = img.getpixel((x, y - 1)) \+ cur_pixel \+ img.getpixel((x, y + 1)) \+ img.getpixel((x + 1, y - 1)) \+ img.getpixel((x + 1, y)) \+ img.getpixel((x + 1, y + 1))return 6 - sum / 255elif x == width - 1:  # 右边非顶点# print('%s,%s' % (x, y))sum = img.getpixel((x, y - 1)) \+ cur_pixel \+ img.getpixel((x, y + 1)) \+ img.getpixel((x - 1, y - 1)) \+ img.getpixel((x - 1, y)) \+ img.getpixel((x - 1, y + 1))return 6 - sum / 255else:  # 具备9领域条件的sum = img.getpixel((x - 1, y - 1)) \+ img.getpixel((x - 1, y)) \+ img.getpixel((x - 1, y + 1)) \+ img.getpixel((x, y - 1)) \+ cur_pixel \+ img.getpixel((x, y + 1)) \+ img.getpixel((x + 1, y - 1)) \+ img.getpixel((x + 1, y)) \+ img.getpixel((x + 1, y + 1))return 9 - sum / 255# 去除噪点
def clear_noise(img):filename = './temp/clear_noise/' + str(random.random()) + '.png'x, y = img.width, img.heightfor i in range(x):for j in range(y):if sum_9_region(img, i, j) <= 2:# print(img.getpixel((i,j)))img.putpixel((i, j), 255)img = np.array(img)

以上程序实现的是当一个黑色像素点周边8个像素位置上小于或等于2个黑色像素点的情况,认定其为孤立的噪点,将它去除,则获得以下图片:

图片验证码的噪点被除去了。

接下来,要对其进行字符分割的处理,在这里,看出图片是一个很规整的,所以,简单地采用等距分割即可分割开。最后分割的图片如下:

以上是图片预处理的全过程,那么,要对验证码进行训练,一张图片是肯定不够的,所以,我们得批量下载几百张图片验证码。对它进行预处理,然后标记分类,最终得到以下结果(因为此类图片验证码只有0-9,所以分类为10类):

以上是其中分类为0的文件夹中的一部分数据,至此,分类完成。

  • 图片训练

将图片转换为01矩阵的形式。

import cv2def get_binary_pix(img):img = cv2.imread(img, 0)img = cv2.threshold(img, 180, 1, 1)img_binary = img.tolist()img_binary.append('label')pixs = [str(i) for i in img_binary]content = ','.join(pixs)with open("train_data.txt", "a+") as f:f.write(content)

利用sklearn库的svm算法对之进行训练。

from sklearn.svm import SVCdef train():dataset = load_data()raw, col = dataset.shapeX = dataset[:, :col - 1]Y = dataset[:, -1]clf = SVC()clf.fit(X, Y)jl.dump(clf, 'model.pkl')

至此,训练完毕,模型建立好了。此时,再下载几个验证码进行测试,同样,对测试验证码进行预处理等流程。

测试结果很理想。

至此,图片验证码识别完成。

---------------------------------------------------我是萌萌的分割线--------------------------------------------------------

在开始实现之前,心里其实很不确定最后是否可以真的实现出来,但是,不懂就要去查,百度,谷歌,博客,书籍,等等方式,感谢公网上的开放的知识,让我学到了很多很多。

源码已传github上:

portfloat/captcha_recgithub.com

,欢迎大家clone。写得不好,欢迎大家批评指正,谢谢~

【成长笔记】图片验证码识别相关推荐

  1. 网络爬虫笔记—滑动验证码识别

    网络爬虫笔记-滑动验证码识别 一.什么是滑动验证码 点击之前 点击之后 像这种通过滑动图片,补全缺口的方式,就是滑动验证码. 二.识别思路 1)使用selenium库操作谷歌浏览器,打开目标网站:关于 ...

  2. 网络爬虫笔记—图形验证码识别

    网络爬虫笔记-图形验证码识别 <兄弟们,本文章开启了关注后阅读.大家如不想关注,可直接微信搜索"宏蜘蛛"或文章标题,查看文章.> 1.什么是图形验证码 像知网注册界面的 ...

  3. 字符识别Python实现 图片验证码识别

    字符型图片验证码识别完整过程及Python实现 1   摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...

  4. 图片验证码识别程序全面分析

    我们在登陆账号的时候,发现有图片验证码需要识别,我们在注册账号的时候,也会有图片验证码需要识别.很多"程序猿"可能也在找如何进行图片验证码识别的编程.图片验证码常有,但是关于如何快 ...

  5. 微博模拟登陆的方法 + 图灵图像图片验证码识别平台 识别验证码(97%正确率)Python + Selenium+Chrome

    最近遇到一个问题,需要频繁切换账号登陆微博,但是需要识别微博的验证码,比较麻烦.而且因为需要24h不间断的操作,所以没法使用人工打码平台,而且打码平台也比较贵,延迟又高.最后找到了一个可以机器识别出来 ...

  6. 字符型图片验证码识别完整过程及Python实现

    1   摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越来越严峻.本文介绍了一套字符验证码识别的完整流程 ...

  7. c++ 图片验证码识别_基于tensorflow 实现端到端的OCR:二代身份证号识别

    最近在研究OCR识别相关的东西,最终目标是能识别身份证上的所有中文汉字+数字,不过本文先设定一个小目标,先识别定长为18的身份证号,当然本文的思路也是可以复用来识别定长的验证码识别的. 本文实现思路主 ...

  8. python识别图片中数字_Python图像处理之图片验证码识别

    在上一篇博客Python图像处理之图片文字识别(OCR)中我们介绍了在Python中如何利用Tesseract软件来识别图片中的英文与中文,本文将具体介绍如何在Python中利用Tesseract软件 ...

  9. 图片验证码识别-自动登录工具开发

    涉及工具技术 Tampermonkey jQuery Tesseract-OCR Flask Pillow 前言 开发软件系统时必然会有用户登陆的模块.每次验证自己的功能时,总是绕不开输入账号密码,这 ...

最新文章

  1. 分享几段祖传的 Python 代码,拿来直接使用!
  2. HTML5原生拖拽/拖放 Drag Drop 详解
  3. 寻宝机器人科技竞赛_第19届广西青少年机器人竞赛组织工作筹备会暨广西青少年科技辅导员交流活动在贺州举行...
  4. js校验文本框只能输入数字(包括小数)
  5. RobotFramework自动化框架—robot文件中调用自定义库
  6. html5画布funcition,2020前端基础知识学习第一节(示例代码)
  7. Need to upgrade docker package to 17.06.0+. Docker升级到最新版本
  8. SpringBoot 入门知识点详解
  9. [转载] Python Numpy基础总结
  10. 语言题库安装包312mb_大学为什么要考取计算机二级,以后很需要,附二级Msoffice题库...
  11. 基础04继承、super、this、抽象类
  12. java加按钮_剪辑大神都在用的加字幕神器,你知道嘛
  13. 嵌入式Linux--根文件系统(二)BusyBox构建根文件系统
  14. Excel每页都打印表头
  15. 传奇手游战神引擎多机多区配置方法
  16. 华硕java安装教程win10_华硕台式机如何重装win10系统,win10系统一键安装教程
  17. h3c.服务器 装系统,h3c服务器u盘安装linux系统安装
  18. uniapp 简易的商品分类垂直分类(单项联动)
  19. 卡西欧G-SHOCK 5146/5425使用说明书
  20. 建筑八大员考试武汉施工员考试道路施工技术的管理与安全控制

热门文章

  1. 利用GitHub Actions每天自动从Pixiv爬虫日推图片并存放到仓库
  2. 增量式编码器和绝对式编码器区别
  3. 等保2.0基本要求与等保1.0对比解读
  4. 如何选择项目负责人?选谁做项目负责人?
  5. Leetcode 79. 单词搜索(迷宫回溯)
  6. [大数据文章之其四] 概率数据结构简介
  7. maximo跟java_maximo中直接应用得到数据库联接
  8. 安装scikit-learn问题
  9. No transaction aspect -managed TransactionStatus in scope 事务回滚报错
  10. 旁轴相机,单反相机之间的区别(转)