前言
CAPTCHA全称Completely Automated Public Turing Test to Tell Computers and Humans Apart,即全自动区分人机的图灵测试。这也是验证码诞生的主要任务。但是随着近年来大数据运算和机器视觉的发展,用机器视觉识别图像已经变得非常容易,过去用于区分人机的验证码也开始变得不再安全。
接下来就让我们从零开始,深入图像处理和算法构建,来看看使用机器视觉来识别过时的验证码( 如下所示 )究竟可以有多简单。
载入需要的程序包 & 设置全局变量
import requests import time from io import BytesIO from PIL import Image import os import numpy as np # 获取验证码的网址 CAPT_URL = "http://xxxxxxxxxxxx.cn/servlet/ImageServlet" # 验证码的保存路径 CAPT_PATH = "capt/" if not os.path.exists(CAPT_PATH): os.mkdir(CAPT_PATH) # 将验证码转为灰度图时用到的"lookup table" THRESHOLD = 165 LUT = [0]*THRESHOLD + [1]*(256 - THRESHOLD)
从网站获取验证码
capt_fetch()方法非常简单,我们直接从网站获取验证码,将其转换为Image对象,等待被训练和测试等环节调用。
def capt_fetch(): """ 从网站获取验证码,将验证码转为Image对象 :require requests: import requests :require time: import time :require BytesIO: from io import BytesIO :require Image: from PIL import Image :param: :return capt: 一个Image对象 """ # 从网站获取验证码 capt_raw = requests.get(CAPT_URL) # 将二进制的验证码图片写入IO流 f = BytesIO(capt_raw.content) # 将验证码转换为Image对象 capt = Image.open(f) return capt
保存验证码到本地
def capt_download(): """ 将Image类型的验证码对象保存到本地 :require Image: from PIL import Image :require os: import os :require capt_fetch(): 从nbsc网站获取验证码 :require CAPT_PATH: 验证码保存路径 :param: :return: """ capt = capt_fetch() capt.show() text = raw_input("请输入验证码中的字符:") suffix = str(int(time.time() * 1e3)) capt.save(CAPT_PATH + text + "_" + suffix + ".jpg")
图像预处理
def capt_process(capt): """ 图像预处理:将验证码图片转为二值型图片,按字符切割 :require Image: from PIL import Image :require LUT: A lookup table, 包含256个值 :param capt: 验证码Image对象 :return capt_per_char_list: 一个数组包含四个元素,每个元素是一张包含单个字符的二值型图片 """ capt_gray = capt.convert("L") capt_bw = capt_gray.point(LUT, "1") capt_per_char_list = [] for i in range(4): x = 5 + i * 15 y = 2 capt_per_char = capt_bw.crop((x, y, x + 15, y + 18)) capt_per_char_list.append(capt_per_char) return capt_per_char_list
图像预处理的效果如下:
原始图像
灰度图
黑白图
按字符切分后的黑白图像
由于字符宽窄有差异,这里我们按字符切分后,有些字符会多出来一部分,有些字符会丢失一部分。比如7多了一笔看起来像个三角形,M少了一竖看起来像N。但只要符号之间有区分度,依然能够准确分类。
提取图像中的特征值
def capt_inference(capt_per_char): """ 提取图像特征 :require numpy: import numpy as np :param capt_per_char: 由单个字符组成的二值型图片 :return char_features:一个数组,包含 capt_per_char中字符的特征 """ char_array = np.array(capt_per_char) total_pixels = np.sum(char_array) cols_pixels = np.sum(char_array, 0) rows_pixels = np.sum(char_array, 1) char_features = np.append(cols_pixels, rows_pixels) char_features = np.append(total_pixels, char_features) return char_features.tolist()
生成训练集
这里我们会将预分类的每张验证码分别读入内存,从它们的图像中提取特征值,从它们的名称中提取验证码所对应的文字(标签),并将特征值与标签分别汇总成列表,注意train_labels中的每个元素是与train_table中的每一行相对应的。
def train(): """ 将预分类的验证码图片集转化为字符特征训练集 :require Image: from PIL import Image :require os: import os :require capt_process(): 图像预处理 :require capt_inference(): 提取图像特征 :param: :return train_table: 验证码字符特征训练集 :return train_labels: 验证码字符预分类结果 """ files = os.listdir(CAPT_PATH) train_table = [] train_labels = [] for f in files: train_labels += list(f.split("_")[0]) capt = Image.open(CAPT_PATH + f) capt_per_char_list = capt_process(capt) for capt_per_char in capt_per_char_list: char_features = capt_inference(capt_per_char) train_table.append(char_features) return train_table, train_labels
定义分类模型
def nnc(train_table, test_vec, train_labels): """ Nearest Neighbour Classification(近邻分类法), 根据已知特征矩阵的分类情况,预测未分类的特征向量所属类别 :require numpy: import numpy as np :param train_table: 预分类的特征矩阵 :param test_vec: 特征向量, 长度必须与矩阵的列数相等 :param labels: 特征矩阵的类别向量 :return : 预测特征向量所属的类别 """ dist_mat = np.square(np.subtract(train_table, test_vec)) dist_vec = np.sum(dist_mat, axis = 1) pos = np.argmin(dist_vec) return train_labels[pos]
测试模型分类效果
最后,我们需要测试我们的理论是否有效,通过调用test()方法,我们会先从网站获取验证码图像,对图像进行处理、特征提取,然后调用nnc()方法对提取到的四组特征值做近邻分类,分别得到验证码中的四个字符。最后将验证码图像和识别到的字符传出,方便我们比对识别结果。
def test(): """ 测试模型分类效果 :require Image: from PIL import Image :require capt_fetch(): 从nbsc网站获取验证码 :require capt_process(): 图像预处理 :require capt_inference(): 提取图像特征 :train_table, train_labels: train_table, train_labels = train() :param: :return capt: 验证码图片 :return test_labels: 验证码识别结果 """ test_labels = [] capt = capt_fetch() capt_per_char_list = capt_process(capt) for capt_per_char in capt_per_char_list: char_features = capt_inference(capt_per_char) label = nnc(train_table, char_features, train_labels) test_labels.append(label) test_labels = "".join(test_labels) return capt, test_labels
训练数据,识别验证码
# 下载120张图片到本地 for i in range(120): capt_download() # 模型的训练与测试 train_table, train_labels = train() test_capt, test_labels = test()
最后我们调用test()方法验证我们的理论是否成立,识别效果如下:
获取到的验证码
识别结果
结语
至此,我们通过机器视觉识别验证码的任务算是完成了。至于正确率,大概每10张验证码,40各字符中会预测失误一个字符。这已经比较接近我们人类的识别准确率了,当然,我们还可以通过建立起更庞大的学习库,使用knn或更复杂的模型,使用卷积核处理图片等方式,使识别准确率更高。
当然,我们这里所用的方法,只适用于识别比较简单的验证码。对于更加复杂的验证码(如下图),以上方法是不起作用的,但这并不代表这样的验证码不能通过机器视觉进行识别。
我们已经看到,随着机器视觉的发展,通过传统的验证码来区分人机已经越来越难了。当然,为了网络的安全性,我们也可使用更复杂的验证码,或者新型的验证方式,比如拖动滑块、短信验证、扫码登陆等。
以上所述是小编给大家介绍的python自动识别验证码详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
本文向大家介绍详解Python验证码识别,包括了详解Python验证码识别的使用技巧和注意事项,需要的朋友参考一下 以前写过一个刷校内网的人气的工具,Java的(以后再也不行Java程序了),里面用到了验证码识别,那段代码不是我自己写的:-) 校内的验证是完全单色没有任何干挠的验证码,识别起来比较容易,不过从那段代码中可以看到基本的验证码识别方式。这几天在写一个程序的时候需要识别验证码,因为程序是
本文向大家介绍Python完全识别验证码自动登录实例详解,包括了Python完全识别验证码自动登录实例详解的使用技巧和注意事项,需要的朋友参考一下 1、直接贴代码 2、控制台日志 以上这篇Python完全识别验证码自动登录实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。
本文向大家介绍python验证码识别的实例详解,包括了python验证码识别的实例详解的使用技巧和注意事项,需要的朋友参考一下 其实关于验证码识别涉及很多方面的内容,入手难度大,但是入手后,可拓展性又非常广泛,可玩性极强,成就感也很足,对这感兴趣的朋友们下面跟着小编一起来学习学习吧。 依赖 利用google ocr来识别验证码 但是pytesseract本身识别率不高,而且一般网站的验证码都带有大
本文向大家介绍Python网站验证码识别,包括了Python网站验证码识别的使用技巧和注意事项,需要的朋友参考一下 0x00 识别涉及技术 验证码识别涉及很多方面的内容。入手难度大,但是入手后,可拓展性又非常广泛,可玩性极强,成就感也很足。 验证码图像处理 验证码图像识别技术主要是操作图片内的像素点,通过对图片的像素点进行一系列的操作,最后输出验证码图像内的每个字符的文本矩阵。 读取图片 图片降噪
本文向大家介绍Python验证码识别的方法,包括了Python验证码识别的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python验证码识别的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的Python程序设计有所帮助。
本文向大家介绍mac使用python识别图形验证码功能,包括了mac使用python识别图形验证码功能的使用技巧和注意事项,需要的朋友参考一下 前言 最近在研究验证码相关的操作,所以准备记录下安装以及使用的过程。虽然之前对验证码的破解有所了解的,但是之前都是简单使用之后就不用了,没有记录一个详细的过程,所以后面再用起来也要重新从网上查找资料比较麻烦,所以这里准备对研究过程的关键点做一个记录。 首先