【每周代码】深度学习破解字符验证码

全自动区分计算机和人类的公开图灵测试(英语:Completely Automated Public Turing test to tell Computers and Humans Apart,簡稱CAPTCHA),俗称验证码,是根据随机字符生成一幅图片,然后在图片中加入干扰象素,用户必须手动填入,防止有人利用机器人自动批量注册、灌水、发垃圾广告等等 。

验证码的作用是验证用户是真人还是机器人;设计理念是对人友好,对机器难。

在这里插入图片描述

如图所示,上图是比较常见的字符验证码,还有一些更加复杂的验证码这里没有讨论(比如图片,或者提问之类的)

破解验证码有几种常见的方式:

  1. 人力打码
  2. 绕过验证码的漏洞
  3. 字符串识别(本文重点

老规矩,参考的文章优先列出来:
http://blog.topspeedsnail.com/archives/10858
https://www.cnblogs.com/beer/p/7392397.html
其中第一个链接提供了主体算法的代码实现
第二个链接对代码进行了模块化优化,对函数功能进行了划分,使得代码更好理解,更清晰明了
本文拟采用第二个链接的代码
如果有优化的部分,会在文章中提到。

在一开始搭建TensorFlow的框架时候,有一个非常经典的demo,叫做OCR手写字符串识别,这个在吴恩达的课程里也有提到。
这个代表了字符串识别的最初发展趋势:将数字分割为单个字符,然后识别单个字符
但是这样面临了一个问题:当字符之间相互重叠,机器就不容易分割了。

得益于基于卷积神经网络CNN的人工智能技术的发展,目前基于主流的深度学习框架的直接开发出 端到端不分割 的识别方式,而且在没有经过太多trick的情况下,已经可以达到95%以上的识别率。

正如上面所说,本项目实现的方法不需要分割验证码,而是把验证码做为一个整体进行识别。

参考文献:

通过深度学习+训练数据+计算能力,可以训练出一个破解验证码的模型

这里获得训练数据的方法:

  1. 手动(不差钱的也可以从打码网站购买
  2. 破解验证码生成机制,自动生成
  3. 。。。。

这里采用了第一个链接里提到的,自己制作的验证码生成器,然后训练CNN模型来破解自己的验证码生成器
(多大仇+没事儿找事儿系列)

碎碎念:其实验证码机制本来就是一个悖论,它需要机器生成一个机器也无法识别的验证码。盲目提高验证码难度,根本就是在为难普通人而已,我已经被好多网站的验证码坑过了,死活登不上去=自己不是人。

验证码生成器

代码在gen-captcha.py里
感觉自己就像一个智障。。按着别人的代码重写一遍也会错。。
还认真的debug了半天:)

成功以后试着跑了一下,如下图所示:
在这里插入图片描述

这一步应该还挺简单的,代码难度不大,如图所示

from captcha.image 
import ImageCaptcha # pip install captcha
import numpy as np
import matplotlib.pyplot as pltfrom PIL 
import Imageimport random
#验证码中出现的字符,不用汉字
number = ['0','1','2','3','4','5','6','7','8','9']
alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']ALPHABET = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
# 验证码一般都无视大小写;验证码长度4个字符
def random_captcha_text(char_set=number + alphabet +  ALPHABET,captcha_size=4):    
captcha_text = []    
for i in range(captcha_size):        
c = random.choice(char_set)        
captcha_text.append(c)    
return captcha_text
#生成字符对应的验证码
def gen_captcha_text_and_image():   
 image = ImageCaptcha()
    captcha_text = random_captcha_text()    
    captcha_text = ''.join(captcha_text)
    captcha = image.generate(captcha_text)   
     #image.write(captcha_text,captcha_text + '.jpg') #写到文件
    captcha_image = Image.open(captcha)    
    captcha_image = np.array(captcha_image)    
    return captcha_text, captcha_image 
    if __name__ == '__main__':    
    # 测试    
    text, image = gen_captcha_text_and_image()     
    f = plt.figure()    
    ax = f.add_subplot(111)    
    ax.text(0.1, 0.9,text, ha='center', va='center', transform=ax.transAxes)    
    plt.imshow(image)     
    plt.show()   

#####模型预测

这里坑还挺多的,一点点的说吧
首先是完全按照参考代码跑了一遍,我的配置是win10,在anaconda下的Python3.6虚拟环境环境。
一开始按照pip install tensorflow 安装的tensorflow cpu 版本
跑的时候报了一个错
查了一下,说是因为cpu版本的tensorflow版本可以用avx2或者sse2加速(GPU版本不用),但是pip install的默认版本是不支持这个加速的。

这里有两种解决方法:

  1. 忽视警报,不影响正常使用
  2. 卸载前面的版本,重新在官网下载安装,具体对应的版本可以看官网的readme,写的还挺详细的。链接点这里

我是选择了重新下载再次运行后不报错了。
开始提示我save model有问题
我查了一下,说是因为路径有问题,在
saver.save(sess, “crack_capcha.model”, global_step=step)
这一句的“crack_capcha.model“前加上./或者绝对路径就可以了。

(我这简直是一部智障犯错史)

在模型训练的时候,建议一开始可以放宽精度(比如0.2就可以存储,否则辛辛苦苦训练了一天,最后发现save model 有问题很容易心态爆炸┓( ´∀` )┏

训完的模型会出现这样的几个文件
在这里插入图片描述
其中13100是迭代的epoch次数,每个人可能不同

这里在后面的调用中,因为模型每次训练都会覆盖上一次的模型数据,所以为了避免总是修改名字,使用了tf.train.latest_checkpoint(’.’)
这个函数来是调用最新的checkpoint文件,避免了反复修改文件的麻烦

训练完模型以后就可以使用testmodel.py来进行调用了
预测效果还不错(毕竟我为了节省时间,降低了训练的期待精度)
在这里插入图片描述

在这里我还犯了一个坑爹的错误
在写trainmodel的时候,因为没有写完整工程的经验,所以没有把运行trainmodel的命令写在main函数里,也没有把整个文件写成一个类
这样,在直接执行这个文件的时候,是没问题的
但是,在testmodel调用这个文件的时候,训练就要被重新开始一次
是真的蠢本人了。。。

在文章的最后,第二个链接的作者探讨了在训练模型的时候,激活函数选择sigmoid和softmax的原因以及对比

说到这个就说点闲话吧,在微软面试的时候,面试官问了我,为什么LR的损失函数是现在的样子,而不是mse或者其他同样很经典的算法
当时就卡壳的很尴尬

都说现在算法领域,工业和理论有着很大的差距,工业上的很多使用,都很难得到理论的支持或者证明,说难听点就是“瞎几把调”,很多函数或者模型的使用,都是因为“大家都这么用”,或者“大佬说这么用”,而别没有深入思考过原因
现在看很多资料很费事儿。觉得也算是偿还自己当年不认真学数学的债了。作为一个数学系毕业的学生,还是想要努力发挥自己在这方面的优势,不能总是做一个知其然不知其所以然的“调参工程师”。

偷偷许一个2019年的愿望吧,希望我能在未来的某一天,能提出一个优秀的算法,让很多很多的人调用我的库~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值