验证码识别_智能识别应用中复制验证码和识别验证码啥意思 - CSDN
验证码识别 订阅
验证码可以有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的密码尝试,实际上用验证码是很多网站通行的方式(比如招商银行的网上个人银行,腾讯的QQ社区)。 展开全文
验证码可以有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的密码尝试,实际上用验证码是很多网站通行的方式(比如招商银行的网上个人银行,腾讯的QQ社区)。
信息
中文名
验证码识别
目    的
识别数字图像转化为字符串值
外文名
Verification code identification
领    域
图像处理和计算机视觉
原    因
色彩识别
验证码识别基本介绍
验证码的主要目的是强制人机交互来抵御机器自动化攻击的。大部分的验证码设计者并不得要领,不了解图像处理,机器视觉,模式识别,人工智能的基本概念。利用验证码,可以发财,当然要犯罪:比如招商银行密码只有6位,验证码形同虚设,计算机很快就能破解一个有钱的账户,很多帐户是可以网上交易的。也有设计得比较好的,比如Yahoo,Google,Microsoft等。而国内Tencent的中文验证码虽然难,但算不上好。处理知识人工智能,模式识别,机器视觉,图像处理的基本知识比如我们要从一副图片中,识别出验证码;比如我们要从一副图片中,检测并识别出一张人脸。1.图像采集:验证码呢,就直接通过HTTP抓HTML,然后分析出图片的url,然后下载保存就可以了。如果是人脸检测识别,一般要通过视屏采集设备,采集回来,通过A/D转操作,存为数字图片或者视频。2.预处理:检测是正确的图像格式,转换到合适的格式,压缩,剪切出ROI,去除噪音,灰度化,转换色彩空间这些。3.检测:车牌检测识别系统要先找到车牌的大概位置,人脸检测系统要找出图片中所有的人脸(包括疑似人脸);验证码识别呢,主要是找出文字所在的主要区域。4.前处理:人脸检测和识别,会对人脸在识别前作一些校正,比如面内面外的旋转,扭曲等。我这里的验证码识别,“一般”要做文字的切割。5.训练:通过各种模式识别,机器学习算法,来挑选和训练合适数量的训练集。不是训练的样本越多越好。过学习,泛化能力差的问题可能在这里出现。这一步不是必须的,有些识别算法是不需要训练的。6.识别:输入待识别的处理后的图片,转换成分类器需要的输入格式,然后通过输出的类和置信度,来判断大概可能是哪个字母。识别本质上就是分类。图像处理:一般指针对数字图像的某种数学处理。比如投影,钝化,锐化,细化,边缘检测,二值化,压缩,各种数据变换等等。1.二值化:一般图片都是彩色的,按照逼真程度,可能很多级别。为了降低计算复杂度,方便后续的处理,如果在不损失关键信息的情况下,能将图片处理成黑白两种颜色,那就最好不过了。2.细化:找出图像的骨架,图像线条可能是很宽的,通过细化将宽度将为1,某些地方可能大于1。不同的细化算法,可能有不同的差异,比如是否更靠近线条中间,比如是否保持联通行等。3.边缘检测:主要是理解边缘的概念。边缘实际上是图像中图像像素属性变化剧烈的地方。可能通过一个固定的门限值来判断,也可能是自适应的。门限可能是图像全局的,也可能是局部的。不能说那个就一定好,不过大部分时候,自适应的局部的门限可能要好点。被分析的,可能是颜色,也可能是灰度图像的灰度。机器视觉:利用计算机来模式实现人的视觉。比如物体检测,定位,识别。按照对图像理解的层次的差别,分高阶和低阶的理解。模式识别:对事物或者现象的某种表示方式(数值,文字,我们这里主要想说的是数值),通过一些处理和分析,来描述,归类,理解,解释这些事物,现象及其某种抽象。人工智能:这种概念比较宽,上面这些都属于人工智能这个大的方向。简单点不要过分学院派的理解就是,把人类的很“智能”的东西给模拟出来协助生物的人来处理问题,特别是在计算机里面。经验: 2017年以前这方面的技术难点主要在于验证码图片的分割方面,对于识别的匹配,OCR技术已经很成熟了,完全可用于验证码图片的识别,但是复杂的验证码图片大多粘连,分割处理比较麻烦,随着深度学习的发展逐渐成熟,卷积神经网络开始被应用于解决OCR识别的问题,验证码识别正式步入基于端到端的不分割时代。
收起全文
  • 以此探究图片识别的过程以及如何避免生成容易被识别验证码。 理论 图片识别的过程 取样本 清洗区分样本 提取样本特征 提取目标的特征与样本进行对比 操作过程 Java有丰富的图片处理类...

    许多网站在进行某些操作前会要求输入验证码以此来抵御爬虫和攻击。此篇主要讲述如何通过代码来识别一些常见的验证码。以此探究图片识别的过程以及如何避免生成容易被识别的验证码。

    理论

    图片识别的过程

    1. 取样本

    2. 清洗区分样本

    3. 提取样本特征

    4. 提取目标的特征与样本进行对比

    操作过程

    Java有丰富的图片处理类,本次操作使用java语言。
    一、取目标网站的验证码样本。在web页面中查看验证码请求的地址。通过http请求批量获取验证码并保存在本地。
    在这里插入图片描述
    二、区分样本。对每张验证码图片进行人工识别区分,重命名为该图片的验证码。
    在这里插入图片描述
    三、清洗切割样本,提取样本特征。图片识别需要尽可能细地区分出特征点。我们观察上图的验证码图片可以发现多个信息:
    ● 验证码的背景存在着许多干扰线。

    ● 每个数字分明,所占的位置几乎是均等的。

    ● 验证码的数字颜色比较深,干扰因素颜色较浅。

    我们可以尝试通过颜色的深浅去除干扰因素。先通过灰度处理,将验证码中颜色较浅的点置换成白色,颜色较深的点置换成黑色。
    在这里插入图片描述
    通过改变灰度阈值grayValue不断尝试去除干扰点。最后得到干净的验证码。
    在这里插入图片描述
    接下来通过识别图片中的黑色点,使用下面的trainData()方法。

    沿着黑色点进行矩形切割,得到单个数字的特征样本。
    在这里插入图片描述
    在这里插入图片描述

    得到的验证码特征样本训练集合如下:
    在这里插入图片描述
    四、提取目标验证码的特征,与训练集合做对比,识别目标验证码图片

    通过上面的三步,我们已经得到了一组样本特征,接下来只需要把将目标验证码同样执行上面的3步。把提取出来的目标验证码特征与样本特征作对比。如果双方绝大部分像素点的颜色相同,则可认为目标验证码与样本内容一致。取样本的文件名,即可等到目标验证的内容了。以下为对比识别的代码。
    在这里插入图片描述

    总结

    通过上面的四部操作,我们已经能够识别出一些网站的验证码了。上面使用的方法是通过颜色的深浅,去除干扰素,再提取样本特征进行对比。面对其他的一些验证码需要我们通过观察掌握图片的规律,灵活地使用其他的算法来识别去除干扰素,提取出样本特征。

    同样地,在生成验证码的过程中,我们需要避免生成易于去除的干扰素。各个验证码之间在不影响人工识别的情况下尽可能粘连起来,避免被切割分类。

    在这里插入图片描述
    文章来自公众号:睿江云计算

    睿江云官网链接:https://www.eflycloud.com/home?from=RJ0024

    展开全文
  • 对CSDN资源上传验证码识别率100%, 对久游网登陆90% 关于这个程序的说明和部分原理在如下链接: http://blog.csdn.net/stevenkylelee/article/details/8270069
  • 数学原理推导与案例实战紧密结合,由机器学习经典算法过度到深度学习的世界,结合深度学习两大主流框架Caffe与Tensorflow,选择经典项目实战人脸检测与验证码识别。原理推导,形象解读,案例实战缺一不可!具体课程...
  • 效果 先来看下成品是什么样子吧,成品的话,用随机生成的5W张验证码做训练,训练个40多个epoch,用随机生成的2W张做验证码做验证准确率在98%的样子...要识别验证码,当然首先就是要弄到验证码数据啦~~,验证码数据...

    效果

    先来看下成品是什么样子吧,成品的话,用随机生成的5W张验证码做训练,训练个40多个epoch,用随机生成的2W张做验证码做验证准确率在98%的样子。带简陋的UI的话是这么个样子:
    这里写图片描述

    这里写图片描述

    想要完整代码的话可以进入传送门:https://github.com/aolingwen/fuck_verifycode

    生成验证码

    要识别验证码,当然首先就是要弄到验证码数据啦~~,验证码数据的话可以自己写爬虫去抓,但是抓下来之后还要自己去给验证码打label,烦的一批。不想这么麻烦的话可以去找找有没有现成的已经label好了的验证码数据,或者自己生成label好的验证码数据。在这里呢,我选择自己生成。所以下面就是验证码生成的代码。简单的一批。就是用ImageCaptcha来随机生成。

    #生成验证码图片,gen_dir是验证码要落地的目录,total_size是总共要生成多少个验证码,chars_set是验证码的字符集,chars_num是一个验证码中有多少个字符
    def gen_verifycode_img(gen_dir, total_size, chars_set, chars_num, img_height, img_width, font_sizes):
        if not os.path.exists(gen_dir):
            os.makedirs(gen_dir)
        image = ImageCaptcha(width=img_width, height=img_height, font_sizes=font_sizes)
        for i in range(total_size):
            label = ''.join(random.sample(chars_set, chars_num))
            image.write(label, os.path.join(gen_dir, label+'_num'+str(i)+'.png'))

    生成好的验证码呢,大概是这个样子,文件名的前5个字符就是验证码的label:
    这里写图片描述

    现在有了验证码之后呢,接下来就要考虑怎么把数据喂给tensorflow了,由于数据比较大5W个图,所以我用的tfrecord的IO方式,下一篇就写写tfrecode怎么玩的。

    展开全文
  • 验证码识别

    2018-01-24 14:08:48
    验证码识别是3年前的一个小愿望了(当时是做一个自动回帖器,抽奖iphone),但自己这两年主要在做分布式架构,今年终于抽出了空,又战胜了对数学的恐惧,在coursera上学习了吴恩达的机器学习和深度学习,验证码识别...

    验证码识别是3年前的一个小愿望了(当时是做一个自动回帖器,抽奖iphone),但自己这两年主要在做分布式架构,今年终于抽出了空,又战胜了对数学的恐惧,在coursera上学习了吴恩达的机器学习和深度学习,验证码识别也算是对部分课程的实践,下面就来整理一下这次识别的过程。

    1. 验证码识别主流程

    1. 目标检测,检测出字符边距,主要是获得weight,并输出坐标
    2. 图片黑白处理
    3. cnn识别算法
    Created with Raphaël 2.1.2开始目标检测图片黑白处理cnn识别字符结束

    2. 识别细节

    2.1 目标检测,检测出验证码图片中的字符边距

    这个部分使用了yolov2算法,下面介绍一下yolov2算法:
    A. 理论:yolov2算法整体来说其实是把图片分成一个一个小格子,然后每个格子会有一个输出

    2.1.1 labelImg使用

    http://blog.csdn.net/dcrmg/article/details/78496002
    首先,采用上述博客的方法对验证码进行手工的打标签,把验证码的目标边框转换为darknet使用的格式, 接下来,如果需要使用gpu,那么按照

    2.1.2 darknet使用教程

    darknet的使用主要有2个部分要注意,
    第一块是:gpu训练darknet
    如果使用gpu来训练darknet(比如我就是去百度租了5块1个小时的gpu进行训练,效率真的提高了很多),那么需要注意一些安装和配置:
    1. 百度的gpu机器需要安装cudnn
    a. 首先下载 https://developer.nvidia.com/rdp/cudnn-download , 请注意一定要下载cudnn-8.0-linux-x64-v5.1.tgz,别的版本可能会有问题
    b. 安装cudnn

    $ cd ~
    $ sudo tar xvf cudnn-8.0-linux-x64-v5.1.tgz
    $ cd cuda/include
    $ sudo cp *.h /usr/local/include/
    $ cd ../lib64
    $ sudo cp lib* /usr/local/lib/
    $ cd /usr/local/lib# sudo chmod +r libcudnn.so.5.1.5
    $ sudo ln -sf libcudnn.so.5.1.5 libcudnn.so.5
    $ sudo ln -sf libcudnn.so.5 libcudnn.so
    $ sudo ldconfig
    1. 编译darknet:
      由于要使用gpu的方式,所以我们需要修改一些配置文件后进行编译:
      a. 修改makefile
    GPU=1
    CUDNN=1

    b. 修改cuda的路径

    ifeq ($(GPU), 1)
    COMMON+= -DGPU -I/usr/local/cuda-8.0/include/
    CFLAGS+= -DGPU
    LDFLAGS+= -L/usr/local/cuda-8.0/lib64 -lcuda -lcudart -lcublas -lcurand
    #########################
    NVCC=/usr/local/cuda-8.0/bin/nvcc

    c. make即可, 这就会产生gpu训练版本的darknet源码了,现在只需要参考:http://blog.csdn.net/dcrmg/article/details/78496002 进行运行即可。

    d. 接下来就训练吧,训练产生的参数都会保存到一个文件backup下面的yolo-voc.backup, 这个文件可要好好的保存哦,可以说weight在手,一切都飞不走,我在百度的机器上跑一天,基本测试集最后能达到100%的iou,和90%的覆盖比,基本够用啦。

    ./darknet detector train cfg/voc.data cfg/yolo-voc.2.0.cfg cfg/yolo-voc.weight

    f. 上面的训练结束之后(以测试集能达到100%的iou,90%的覆盖比为准),我们又需要改造一下代码,让darknet能够输出中心位置的坐标,而不仅仅是在图片上显示出来。打开darknet的代码: src/image.c, 在如下函数新增一句话:

    void draw_detections(image im, int num, float thresh, box *boxes, float **probs, float **masks, char **names, image **alphabet, int classes)
    {
        int i,j;
    
        for(i = 0; i < num; ++i){
            char labelstr[4096] = {0};
            int class = -1;
            for(j = 0; j < classes; ++j){
                if (probs[i][j] > thresh){
                    if (class < 0) {
                        strcat(labelstr, names[j]);
                        class = j;
                    } else {
                        strcat(labelstr, ", ");
                        strcat(labelstr, names[j]);
                    }
                }
            }
            if(class >= 0){
                int width = im.h * .006;
    
                /*
                   if(0){
                   width = pow(prob, 1./2.)*10+1;
                   alphabet = 0;
                   }
                 */
    
                //printf("%d %s: %.0f%%\n", i, names[class], prob*100);
                int offset = class*123457 % classes;
                float red = get_color(2,offset,classes);
                float green = get_color(1,offset,classes);
                float blue = get_color(0,offset,classes);
                float rgb[3];
    
                //width = prob*20+2;
    
                rgb[0] = red;
                rgb[1] = green;
                rgb[2] = blue;
                box b = boxes[i];
    
                int left  = (b.x-b.w/2.)*im.w;
                int right = (b.x+b.w/2.)*im.w;
                int top   = (b.y-b.h/2.)*im.h;
                int bot   = (b.y+b.h/2.)*im.h;
    
                if(left < 0) left = 0;
                if(right > im.w-1) right = im.w-1;
                if(top < 0) top = 0;
                if(bot > im.h-1) bot = im.h-1;
    
                draw_box_width(im, left, top, right, bot, width, red, green, blue);
            //------------------新增这句话--------------------------------
                printf("rect:%d, %d, %d, %d\n", left, top, right, bot);
            //----------------------------------------------------------
            if (alphabet) {
                    image label = get_label(alphabet, labelstr, (im.h*.03)/10);
                    draw_label(im, top + width, left, label, rgb);
                    free_image(label);
                }
                if (masks){
                    image mask = float_to_image(14, 14, 1, masks[i]);
                    image resized_mask = resize_image(mask, b.w*im.w, b.h*im.h);
                    image tmask = threshold_image(resized_mask, .5);
                    embed_image(tmask, im, left, top);
                    free_image(mask);
                    free_image(resized_mask);
                    free_image(tmask);
                }
            }
        }
    }

    g. 重新make,得到darknet
    h. 进行预测:

    ./darknet detector test cfg/voc.data cfg/yolo-voc.2.0.cfg backup/yolo-voc.backup a.png|grep "rect"
    # 注意rect打印出来的结果不一定是从左到右,所以我们需要进行排序,让识别的部分能从左到右识别
    echo "${result//rect:/}"|sort -n -t "," -k 1 >"${destPath}"/tmp

    image.png

    image.png
    image.png

    好的,已经打印出我们的字符的坐标了。第一步顺利完成。

    2.2 图片黑白处理

    当图片的边框已经识别出来了,我们就需要根据给出的坐标将其切割,并二值化为黑白图片。
    可以使用如下的python代码进行切割:

    # -*-coding:utf-8-*-
    from PIL import Image
    import sys
    # x1(左上角坐标x), y1(左上角坐标y), x2(右下角坐标x), y2(右下角坐标y), picName(文件名), picPath(文件路径), codeName(单字符名字), destPath(目标路径)
    x1 = sys.argv[1]
    y1 = sys.argv[2]
    x2 = sys.argv[3]
    y2 = sys.argv[4]
    picName = sys.argv[5]
    picPath = sys.argv[6]
    codeName = sys.argv[7]
    destPath = sys.argv[8]
    
    im = Image.open(picPath)
    
    region = im.crop((float(x1), float(y1), float(x2), float(y2)))
    cropPath= destPath + "/" + codeName + "_" + picName +"_ori.png"
    bwPath= destPath+ "/" + codeName + "_" + picName +".png"
    region.save(destPath + "/" + codeName + "_" + picName +"_ori.png")

    可以用如下代码进行二值化为黑白图片:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    """Binarize (make it black and white) an image with Python."""
    
    from PIL import Image
    from scipy.misc import imsave
    import numpy
    
    
    def binarize_image(img_path, target_path, threshold):
        """Binarize an image."""
        image_file = Image.open(img_path)
        image = image_file.convert('L')  # convert image to monochrome
        image = numpy.array(image)
        image = binarize_array(image, threshold)
        imsave(target_path, image)
    
    
    def binarize_array(numpy_array, threshold=254):
        """Binarize a numpy array."""
        for i in range(len(numpy_array)):
            for j in range(len(numpy_array[0])):
    #       print(numpy_array[i][j])
                if numpy_array[i][j] > threshold:
                    numpy_array[i][j] = 255
                else:
                    numpy_array[i][j] = 0
        return numpy_array
    
    
    def get_parser():
        """Get parser object for script xy.py."""
        from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
        parser = ArgumentParser(description=__doc__,
                                formatter_class=ArgumentDefaultsHelpFormatter)
        parser.add_argument("-i", "--input",
                            dest="input",
                            help="read this file",
                            metavar="FILE",
                            required=True)
        parser.add_argument("-o", "--output",
                            dest="output",
                            help="write binarized file hre",
                            metavar="FILE",
                            required=True)
        parser.add_argument("--threshold",
                            dest="threshold",
                            default=200,
                            type=int,
                            help="Threshold when to show white")
        return parser
    
    
    if __name__ == "__main__":
        args = get_parser().parse_args()
        binarize_image(args.input, args.output, args.threshold)

    调用方式:

    # cropPath:源文件
    # bwPath: 目标文件
    python ./convertblack.py -i "$cropPath" -o "$bwPath" --threshold 254

    至此,我们的切割与黑白化就完成了。

    2.3 cnn识别算法

    这个部分我主要参考了tensorflow识别mnist的代码,对其进行了改造,我的识别图片resize到24*24,一共有62个类别(0-9, a-z, A-Z), 主要有如下2个文件:一个是huobi.py,主要是识别的主体部分:

    # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    # ==============================================================================
    
    """Functions for downloading and reading MNIST data."""
    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import gzip
    import os
    import tempfile
    import numpy
    from six.moves import urllib
    from six.moves import xrange  # pylint: disable=redefined-builtin
    import tensorflow as tf
    #from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
    import tensorflow as tf
    import read_huobi
    
    reSizePic=24
    #0-9,a-z,A-Z, 62
    classNum=62
    originalPicSize=reSizePic*reSizePic
    
    # read to mnist
    #mnist = read_data_sets('/Users/zxx/PycharmProjects/neural/mnist/date/', one_hot=True)
    mnist = read_huobi.load_huobi("/Users/zxx/PycharmProjects/neural/VerifyCodeDetection/darknet/darknet/results/")
    x = tf.placeholder("float", shape=[None, originalPicSize], name='input_x')
    y_ = tf.placeholder("float", shape=[None, classNum], name='input_y')
    
    def weight_variable(shape):
      initial = tf.truncated_normal(shape, stddev=0.1)
      return tf.Variable(initial)
    
    def bias_variable(shape):
      initial = tf.constant(0.1, shape=shape)
      return tf.Variable(initial)
    
    def conv2d(x, W):
      return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    
    def max_pool_2x2(x):
      return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                            strides=[1, 2, 2, 1], padding='SAME')
    # 1 layer: 5*5*1(input 1), 32 filters 
    W_conv1 = weight_variable([5, 5, 1, 32])
    b_conv1 = bias_variable([32])
    x_image = tf.reshape(x, [-1,reSizePic,reSizePic,1])
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)
    # pool1 output 12
    
    #2 layer: 5*5*32(layer 1 output 32), 64 filters
    W_conv2 = weight_variable([5, 5, 32, 64])
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
    h_pool2 = max_pool_2x2(h_conv2)
    # pool2 output 6,
    
    # conection 1, the 6 is related to input size
    W_fc1 = weight_variable([(reSizePic/4) * (reSizePic/4) * 64, 1024])
    b_fc1 = bias_variable([1024])
    
    h_pool2_flat = tf.reshape(h_pool2, [-1, (reSizePic/4)*(reSizePic/4)*64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
    
    # drop out
    keep_prob = tf.placeholder("float", name='keep_prob')
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
    
    # output layer
    W_fc2 = weight_variable([1024, classNum])
    # 0-9, a-z, a-Z=10+26+26=62
    b_fc2 = bias_variable([classNum])
    y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
    
    # loss
    cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
    
    # backproporation
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
    correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    
    graph_location = tempfile.mkdtemp() # temp file
    print('Saving graph to: %s' % graph_location)
    train_writer = tf.summary.FileWriter(graph_location)
    train_writer.add_graph(tf.get_default_graph())
    saver=tf.train.Saver(tf.global_variables())
    tf.add_to_collection('pred_network', y_conv)
    tf.add_to_collection('accuracy_network', accuracy)
    with tf.Session() as sess:
      sess.run(tf.initialize_all_variables())
      for i in range(1000):
        batch = mnist.train.next_batch(1448)
        if i%100 == 0:
          save_path ='./tf_model/model_'+'%d'%i
          print('%s' % save_path)
          saver.save(sess, save_path)
          train_accuracy = accuracy.eval(feed_dict={
              x:batch[0], y_: batch[1], keep_prob: 1.0})
          print("step %d, training accuracy %g"%(i, train_accuracy))
        train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
    
      print("test accuracy %g"%accuracy.eval(feed_dict={
          x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

    另一个是read_huobi.py,主要用于图片的处理和读取:

    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import gzip
    
    import numpy as np
    from six.moves import xrange  # pylint: disable=redefined-builtin
    import numpy
    from tensorflow.contrib.learn.python.learn.datasets import base
    from tensorflow.python.framework import dtypes
    from tensorflow.python.framework import random_seed
    import shutil
    import os
    import random
    from PIL import Image
    
    class DataSet(object):
    
      def __init__(self,
                   images,
                   labels,
                   fake_data=False,
                   one_hot=False,
                   dtype=dtypes.float32,
                   reshape=True,
                   seed=None):
        """Construct a DataSet.
        one_hot arg is used only if fake_data is true.  `dtype` can be either
        `uint8` to leave the input as `[0, 255]`, or `float32` to rescale into
        `[0, 1]`.  Seed arg provides for convenient deterministic testing.
        """
        seed1, seed2 = random_seed.get_seed(seed)
        # If op level seed is not set, use whatever graph level seed is returned
        numpy.random.seed(seed1 if seed is None else seed2)
        dtype = dtypes.as_dtype(dtype).base_dtype
        if dtype not in (dtypes.uint8, dtypes.float32):
          raise TypeError('Invalid image dtype %r, expected uint8 or float32' %
                          dtype)
        if fake_data:
          self._num_examples = 10000
          self.one_hot = one_hot
        else:
          assert images.shape[0] == labels.shape[0], (
              'images.shape: %s labels.shape: %s' % (images.shape, labels.shape))
          self._num_examples = images.shape[0]
    
          # Convert shape from [num examples, rows, columns, depth]
          # to [num examples, rows*columns] (assuming depth == 1)
          if reshape:
            assert images.shape[3] == 1
            images = images.reshape(images.shape[0],
                                    images.shape[1] * images.shape[2])
          if dtype == dtypes.float32:
            # Convert from [0, 255] -> [0.0, 1.0].
            images = images.astype(numpy.float32)
            images = numpy.multiply(images, 1.0 / 255.0)
        self._images = images
        self._labels = labels
        self._epochs_completed = 0
        self._index_in_epoch = 0
    
      @property
      def images(self):
        return self._images
    
      @property
      def labels(self):
        return self._labels
    
      @property
      def num_examples(self):
        return self._num_examples
    
      @property
      def epochs_completed(self):
        return self._epochs_completed
    
      def next_batch(self, batch_size, fake_data=False, shuffle=True):
        """Return the next `batch_size` examples from this data set."""
        if fake_data:
          fake_image = [1] * 529
          if self.one_hot:
            fake_label = [1] + [0] * 62
          else:
            fake_label = 0
          return [fake_image for _ in xrange(batch_size)], [
              fake_label for _ in xrange(batch_size)
          ]
        start = self._index_in_epoch
        # Shuffle for the first epoch
        if self._epochs_completed == 0 and start == 0 and shuffle:
          perm0 = numpy.arange(self._num_examples)
          numpy.random.shuffle(perm0)
          self._images = self.images[perm0]
          self._labels = self.labels[perm0]
        # Go to the next epoch
        if start + batch_size > self._num_examples:
          # Finished epoch
          self._epochs_completed += 1
          # Get the rest examples in this epoch
          rest_num_examples = self._num_examples - start
          images_rest_part = self._images[start:self._num_examples]
          labels_rest_part = self._labels[start:self._num_examples]
          # Shuffle the data
          if shuffle:
            perm = numpy.arange(self._num_examples)
            numpy.random.shuffle(perm)
            self._images = self.images[perm]
            self._labels = self.labels[perm]
          # Start next epoch
          start = 0
          self._index_in_epoch = batch_size - rest_num_examples
          end = self._index_in_epoch
          images_new_part = self._images[start:end]
          labels_new_part = self._labels[start:end]
          return numpy.concatenate((images_rest_part, images_new_part), axis=0) , numpy.concatenate((labels_rest_part, labels_new_part), axis=0)
        else:
          self._index_in_epoch += batch_size
          end = self._index_in_epoch
          return self._images[start:end], self._labels[start:end]
    
    
    def dense_to_one_hot(labels_dense, num_classes):
      """Convert class labels from scalars to one-hot vectors."""
      num_labels = labels_dense.shape[0]
    # arange dengchashulie
      index_offset = numpy.arange(num_labels) * num_classes
      labels_one_hot = numpy.zeros((num_labels, num_classes))
      labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
      return labels_one_hot
    
    
    
    def load_predict_huobi(imgDir,dtype=dtypes.float32,
                       reshape=True,
                       seed=None,reSize=24):
        train_images, train_labels = load_img(imgDir, reSize=reSize)
        validation_images, validation_labels = load_img(imgDir, reSize=reSize)
        test_images, test_labels = load_img(imgDir,reSize=reSize)
    
        train = DataSet(train_images, train_labels, dtype=dtype, reshape=reshape, seed=seed)
        validation = DataSet(validation_images, validation_labels, dtype=dtype, reshape=reshape,seed=seed)
        test = DataSet(test_images, test_labels, dtype=dtype, reshape=reshape, seed=seed)
    
        return base.Datasets(train=train, validation=validation, test=test)
    
    
    
    def load_huobi(imgDir,dtype=dtypes.float32,
                       reshape=True,
                       seed=None, reSize=24):
        train_images, train_labels = load_img(imgDir + "/trainImg/", reSize=reSize)
        validation_images, validation_labels = load_img(imgDir + "/validationImg/", reSize=reSize)
        test_images, test_labels = load_img(imgDir + "/testImg/", reSize=reSize)
    
        train = DataSet(train_images, train_labels, dtype=dtype, reshape=reshape, seed=seed)
        validation = DataSet(validation_images, validation_labels, dtype=dtype, reshape=reshape,seed=seed)
        test = DataSet(test_images, test_labels, dtype=dtype, reshape=reshape, seed=seed)
    
        return base.Datasets(train=train, validation=validation, test=test)
    
    
    def convert_label_to_int_index(label):
         # 0-9 1-10
         # a-z 11-36
         # A-Z 37-62
         inta = ord('a')
         intz = ord('z')
         intA = ord('A')
         intZ = ord('Z')
         int0 = ord('0')
         intLabel = ord(label)
         if intLabel>=inta and intLabel<=intz:
        return intLabel - inta + 10
         elif intLabel>=intA and intLabel<=intZ:
            return intLabel - intA + 36
         else:
            return intLabel - int0
    
    def convert_int_index_to_label(int_index):
         # 0-9 0-9
         # a-z 10-35
         # A-Z 36-61
         inta = ord('a')
         intz = ord('z')
         intA = ord('A')
         intZ = ord('Z')
         int0 = ord('0')
         intLabel = int_index
    
         if int_index>=0 and int_index<=9:
            label = chr(int_index + int0)
         elif int_index>=10 and int_index<=35:
            label = chr(int_index - 10 + inta)
         else:
            label = chr(int_index - 36 + intA)
         return label
    
    
    def load_img(imgDir, reSize=24):
         imgs = os.listdir(imgDir)
         imgNum = len(imgs)
         data = np.empty((imgNum,reSize,reSize,1),dtype="float32")
         label = np.empty((imgNum,),dtype="uint8")
         for i in range (imgNum):
             im = Image.open(imgDir+"/"+imgs[i]).convert('L')
         img = im.resize((reSize, reSize),Image.ANTIALIAS)
             arr = np.asarray(img,dtype="float32")
             data[i,:,:,:] = arr.reshape(reSize,reSize,1)
             label[i] = convert_label_to_int_index(imgs[i].split('_')[0])
         print(label[i])
         labels_one_hot = dense_to_one_hot(label, 62)
         print("data.shape=" + str(data.shape))
         print("label.shape=" + str(labels_one_hot.shape))
         return data,labels_one_hot
    
    
    def random_split_img(srcDir, validation_size=100, test_size=10):
         imgs = os.listdir(srcDir)
         random.shuffle(imgs)
         imgNum = len(imgs)
         test_images = imgs[:validation_size]
         validation_images = imgs[validation_size:validation_size+test_size]
         train_images = imgs[validation_size+test_size:]
         if os.path.exists(srcDir + "/trainImg/"):
            shutil.rmtree(srcDir + "/trainImg/")
         if os.path.exists(srcDir + "/testImg/"):
            shutil.rmtree(srcDir + "/testImg/")
         if os.path.exists(srcDir + "/validationImg/"):
            shutil.rmtree(srcDir + "/validationImg/")
    
         os.mkdir(srcDir + "/trainImg/")
         os.mkdir(srcDir + "/testImg/")
         os.mkdir(srcDir + "/validationImg/")
    
         for i in range (imgNum):
        if not os.path.isdir(srcDir + imgs[i]):
            if i < validation_size :
                    moveFileto(srcDir + imgs[i],  srcDir + "/validationImg/" + imgs[i])
            elif i < (validation_size + test_size) :
                    moveFileto(srcDir + imgs[i],  srcDir + "/testImg/" + imgs[i])
            else :
                    moveFileto(srcDir + imgs[i],  srcDir + "/trainImg/" + imgs[i])
    
    
    def moveFileto(sourceDir,  targetDir): 
         shutil.copy(sourceDir,  targetDir)

    验证cnn识别算法识别率的load_huobi.py

    import tensorflow as tf  
    import numpy as np 
    import read_huobi
    import sys
    filePath=sys.argv[1]
    destFileName=sys.argv[2]
    reSize=sys.argv[3]
    with tf.Session() as sess:
          new_saver = tf.train.import_meta_graph("tf_model/model_900.meta")
          new_saver.restore(sess, "tf_model/model_900")
    
          y = tf.get_collection('pred_network')[0]
          accurancy = tf.get_collection('accurancy_network')
    
    
          graph = tf.get_default_graph()
          x = graph.get_operation_by_name('input_x').outputs[0]
          y_ = graph.get_operation_by_name('input_y').outputs[0]
          keep_prob = graph.get_operation_by_name('keep_prob').outputs[0]
          mnist = read_huobi.load_predict_huobi(filePath, reSize)  
          batch = mnist.train.next_batch(mnist.train.num_examples)
          y_pre = sess.run(y, feed_dict={x:batch[0],  keep_prob:1.0})
          right=0
          error=0
          resultLabel = np.ones((1,mnist.train.num_examples))
          resultLabel = resultLabel.astype(np.str)
          for i in range(mnist.train.num_examples):
            y_pre_list = y_pre[i].tolist()
            y_batch_list = batch[1][i].tolist()
            predict_y=str(read_huobi.convert_int_index_to_label(y_pre_list.index(max(y_pre_list))))
            real_y=str(read_huobi.convert_int_index_to_label(y_batch_list.index(max(y_batch_list))))
            resultLabel[0][int(real_y)] = predict_y
    
          resultStr="" 
          for i in range(mnist.train.num_examples):
            resultStr+=resultLabel[0][i]
    
          fo = open(filePath+"/"+destFileName+".txt", "wb")
          fo.write(resultStr);
          fo.close()
    

    4. 训练结束,识别验证码

    这里主要涉及到3个文件,一个是总调用流程predict.sh :

    picSrc="/Users/baidu/PycharmProjects/neural/mnist/srcImg/"
    splitDest="/Users/baidu/PycharmProjects/neural/mnist/results/"
    rm -rf "${splitDest}"
    
    
    # splitpic
    cd "/Users/baidu/PycharmProjects/neural/VerifyCodeDetection/darknet/darknet"
    sh splitImg.sh "${picSrc}" "${splitDest}" 
    
    #predict
    cd /Users/baidu/PycharmProjects/neural/mnist/
    allPicDirName=`ls "${splitDest}"`
    
    for picDirName in $allPicDirName
    do
    
        result=`python predict_huobi.py "${splitDest}/$picDirName" "$picDirName"`
        echo "result:$result"
    done

    从上面的代码可以看到,还涉及到2个脚本,一个是splitImg.sh,用于调用darknet分割图片中的每一个字符:

    function splitPic()
    {
    picName=$1
    filePath=$2
    destPath=$3
    
    result=`./darknet detector test cfg/voc.data cfg/yolo-voc.2.0.cfg backup/yolo-voc.backup "${filePath}"|grep "rect"`
    echo "${result//rect:/}"|sort -n -t "," -k 1 >"${destPath}"/tmp
    cat ${destPath}/tmp
    pic=0
    
    while read line
    do
        x1=`echo $line|awk -F ', ' '{print $1}'`
        y1=`echo $line|awk -F ', ' '{print $2}'`
        x2=`echo $line|awk -F ', ' '{print $3}'`
        y2=`echo $line|awk -F ', ' '{print $4}'`
        #train
            #codeName="${picName:$pic:1}"
            #predict
        codeName="${pic}"
    
        python ./screen.py "$x1" "$y1" "$x2" "$y2" "$picName" "$filePath"  "$codeName" "$destPath"
        cropPath="${destPath}/${codeName}_${picName}_ori.png"
        bwPath="${destPath}/${codeName}_${picName}.png"
        python ./convertblack.py -i "$cropPath" -o "$bwPath" --threshold 254
        rm "$cropPath"
        pic=$((pic+1))
    done < "${destPath}/tmp"
    rm "${destPath}/tmp"
    echo "Done"
    }
    
    destPath="./results/"
    srcPath="/Users/baidu/PycharmProjects/neural/VerifyCodeDetection/darknet/darknet/validateImage/"
    if [ "$1" != "" ];then
    
          srcPath="$1" 
    fi
    
    
    if [ "$2" != "" ];then
          destPath="$2"    
    fi
    
    allPicName=`ls "${srcPath}"`
    
    for picName in $allPicName
    do
    picName=`echo $picName |awk -F '.png' '{print $1}'`
    destPath="${destPath}/${picName}/"
    mkdir -p "$destPath"   
    #filePath="/Users/baidu/PycharmProjects/neural/VerifyCodeDetection/darknet/darknet/validateImage/${picName}.png"
    filePath="${srcPath}/${picName}.png"
    splitPic "$picName" "$filePath" "$destPath";
    echo $picName
    done
    
    #usage:
    #sh splitImg.sh "/Users/zxx/PycharmProjects/neural/mnist/srcImg/" "/Users/zxx/PycharmProjects/neural/mnist/results/"

    第三个脚本是真正的识别脚本: predict_huobi.py

    import tensorflow as tf  
    import numpy as np 
    import read_huobi
    import sys
    filePath=sys.argv[1]
    destFileName=sys.argv[2]
    reSize=sys.argv[3]
    with tf.Session() as sess:
          new_saver = tf.train.import_meta_graph("tf_model/model_900.meta")
          new_saver.restore(sess, "tf_model/model_900")
    
          y = tf.get_collection('pred_network')[0]
          accurancy = tf.get_collection('accurancy_network')
    
    
          graph = tf.get_default_graph()
          x = graph.get_operation_by_name('input_x').outputs[0]
          y_ = graph.get_operation_by_name('input_y').outputs[0]
          keep_prob = graph.get_operation_by_name('keep_prob').outputs[0]
          mnist = read_huobi.load_predict_huobi(filePath, reSize)  
          batch = mnist.train.next_batch(mnist.train.num_examples)
          y_pre = sess.run(y, feed_dict={x:batch[0],  keep_prob:1.0})
          right=0
          error=0
          resultLabel = np.ones((1,mnist.train.num_examples))
          resultLabel = resultLabel.astype(np.str)
          for i in range(mnist.train.num_examples):
            y_pre_list = y_pre[i].tolist()
            y_batch_list = batch[1][i].tolist()
            predict_y=str(read_huobi.convert_int_index_to_label(y_pre_list.index(max(y_pre_list))))
            real_y=str(read_huobi.convert_int_index_to_label(y_batch_list.index(max(y_batch_list))))
            resultLabel[0][int(real_y)] = predict_y
    
          resultStr="" 
          for i in range(mnist.train.num_examples):
            resultStr+=resultLabel[0][i]
    
          fo = open(filePath+"/"+destFileName+".txt", "wb")
          fo.write(resultStr);
          fo.close()
    展开全文
  • 利用captcha随机生成四位0-9数字的验证码图片.总共生成10000张,因为随机生成过程会有重复最后只有6370张,其中5870张作为训练集,500张作为测试集. 把生成好的图片转换成tfrecord的格式保存. 这个项目是把四个数字作为...

    整体流程:

    1. 利用captcha随机生成四位0-9数字的验证码图片.总共生成10000张,因为随机生成过程会有重复最后只有6370张,其中5870张作为训练集,500张作为测试集.
    2. 把生成好的图片转换成tfrecord的格式保存.
    3. 这个项目是把四个数字作为四个预测去检测,利用slim,修改Alexnet网络结构在后面接四个分类输出.在上一步中生成tfrecord的时候也是把4个label转换.
    4. 读入tfrecord,进行训练.
    5. 测试

    验证码生成.py

    from captcha.image import ImageCaptcha
    import numpy as np
    from PIL import Image
    import sys
    import random
    
    number = ['0','1','2','3','4','5','6','7','8','9']
    
    
    #获取四个随机字符
    #def random_captcha_text(char_set=number,captcha_size=4):
    def random_captcha_text(char_set=number,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)
        #生成验证码
        image.write(captcha_text,'./image/' + captcha_text + '.png')  # write it 
        
    num=10000
    if __name__=='__main__':
        for i in range(num):
            gen_captcha_text_and_image()
            sys.stdout.write('\r>>creating images %d/%d'%(i+1,num))
            sys.stdout.flush()
        sys.stdout.write('\n')
        sys.stdout.flush()
        print('生成完毕')
        
    
    

    在这里插入图片描述
    生成的验证码图片如下:
    在这里插入图片描述
    生成tfrecord.py

    import tensorflow as tf
    import numpy as np
    from PIL import Image
    import os
    import random
    import sys
    
    #验证集数量
    _NUM_TEST = 500
    #随机种子
    _RANDOM_SEED = 0
    #数据集路径
    DATASET_DIR = './image/'
    #tfrecord文件存放路径
    TFRECORD_DIR = './image/tfrecord/'
    
    
    #判断tfrecord文件是否存在
    def _dataset_exists(dataset_dir):
        for split_name in ['train', 'test']:
            output_filename = os.path.join(dataset_dir, split_name + 'tfrecords')
            if not tf.gfile.Exists(output_filename):
                return False
        return True
        
    #获取所有验证码图片
    def _get_filenames_and_classes(dataset_dir):
        photo_filenames = []
        for filename in os.listdir(dataset_dir):
            #获取文件路径
            path  = os.path.join(dataset_dir, filename)
            photo_filenames.append(path)
        return photo_filenames
    
    def int64_feature(values):
        if not isinstance(values,(tuple,list)):
            values=[values]
        return tf.train.Feature(int64_list=tf.train.Int64List(value=values))
    
    def bytes_feature(values):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[values]))
    
    def image_to_tfexample(image_data, label0, label1, label2, label3):
        return tf.train.Example(features=tf.train.Features(feature={
            'image':bytes_feature(image_data),
            'label0':int64_feature(label0),
            'label1':int64_feature(label1),
            'label2':int64_feature(label2),
            'label3':int64_feature(label3),
        }))
    
    
    #数据转化为tfrecord格式            
    def _convert_dataset(split_name, filenames, dataset_dir):
        assert split_name in ['train', 'test']
        
        with tf.Session() as sess:
            #定义tfrecord文件的路径和名字
            output_filename = os.path.join(TFRECORD_DIR, split_name + '.tfrecords')
            with tf.python_io.TFRecordWriter(output_filename) as tfrecord_writer:
                for i, filename in enumerate(filenames):
                    try:
                        sys.stdout.write('\r>>转换图片 %d / %d' % (i+1, len(filenames)))
                        sys.stdout.flush()
                        
                        #读取图片
                        image_data = Image.open(filename)
                        #根据模型结构resize
                        image_data = image_data.resize((224, 224))
                        #灰度化
                        image_data = np.array(image_data.convert('L'))
                        #将图片转换为bytes
                        image_data = image_data.tobytes()
                        
                        #获取lables
                        labels = filename.split('/')[-1][0:4]
                        num_labels = []
                        for j in range(4):
                            num_labels.append(int(labels[j]))
                            
                        #生成protocol数据类型
                        example = image_to_tfexample(image_data, num_labels[0],num_labels[1],num_labels[2],num_labels[3])
                        tfrecord_writer.write(example.SerializeToString())
                    
                    except IOError as e:
                        print('\n不能读取:' , filename)
                        print('Error:' , e)
                        print('跳过 \n')
            sys.stdout.write('\n') #和print是一个意思
            sys.stdout.flush() # 一秒显示一次结果,一般都是程序执行完才显示结果
                                
    
        
    #判断tfrecord文件是否存在
    if _dataset_exists(DATASET_DIR):
        print('file already exists')
    else:
        #获得所有图片
        photo_filenames= _get_filenames_and_classes(DATASET_DIR)
    
        #把数据分为测试集和训练集,并且打乱
        random.seed(_RANDOM_SEED)
        random.shuffle(photo_filenames)
        training_filenames = photo_filenames[_NUM_TEST:]
        testing_filenames = photo_filenames[:_NUM_TEST]
    
        #数据转换为tfrecord
        _convert_dataset('train',training_filenames,DATASET_DIR)
        _convert_dataset('test',testing_filenames,DATASET_DIR)
        print('-------------生成tfrecord文件结束------------------')
        
    

    在这里插入图片描述
    在这里插入图片描述
    验证码识别.py

    import os
    import tensorflow as tf
    from PIL import Image
    import numpy as np
    from nets  import nets_factory
    
    tf.reset_default_graph()
    #字符数量
    CHAR_NUM=10
    #图片高度和宽度
    IMAGE_HEIGHT=60
    IMAGE_WIDTH=160
    #批次
    BATCH_SIZE=10
    TFRECORD_FILE="./image/tfrecord/train.tfrecords"
    CHECKPOINT_DIR = './ckpt/'
    
    #placeholder
    x=tf.placeholder(tf.float32,[None,224,224])
    y0=tf.placeholder(tf.float32,[None])
    y1=tf.placeholder(tf.float32,[None])
    y2=tf.placeholder(tf.float32,[None])
    y3=tf.placeholder(tf.float32,[None])
    
    lr=tf.Variable(0.0003,dtype=tf.float32)
    
    
    #从tfrecord中读取数据
    def read_and_decode(filename):
        #根据文件名生成队列
        filename_queue = tf.train.string_input_producer([filename])
        reader = tf.TFRecordReader()
        #返回文件名和文件
        _, serialized_example = reader.read(filename_queue)
        features = tf.parse_single_example(serialized_example,features={'image':tf.FixedLenFeature([],tf.string),
                                                                      'label0':tf.FixedLenFeature([],tf.int64),
                                                                      'label1':tf.FixedLenFeature([],tf.int64),
                                                                      'label2':tf.FixedLenFeature([],tf.int64),
                                                                      'label3':tf.FixedLenFeature([],tf.int64)
                                                                     })
        #获取图片数据
        image=tf.decode_raw(features['image'],tf.uint8)
        #tf.train.shuffle_batch必须确定shape
        image=tf.reshape(image,[224,224])
        #图片预处理归一化(-1,1)
        image=tf.cast(image,tf.float32)/255.0
        image=tf.subtract(image,0.5)
        image=tf.multiply(image,2.0)
        #获取labels
        label0=tf.cast(features['label0'],tf.int32)
        label1=tf.cast(features['label1'],tf.int32)
        label2=tf.cast(features['label2'],tf.int32)
        label3=tf.cast(features['label3'],tf.int32)
        return image,label0,label1,label2,label3
    
    #获取图片数据和标签
    image,label0,label1,label2,label3 = read_and_decode(TFRECORD_FILE)
    
    #使用shuffle_batch可以随机的打乱
    image_batch,label_batch0,label_batch1,label_batch2,label_batch3 = tf.train.shuffle_batch(
                                    [image,label0,label1,label2,label3], batch_size=BATCH_SIZE, \
                                            capacity=1075, min_after_dequeue=1000, num_threads=128)
    
    #定义网络结构
    train_network_fn = nets_factory.get_network_fn('alexnet_v2', num_classes=CHAR_NUM, \
                                                 weight_decay=0.0005,is_training=True)
    
    #gpu_options = tf.GPUOptions(allow_growth=True)
    
    #with tf.Session(config=tf.ConfigProto(log_device_placement=False,allow_soft_placement=True,gpu_options=gpu_options)) as sess:
    #     gpu_options = tf.GPUOptions(allow_growth=True)
    #     tf.Session(config=tf.ConfigProto(log_device_placement=False,allow_soft_placement=True,gpu_options=gpu_options))
    
    with tf.Session() as sess:
        
        X = tf.reshape(x,[BATCH_SIZE,224,224,1])
        
        #训练以后得到的输出值
        logits0,logits1,logits2,logits3,end_pintos = train_network_fn(X)
        
        #把标签打成one_hot形式
        one_hot_labels0 = tf.one_hot(indices=tf.cast(y0,tf.int32),depth=CHAR_NUM)
        one_hot_labels1 = tf.one_hot(indices=tf.cast(y1,tf.int32),depth=CHAR_NUM)
        one_hot_labels2 = tf.one_hot(indices=tf.cast(y2,tf.int32),depth=CHAR_NUM)
        one_hot_labels3 = tf.one_hot(indices=tf.cast(y3,tf.int32),depth=CHAR_NUM)
        
        #四部分的loss
        loss0=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits0, labels=one_hot_labels0))
        loss1=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits1, labels=one_hot_labels1))
        loss2=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits2, labels=one_hot_labels2))
        loss3=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits3, labels=one_hot_labels3))
        #总的loss
        total_loss=(loss0+loss1+loss2+loss3)/4.0
        #优化起
        optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(total_loss)
        
        #计算四部分的准确率
        correct_prediction0 = tf.equal(tf.argmax(one_hot_labels0,1), tf.argmax(logits0,1))
        accuracy0 = tf.reduce_mean(tf.cast(correct_prediction0, tf.float32))
        
        correct_prediction1 = tf.equal(tf.argmax(one_hot_labels1,1), tf.argmax(logits1,1))
        accuracy1 = tf.reduce_mean(tf.cast(correct_prediction1, tf.float32))
        
        correct_prediction2 = tf.equal(tf.argmax(one_hot_labels2,1), tf.argmax(logits2,1))
        accuracy2 = tf.reduce_mean(tf.cast(correct_prediction2, tf.float32))
        
        correct_prediction3 = tf.equal(tf.argmax(one_hot_labels3,1), tf.argmax(logits3,1))
        accuracy3 = tf.reduce_mean(tf.cast(correct_prediction3, tf.float32))
        
        #保存模型
        saver = tf.train.Saver()
        sess.run(tf.global_variables_initializer())
        #saver.restore(sess, './ckpt/crack_captcha-10000.ckpt')
        #sess.run(tf.local_variables_initializer())
        #创建一个协调器来管理线程
        coord = tf.train.Coordinator() 
        #启动QueueRunner,此时文件名列队已经进队
        threads = tf.train.start_queue_runners(sess=sess,coord=coord)
        
        for i in range(10001):
            #获取一个批次的数据和标签
            b_image,b_label0,b_label1,b_label2,b_label3 = sess.run([image_batch,label_batch0,label_batch1,label_batch2,label_batch3])
            #优化模型
            sess.run(optimizer,feed_dict={x:b_image, y0:b_label0, y1:b_label1, y2:b_label2, y3:b_label3})
            
            #每100次计算一次loss和准确路
            if i%100 == 0:
                #每10000次降低一次学习率
                if i%5000 == 0:
                    sess.run(tf.assign(lr,lr/3))
                acc0,acc1,acc2,acc3,loss_ = sess.run([accuracy0, accuracy1, accuracy2, accuracy3, total_loss],feed_dict={x:b_image,                                                                                                y0:b_label0,
                                                                                                              y1:b_label1,
                                                                                                              y2:b_label2,
                                                                                                              y3:b_label3})
                learning_rate = sess.run(lr)
                print("Iter: %d , Loss:%.3f , Accuracy:%.3f, %.3f, %.3f, %.3f  Learning_rate:%.7f" % (i,loss_,acc0,acc1,acc2,acc3,learning_rate))
                
                #if acc0 > 0.9 and acc1 > 0.9 and acc2 > 0.9 and acc3 > 0.9 :
                
                if i%5000 == 0:  
                    #saver.save(sess,'./ckpt/crack_captcha.ckpt', global_step=1)
                    saver.save(sess, CHECKPOINT_DIR + 'crack_captcha-' + str(i) + '.ckpt')
                    print('----保存第 %d 次模型----' % i)
                    continue
        #通知其他线程关闭
        coord.request_stop()
        #其他所有线程关闭之后,这一函数才能返回
        coord.join(threads)
    

    在这里插入图片描述
    可以看到到一万次的时候,准确率基本都稳定在100%.

    因为上面用到了slim里面的Alexnet,下面是修改的model/research/slim/alexnet的代码:

    alexnet.py

    # %load alexnet.py
    # Copyright 2016 The TensorFlow Authors. All Rights Reserved.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    # http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    # ==============================================================================
    """Contains a model definition for AlexNet.
    
    This work was first described in:
      ImageNet Classification with Deep Convolutional Neural Networks
      Alex Krizhevsky, Ilya Sutskever and Geoffrey E. Hinton
    
    and later refined in:
      One weird trick for parallelizing convolutional neural networks
      Alex Krizhevsky, 2014
    
    Here we provide the implementation proposed in "One weird trick" and not
    "ImageNet Classification", as per the paper, the LRN layers have been removed.
    
    Usage:
      with slim.arg_scope(alexnet.alexnet_v2_arg_scope()):
        outputs, end_points = alexnet.alexnet_v2(inputs)
    
    @@alexnet_v2
    """
    
    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import tensorflow as tf
    
    slim = tf.contrib.slim
    trunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev)
    
    
    def alexnet_v2_arg_scope(weight_decay=0.0005):
        with slim.arg_scope([slim.conv2d, slim.fully_connected],
                          activation_fn=tf.nn.relu,
                          biases_initializer=tf.constant_initializer(0.1),
                          weights_regularizer=slim.l2_regularizer(weight_decay)):
        with slim.arg_scope([slim.conv2d], padding='SAME'):
            with slim.arg_scope([slim.max_pool2d], padding='VALID') as arg_sc:
                return arg_sc
    
    
    def alexnet_v2(inputs,
                   num_classes=1000,
                   is_training=True,
                   dropout_keep_prob=0.5,
                   spatial_squeeze=True,
                   scope='alexnet_v2',
                   global_pool=False):
      """AlexNet version 2.
    
      Described in: http://arxiv.org/pdf/1404.5997v2.pdf
      Parameters from:
      github.com/akrizhevsky/cuda-convnet2/blob/master/layers/
      layers-imagenet-1gpu.cfg
    
      Note: All the fully_connected layers have been transformed to conv2d layers.
            To use in classification mode, resize input to 224x224 or set
            global_pool=True. To use in fully convolutional mode, set
            spatial_squeeze to false.
            The LRN layers have been removed and change the initializers from
            random_normal_initializer to xavier_initializer.
    
      Args:
        inputs: a tensor of size [batch_size, height, width, channels].
        num_classes: the number of predicted classes. If 0 or None, the logits layer
        is omitted and the input features to the logits layer are returned instead.
        is_training: whether or not the model is being trained.
        dropout_keep_prob: the probability that activations are kept in the dropout
          layers during training.
        spatial_squeeze: whether or not should squeeze the spatial dimensions of the
          logits. Useful to remove unnecessary dimensions for classification.
        scope: Optional scope for the variables.
        global_pool: Optional boolean flag. If True, the input to the classification
          layer is avgpooled to size 1x1, for any input size. (This is not part
          of the original AlexNet.)
    
      Returns:
        net: the output of the logits layer (if num_classes is a non-zero integer),
          or the non-dropped-out input to the logits layer (if num_classes is 0
          or None).
        end_points: a dict of tensors with intermediate activations.
      """
      with tf.variable_scope(scope, 'alexnet_v2', [inputs]) as sc:
        end_points_collection = sc.original_name_scope + '_end_points'
        # Collect outputs for conv2d, fully_connected and max_pool2d.
        with slim.arg_scope([slim.conv2d, slim.fully_connected, slim.max_pool2d],
                            outputs_collections=[end_points_collection]):
            net = slim.conv2d(inputs, 64, [11, 11], 4, padding='VALID',
                            scope='conv1')
            net = slim.max_pool2d(net, [3, 3], 2, scope='pool1')
            net = slim.conv2d(net, 192, [5, 5], scope='conv2')
            net = slim.max_pool2d(net, [3, 3], 2, scope='pool2')
            net = slim.conv2d(net, 384, [3, 3], scope='conv3')
            net = slim.conv2d(net, 384, [3, 3], scope='conv4')
            net = slim.conv2d(net, 256, [3, 3], scope='conv5')
            net = slim.max_pool2d(net, [3, 3], 2, scope='pool5')
    
        # Use conv2d instead of fully_connected layers.
        with slim.arg_scope([slim.conv2d],
                              weights_initializer=trunc_normal(0.005),
                              biases_initializer=tf.constant_initializer(0.1)):
            net = slim.conv2d(net, 4096, [5, 5], padding='VALID',
                              scope='fc6')
            net = slim.dropout(net, dropout_keep_prob, is_training=is_training,
                               scope='dropout6')
            net = slim.conv2d(net, 4096, [1, 1], scope='fc7')
            net = slim.dropout(net, dropout_keep_prob, is_training=is_training,
                               scope='dropout7')
            
            net0 = slim.conv2d(net, num_classes, [1, 1],
                                activation_fn=None,
                                normalizer_fn=None,
                                biases_initializer=tf.zeros_initializer(),
                                scope='fc8_0')
            net1 = slim.conv2d(net, num_classes, [1, 1],
                                activation_fn=None,
                                normalizer_fn=None,
                                biases_initializer=tf.zeros_initializer(),
                                scope='fc8_1')
            net2 = slim.conv2d(net, num_classes, [1, 1],
                                activation_fn=None,
                                normalizer_fn=None,
                                biases_initializer=tf.zeros_initializer(),
                                scope='fc8_2')
            net3 = slim.conv2d(net, num_classes, [1, 1],
                                activation_fn=None,
                                normalizer_fn=None,
                                biases_initializer=tf.zeros_initializer(),
                                scope='fc8_3')
            
            # Convert end_points_collection into a end_point dict.
            end_points = slim.utils.convert_collection_to_dict(end_points_collection)
           
            if spatial_squeeze:
                net0 = tf.squeeze(net0, [1, 2], name='fc8_0/squeezed')
                end_points[sc.name + '/fc8_0'] = net0
                
                net1 = tf.squeeze(net1, [1, 2], name='fc8_1/squeezed')
                end_points[sc.name + '/fc8_1'] = net1
                
                net2 = tf.squeeze(net2, [1, 2], name='fc8_2/squeezed')
                end_points[sc.name + '/fc8_2'] = net2
                
                net3 = tf.squeeze(net3, [1, 2], name='fc8_3/squeezed')
                end_points[sc.name + '/fc8_3'] = net3
                
            return net0,net1, net2, net3, end_points
    alexnet_v2.default_image_size = 224
    
    

    验证码测试.py

    import os
    import tensorflow as tf
    from PIL import Image
    import numpy as np
    from nets  import nets_factory
    import matplotlib.pyplot as plt
    
    #字符数量
    CHAR_NUM=10
    #图片高度
    IMAGE_HEIGHT=60
    IMAGE_WIDTH=160
    BATCH_SIZE=1
    TFRECORD_FILE="./image/tfrecord/test.tfrecords"
    
    #x = tf.placeholder(tf.float32,[None,224,224])
    
    x = tf.placeholder(tf.float32, [None, 224, 224])
    
    def read_and_decode(filename):
        #根据文件名生成队列
        filename_queue=tf.train.string_input_producer([filename])
        reader=tf.TFRecordReader()
        #返回文件名和文件
        _, serialized_example=reader.read(filename_queue)
        features=tf.parse_single_example(serialized_example,features={'image':tf.FixedLenFeature([],tf.string),
                                                                      'label0':tf.FixedLenFeature([],tf.int64),
                                                                      'label1':tf.FixedLenFeature([],tf.int64),
                                                                      'label2':tf.FixedLenFeature([],tf.int64),
                                                                      'label3':tf.FixedLenFeature([],tf.int64)
                                                                     })
        image = tf.decode_raw(features['image'],tf.uint8)
        
        #没有经过预处理的灰度图
        image_raw = tf.reshape(image,[224,224]) #保留原图以便显示使用
        
        image = tf.reshape(image,[224,224])
        image = tf.cast(image,tf.float32)/255.0 #把原图像素值由0-255变为-1 - 1
        image = tf.subtract(image,0.5)
        image = tf.multiply(image,2.0)
        
        label0=tf.cast(features['label0'],tf.int32)
        label1=tf.cast(features['label1'],tf.int32)
        label2=tf.cast(features['label2'],tf.int32)
        label3=tf.cast(features['label3'],tf.int32)
        return image, image_raw, label0, label1, label2, label3
    
    #获取图片数据和标签
    image,image_raw,label0,label1,label2,label3 = read_and_decode(TFRECORD_FILE)
    #print(len(sess.run(image)))
    image_batch,image_raw_batch,label_batch0,label_batch1,label_batch2,label_batch3 = tf.train.shuffle_batch(
                                                    [image,image_raw,label0,label1,label2,label3],\
                                                        batch_size=BATCH_SIZE,\
                                                        capacity=53,min_after_dequeue=50,\
                                                            num_threads=1)
    
    train_network_fn = nets_factory.get_network_fn(
      'alexnet_v2',
      num_classes=CHAR_NUM,
      weight_decay=0.0005,
      is_training=False)
    
    #gpu_options = tf.GPUOptions(allow_growth=True)
    #with tf.Session(config=tf.ConfigProto(log_device_placement=False,allow_soft_placement=True,gpu_options=gpu_options)) as sess:
    with tf.Session() as sess:
        
        X = tf.reshape(x,[BATCH_SIZE,224,224,1]) 
        
        logits0,logits1,logits2,logits3,end_pintos = train_network_fn(X)
        
        prediction0=tf.reshape(logits0,[-1,CHAR_NUM])
        prediction0=tf.argmax(prediction0,1)
        
        prediction1=tf.reshape(logits1,[-1,CHAR_NUM])
        prediction1=tf.argmax(prediction1,1)
        
        prediction2=tf.reshape(logits2,[-1,CHAR_NUM])
        prediction2=tf.argmax(prediction2,1)
        
        prediction3=tf.reshape(logits3,[-1,CHAR_NUM])
        prediction3=tf.argmax(prediction3,1)
    
        
        sess.run(tf.global_variables_initializer())
        
        saver=tf.train.Saver()
        saver.restore(sess,'./ckpt/crack_captcha-10000.ckpt')
        
        coord=tf.train.Coordinator()  
        threads=tf.train.start_queue_runners(sess=sess,coord=coord)
        
        for i in range(5):
            b_image, b_image_raw, b_label0, b_label1, b_label2, b_label3 = sess.run([image_batch,
                                                                              image_raw_batch,
                                                                              label_batch0,
                                                                              label_batch1,
                                                                              label_batch2,
                                                                              label_batch3]) 
            
            #img = np.array(b_image_raw[0],dtype=np.uint8)
            
            #显示图片[1,224,224]
            img = Image.fromarray(b_image_raw[0],'L')
            
            plt.imshow(img)
            plt.axis('off')
            plt.show()
            print('label:',b_label0,b_label1,b_label2,b_label3)
            
            label0,label1,label2,label3=sess.run([prediction0,prediction1,prediction2,prediction3],
                                                 feed_dict={x:b_image})
            print('predict:',label0,label1,label2,label3)
            
        coord.request_stop()
        coord.join(threads)
    

    在这里插入图片描述
    在这里插入图片描述
    发现识别效果还是很好的.

    展开全文
  • 论如何用python识别验证码(干扰线类型) 1.开发环境与工具 ...python27:sklearn、pytesser、...3.验证码识别大概步骤 转化成灰度图 去背景噪声 图片分割 (1)转化成灰度图 im = cv2...

    (一)python爬虫验证码识别(去除干扰线)

    1.开发环境与工具

    • python27:sklearn、pytesser、opencv等
    • pycharm
    • windows7

    2. 数据集

    这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述
    用request库爬虫抓取某一网站验证码1200张,并做好标注

    3.验证码识别大概步骤

    • 转化成灰度图
    • 去背景噪声
    • 图片分割
    (1)转化成灰度图
    im = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    (2)去除背景噪声

    验证码去除干扰线的思想可参考链接:验证码去除干扰线
    本文所使用的去除背景噪声的方法:
         认真观察我们的实验数据,发现根据线降噪方法来去除噪声是不可行的,因为我们的图片干扰线很粗,和数字差不多粗。那再认真观察一下,1个数字的颜色都是一个‘“色”,那么是否可以跟据颜色来分呢?
         博主认真想了下,先转化成灰度图,再通过图像分割把图片分割一下,去除掉边框和部分噪声,这样就分成了4张图,然后统计每张图的灰度直方图(自己设置bins),找到第二大所对应的像素范围,即某一像素范围内像素数第二多所对应的像素范围(像素最多的应该是白色,空白处),取像素范围中位数mode,然后保留(mode±biases)的像素。这样就可以将大部分噪声去除掉啦。
    (这段描述有点复杂,需要一定的图像基础,不懂的,可以看代码del_noise()方法)
    这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述

    4. 实验方法

    (1)使用Google的pytesser识别图片方法,准确率在50%左右
           pytesser环境配置参考 https://www.cnblogs.com/lcosima/p/7138091.html
    (2)使用机器学习方法KNN,准确率在99.6%

    pip install sklearn
    

    5.pytesser方法

    • 这里im_cut是指:分割好验证码后,传入的子图片
    def del_noise(im_cut):
        ''' variable:bins:灰度直方图bin的数目
                      num_gray:像素间隔
            method:1.找到灰度直方图中像素第二多所对应的像素,即second_max,因为图像空白处比较多所以第一多的应该是空白,第二多的才是我们想要的内容。
                    2.计算mode
                    3.除了在mode+-一定范围内的,全部变为空白。
        '''
        bins = 16
        num_gray = math.ceil(256 / bins)
        hist = cv2.calcHist([im_cut], [0], None, [bins], [0, 256])
        lists = []
        for i in range(len(hist)):
            # print hist[i][0]
            lists.append(hist[i][0])
        second_max = sorted(lists)[-2]
        bins_second_max = lists.index(second_max)
    
        mode = (bins_second_max + 0.5) * num_gray
    
        for i in range(len(im_cut)):
            for j in range(len(im_cut[0])):
                if im_cut[i][j] < mode - 15 or im_cut[i][j] > mode + 15:
                    # print im_cut[i][j]
                    im_cut[i][j] = 255
        return im_cut
    
    # 替换文本
    def replace_text(text):
        text = text.strip()
        text = text.upper()
        rep = {'O': '0',
               'I': '1',
               'L': '1',
               'Z': '7',
               'A': '4',
               '&': '4',
               'S': '8',
               'Q': '0',
               'T': '7',
               'Y': '7',
               '}': '7',
               'J': '7',
               'F': '7',
               'E': '6',
               ']': '0',
               '?': '7',
               'B': '8',
               '@': '6',
               'G': '0',
               'H': '3',
               '$': '3',
               'C': '0',
               '(': '0',
               '[': '5',
               'X': '7',
               '`': '',
               '\\': '',
               ' ': '',
               '\n': '',
               '-': '',
               '+': '',
               '*': '',
               '.': '',
               ';': ''
               }
    
        #判断是否有数字,有数字直接返回第一个数字,不需要字符替换
        print text
        if len(text) >= 1:
            pattern = re.compile(u'\d{1}')
            result = pattern.findall(text)
            if len(result) >= 1:
                text = result[0]
            else:
                # 字符替换,替换之后抽取数字返回
                for r in rep:
                    text = text.replace(r, rep[r])
                pattern = re.compile(u'\d{1}')
                result = pattern.findall(text)
                if len(result) >= 1:
                    text = result[0]
    
        return text
    
    
    • 主方法
    #im_cut = [im_cut_1, im_cut_2, im_cut_3, im_cut_4]
    for i in range(4):
    	im_temp = del_noise(im_cut[i])
    	im_result = Image.fromarray(im_temp.astype('uint8'))
    	#使用pytesser识别
    	text = image_to_string(im_result)
    	#做文本替换处理
    	text_rep = replace_text(text)
    	#获得预测结果
    	pre_text.append(text_rep)
    	pre_text = ''.join(pre_text)
    
    • 结果
      这里写图片描述

    6.KNN分类(sklearn)

    (1)先转成灰度图,去背景噪声,分割1200张已标注好的图片,得到4800张子图片;
    这里写图片描述这里写图片描述这里写图片描述这里写图片描述
    (2)用knn训练分类器,训练集:测试集=0.8,训练结果精度达到99%以上;
    (3)使用训练好的模型,进行实际验证码预测,效果不错。

    # -*-coding:utf-8-*-
    import numpy as np
    from sklearn import neighbors
    import os
    from sklearn.preprocessing import LabelBinarizer
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import classification_report
    from sklearn.externals import joblib
    
    import cv2
    
    if __name__ == '__main__':
        # 读入数据
        data = []
        labels = []
        img_dir = './img_train_cut'
        img_name = os.listdir(img_dir)
        # number = ['0','1', '2','3','4','5','6','7','8','9']
        for i in range(len(img_name)):
            path = os.path.join(img_dir, img_name[i])
            # cv2读进来的图片是RGB3维的,转成灰度图,将图片转化成1维
            image = cv2.imread(path)
            im = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            image = im.reshape(-1)
            data.append(image)
            y_temp = img_name[i][-5]
            labels.append(y_temp)
    
        # 标签规范化
        y = LabelBinarizer().fit_transform(labels)
    
        x = np.array(data)
        y = np.array(y)
    
        # 拆分训练数据与测试数据
        x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)
    
        # 训练KNN分类器
        clf = neighbors.KNeighborsClassifier()
        clf.fit(x_train, y_train)
    
        # 保存分类器模型
        joblib.dump(clf, './knn.pkl')
    
        # # 测试结果打印
        pre_y_train = clf.predict(x_train)
        pre_y_test = clf.predict(x_test)
        class_name = ['class0', 'class1', 'class2', 'class3', 'class4', 'class5', 'class6', 'class7', 'class8', 'class9']
        print classification_report(y_train, pre_y_train, target_names=class_name)
        print classification_report(y_test, pre_y_test, target_names=class_name)
    
        # clf = joblib.load('knn.pkl')
        # pre_y_test = clf.predict(x)
        # print pre_y_test
        # print classification_report(y, pre_y_test, target_names=class_name)
    

    结果截图:
    这里写图片描述

    ps:在运行过程中,程序还可能会帮你检测出人工标错的哟!
    这里写图片描述
    这里写图片描述

    代码已上传至https://download.csdn.net/download/weixin_40267472/11097627。

    如果喜欢这篇博客,可以小小打赏下小编,表示下支持哟!!!(毕竟好不容易整理出来的) 谢谢哟~~

    链接:https://pan.baidu.com/s/12ajeAEe_hlH0j-wklvWukg
    提取码:ya85

    在这里插入图片描述

    展开全文
  • 验证码识别总结

    2018-09-01 15:17:39
    现在的验证码有很多形式,然而识别方式也有很多方式,本文就两种方式来进行讲解 (1)tesseract识别方式 这图片已经是二值化的图片有的验证码有很多的反识别措施,例如知乎的验证码点击倒立的文字,还有12306的...
  • 简单的验证码识别

    2018-03-11 21:15:11
    所以本文主要提供验证码识别的一个简单的思路,代码实现的部分还望各位大佬指点。 看了好几篇验证码图片识别的博文,不难归纳出验证码识别的大概思路是收集训练集——&gt;图像处理——&gt;得到图片特征值...
  • pytesseract:用于识别图片文字 准备工具: Tesseract Ocr 下载地址 http://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-3.05.00dev.exe 简单来说,三个步骤: 下载验证码图片。 加载(处...
  • 这是一篇含金量很高的干货文章,国家税务总局全国增值税发票查验平台验证码识别方案和具体思路,实验结果测试了200+次,识别率达到98%以上,识别速度的话,CPU大概5-8毫秒左右,模型大概3mb。
  • 亦思验证码识别系统 (破解版)  亦思验证码识别系统(enjoy-soft.cn)是用于识别的系统性软件,其用途广泛,适用于各类验证码识别,本地图片识别,车牌号码识别,汉字文字识别等领域,拥有识别库体积小,识别速度...
  • 基于matlab不变矩的数字验证码识别,通过模拟人类的视觉特性来分析验证码字符特点,目标是识别验证码,读取图像文件中的验证码字符。验证码的识别涉及图像预处理、分隔、特征提取、识别。这个仿真代码,首先通过对...
  • 完美验证码识别系统

    2020-07-30 23:32:04
    完美验证码识别系统V3.2 1.增加DLL识别返回方式2和3具体看我的函数.txt里说明,主要是增加一个可以返回识别后的总体信任度.这个值你可以给它个阀值,比如说如果总体信任度小于60,那么你就不提交服务器,直接重新获取...
  • 最好的验证码识别软件api接口 验证码识别平台最新功能介绍:   1、识别程序以dll的方式提供使用,通过简单的函数调用即可识别复杂的验证码图片。   2、自动识别; 智能处理各种背景、边框、干扰等;   3、...
  • matlab数字验证码识别

    2019-10-10 10:41:49
    matlab数字验证码识别
  • VB写的最简单的验证码识别程序,含图片识别及源代码模块,验证码图片取自网上ASP程序生成的图片,由程序读取后下载到本地,识别模块通过点阵扫描后对字符点阵数量的统计来进行识别,比较初级。只能识别字符比较规则...
  • 闲来想实现程序模拟登陆一个系统,说白了,就是写个简单的爬虫,但是无奈,遇到了数字图片验证码,在查阅了一些方案以后,遂决定自己手写代码实现验证码识别,分享一下整个过程。 图片验证码是什么 图片验证码...
  • 讲到验证码识别,大家第一个可能想到tesseract。诚然,对于OCR而言,tesseract确实很强大,自带的字模能识别绝大多数规整的中英文。但是验证码毕竟不是OCR。对于现在简单的验证码,其干扰都很难规整的去完,或者说去...
  • 验证码识别OCR技术

    2019-04-04 10:25:20
    在开发爬虫时,会遇到验证码识别,在网站中加入验证码的目的是加强用户安全性和提高反爬虫机制。 验证码类型:字符验证码,图片验证码,gif动图验证码,极验验证码(拖动滑块完成拼图),手机验证码,视频验证码等...
1 2 3 4 5 ... 20
收藏数 31,296
精华内容 12,518
关键字:

验证码识别