zoukankan      html  css  js  c++  java
  • 基于LeNet网络的中文验证码识别

    基于LeNet网络的中文验证码识别

    由于公司需要进行了中文验证码的图片识别开发,最近一段时间刚忙完上线,好不容易闲下来就继上篇《基于Windows10 x64+visual Studio2013+Python2.7.12环境下的Caffe配置学习 》文章,记录下利用caffe进行中文验证码图片识别的开发过程。由于这里主要介绍开发和实现过程,CNN理论性的东西这里不作为介绍的重点,遇到相关的概念和术语请自行研究。目前从我们训练出来的模型来看,单字识别率接近96%,所以一个四字验证码的准确率大概80%,效果还不错,完全能满足使用,如果每张图片的样本继续加大应该能取得更高的准确率,当然随着样本的加大,训练时间也随之增大,对硬件设备要求也越高,还有就是优化LeNet网络结构,目前这里只使用了三层卷积。

    (一)开发准备

    (1)开发环境

         软件环境:visual Studio2013+Python2.7.12+caffe

         硬件环境:Intel Core i7-4790+GTX1080+RAM32G

    (2)训练图片

      可以用于验证码的中文常用字大概3666个,每个字的训练大于等于50个,所以总共训练样本大概20万,其中80%用于训练集,20%用于测试集。样本收集是一个非常麻烦和耗时的过程,需要手工标注结果,我这里利用手工打码平台收集,最便宜一个验证码要4分钱,可以大概算一下,光为了收集这么多样本就将近花费1万RMB,还有配置一个GTX1080的显卡大概6千RMB,这点成本对一个公司还好,如果是对于个人投入还是不少,所以对于实验室的学生党玩深度学习成本还是蛮高的!

      训练集:26万样本图片

      测试集:13万样本图片

    (二)图片样本处理

       目前验证码种类无极繁多,有数字、字母、中文、图片等等,不过本文主要介绍中文验证码的识别。中文验证码设计干扰的方式主要围绕:

      (1)背景色干扰

      (2)文字倾斜扭曲

      (3)干扰线

      (4)中文拼音并存(百度九宫格)

      (5)叠字

      针对不同类型的验证码需要分别处理,这些处理过程统称图片预处理,目前并没有统一的预处理方式,需要针对不同的验证码做特殊处理,但是大体过程无外乎:灰度化、二值化、去干扰线、分割切图、标准化,这些过程用python实现都非常的简单,这里就不详细介绍了,直接上代码,需要import cv2:

     预处理

     调用预处理方法的代码:

     批量处理图片

     处理前的图片:

    预处理后的图片:

     

    (三)caffe模型配置

       模型配置阶段,需要进行caffe所需数据格式准备、训练集和测试集准备、Lenet网络结构配置等三步

      (1)训练集和测试集准备

        预处理阶段将验证码切割成四个图片后,需要将每个图片进行标准化为32*32像素大小的图片,不然caffe模型无法训练。标准化完成以后就需要把每个字的图片分拆到训练集和测试集中去,这里代码就不贴了,根据个人喜好我设置一个字的训练集占80%,测试集占20%,然后把所有字用一个字典进行映射为数字编号,方便模型给出结果时我们能找到对应的汉字。

      (2)caffe格式数据

        为了生成caffe所需数据格式需要用到convert_imageset项目,在第一篇配置中已经编译好了这个项目,可以直接拿过来用,python调用代码如下:

     调用convert_imageset生成caffe数据格式

         生成成功过后可以分别在训练集和测试集文件夹看到如下两个文件:data.mdb和lock.mdb,都是caffe标准mdb格式的数据

      (3)Lenet网络模型

        目前Lenet模型已经非常成熟,最常用的是Lenet-5(5层),对于层数不需要太多的CNN网络用它完全足够了,当然现在更强大的模型还有:Alexnet、googlenet,VGG,resnet。resnet是今年刚出的,据benchmark的测试,对于人脸识别它可以完爆其他网络,层数更是可以多达200,有兴趣的可以看看:GitHub测评项目。对于Lenet有一个可视化的配置网站:http://ethereon.github.io/netscope/#/editor,这里配置的三层结构如下:

        模型总共包含三个卷积层,两个池化层,模型中最重要的几个设置参数:num_output、kernel_size、stride需要分别配置,模型的好坏除了层数结构的设计外,就看这几个参数是否配置的合理,具体的配置这里不详细讲解,相关讲解文章非常的多,也有很多优秀的论文可以借鉴,模型的结构代码如下:

     View Code

         

    (四)训练模型

       到目前为止,准备工作都做完了,现在就可以利用python import caffe进行模型训练了,模型训练速度快慢主要看你GPU的配置如何,我开始用的GTX650,训练5000轮下来,就得消耗半天时间,实在无法忍受这个速度,就向公司申请买了一个GTX1080,那速度简直没法比,训练5000轮半个小时就能完成。调用模型的代码如下:

        cmd='caffe.exe train -solver=./caffe-master/caffe-master/windows/CaptchaTest/dpsample/solver/lenet_solver.prototxt'#训练语句
        os.system(cmd)
        os.chdir(path)

      模型训练中主要的输出参数有:loss,accuracy,如果你看到loss一直在收敛,每500轮输出一次的准确率也在提高,那么说明你的模型设计没什么问题,不然就得重新设计。训练完成后就能得到如下模型:

      

    (五)使用模型

      模型训练完成后,我们就可以简单的用测试图片进行测试,测试代码如下:

    复制代码
        #调用模型
        deploy='.dpsamplesolverlenet_deploy.prototxt'    #deploy文件
        caffe_model='.dpsampleiterate_iter_5000.caffemodel'   #训练好的 caffemodel
        imgtest='./dpsample/data/val/685_363.png'    #随机找的一张待测图片
    
        net = caffe.Net(deploy, caffe_model, caffe.TEST)
        transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})  #设定图片的shape格式(1,3,32,32)
        transformer.set_transpose('data', (2,0,1))    #改变维度的顺序,由原始图片(28,28,3)变为(3,28,28)
        #transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))    #减去均值,前面训练模型时没有减均值,这儿就不用
        #transformer.set_raw_scale('data', 1)    # 缩放到【0,1】之间    已经在网络里设置scale,这里可以不用
        transformer.set_channel_swap('data', (2,1,0))   #交换通道,将图片由RGB变为BGR
        im=caffe.io.load_image(imgtest)                   #加载图片
        net.blobs['data'].data[...] = transformer.preprocess('data',im)       #执行上面设置的图片预处理操作,并将图片载入到blob中
        out = net.forward()
        prob= net.blobs['prob'].data[0].flatten() #取出最后一层(Softmax)属于某个类别的概率值,并打印
        print prob
        order=prob.argsort()[-1]
        print(order)
    复制代码

      最后输出的order就是模型预测出最有可能文字的序号,再到文字和序号对应的字典中去查看就知道这里的识别对不对了!

    #写在最后# 我是一个忠实的VS用户,所有代码都在VS编辑器实现的,它要能用python需要安装一个PTVS插件,在这里编辑python代码需要非常注意中文编码的处理,否则你会吃大苦头,不过相信我,其他编辑器能搞定的VS也一定没问题,只是你要有足够的耐心,遇到问题的时候多思考多搜搜问题的本质所在。

    原创性声明:

    本人在cnblogs上的ID为marso,博客地址为http://www.cnblogs.com/marso/,所有包含原创声明的博客均为本人原创作品。博客的内容除已注明的引用文献外均为本人独立研究成果。除特殊注明外均采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。

    作品及其衍生品不得未经许可而用于商业用途。个人使用无需许可,但必须在引用部分(代码,基本思想或实现方案等)标示出原作者信息,发布时需附带本声明。(对于GPLv3下发布的作品,引用本人作品不需要许可,也不需要标示出引用部分或附带声明。)

    关于“原创”的说明:文章发布前我会进行初步的相关搜索,如未发现有别人发表过类似内容的作品我才会发表。但是因为可能有遗漏,所以不能保证我的博客内容一定为“首创”,但一定可以保证“原创”。

    欢迎转载,并请注明以下内容:

    转载自博客园marso的Blog, 博客地址为http://%博客URL%,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议 进行许可。其中“%博客URL%”替换为被转载博客的实际URL。
  • 相关阅读:
    mojo 接口示例
    MojoliciousLite: 实时的web框架 概述
    接口返回json
    centos 6.7 perl 版本 This is perl 5, version 22 安装DBI DBD
    centos 6.7 perl 5.22 安装DBD 需要使用老的perl版本
    商业智能改变汽车行业
    商业智能改变汽车行业
    读MBA经历回顾(上)目的决定手段——北漂18年(48)
    perl 升级到5.20版本
    Group Commit of Binary Log
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6202467.html
Copyright © 2011-2022 走看看