30分钟吃掉CRNN-CTC验证码识别

opencv pytorch CRNN验证码识别 opencv验证码识别,pytorch,CRNN 阅读详情

本范例我们使用经典的 CRNN+ CTC Loss 的OCR模型来识别验证码。

我们通过导入一个叫 captcha 的库来生成验证码。

我们生成验证码的字符由数字和大写字母组成。

项目参考:https://github.com/ypwhs/captcha_break

#!pip install captcha torchkeras
import torch 
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from torchvision.transforms.functional import to_tensor, to_pil_image

from tqdm import tqdm
import random
import numpy as np

import torchkeras 
from pathlib import Path
from collections import OrderedDict 


characters = '-' + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'  # 注:’-‘ 为[blank] 特殊字符
width, height  = 192, 64
n_classes = len(characters)

txt_length = 4 #识别的验证码长度
seq_length = 12 #CRNN输出序列长度,一般要求 seq_length>=2*txt_length+1

一,准备数据

from captcha.image import ImageCaptcha
generator = ImageCaptcha(width=320, height=64, 
        fonts=[str(Path(torchkeras.__file__).parent/'assets'/'SimHei.ttf') ],
        font_sizes=[40,45])
generator.generate_image('中国人民很行')

06f8b29f508d971c08590aad8661f82c.png

class CaptchaDataset(Dataset):
    def __init__(self, characters, length, 
                 width, height, input_length, label_length):
        super(CaptchaDataset, self).__init__()
        self.characters = characters
        self.length = length
        self.width = width
        self.height = height
        self.input_length = input_length
        self.label_length = label_length
        self.n_class = len(characters)
        self.generator = ImageCaptcha(width=width, height=height)

    def __len__(self):
        return self.length
    
    def __getitem__(self, index):
        random_str = ''.join([random.choice(self.characters[1:]) for j in range(self.label_length)])
        image = to_tensor(self.generator.generate_image(random_str))
        target = torch.tensor([self.characters.find(x) for x in random_str], dtype=torch.long)
        input_length = torch.full(size=(1, ), fill_value=self.input_length, dtype=torch.long)
        target_length = torch.full(size=(1, ), fill_value=self.label_length, dtype=torch.long)
        return image, target, input_length, target_length
batch_size = 128
ds_train= CaptchaDataset(characters, 100 * batch_size, 
                         width, height, seq_length, txt_length)

ds_val = CaptchaDataset(characters, 20 * batch_size, 
                        width, height, seq_length, txt_length)

dl_train = DataLoader(ds_train, batch_size=batch_size, num_workers=4)
dl_val = DataLoader(ds_val, batch_size=batch_size, num_workers=4)


ds_test = CaptchaDataset(characters, 1, width, height, seq_length, txt_length)

image, target, input_length, label_length = ds_test[0]
print(''.join([characters[x] for x in target]), input_length, label_length)
to_pil_image(image)

二,定义模型

class CRNN(nn.Module):
    def __init__(self, n_classes, input_shape=(3, 64, 128)):
        super().__init__()
        self.input_shape = input_shape
        channels = [32, 64, 128, 256, 256]
        layers = [2, 2, 2, 2, 2]
        kernels = [3, 3, 3, 3, 3]
        pools = [2, 2, 2, 2, (2, 1)]
        modules = OrderedDict()
        
        def cba(name, in_channels, out_channels, kernel_size):
            modules[f'conv{name}'] = nn.Conv2d(in_channels, out_channels, kernel_size,
                                               padding=(1, 1) if kernel_size == 3 else 0)
            modules[f'bn{name}'] = nn.BatchNorm2d(out_channels)
            modules[f'relu{name}'] = nn.ReLU(inplace=True)
        
        last_channel = 3
        for block, (n_channel, n_layer, n_kernel, k_pool) in enumerate(zip(channels, layers, kernels, pools)):
            for layer in range(1, n_layer + 1):
                cba(f'{block+1}{layer}', last_channel, n_channel, n_kernel)
                last_channel = n_channel
            modules[f'pool{block + 1}'] = nn.MaxPool2d(k_pool)
        modules[f'dropout'] = nn.Dropout(0.25, inplace=True)
        
        self.cnn = nn.Sequential(modules)
        self.lstm = nn.LSTM(input_size=self.infer_features(), hidden_size=128, num_layers=2, bidirectional=True)
        self.fc = nn.Linear(in_features=256, out_features=n_classes)
    
    def infer_features(self):
        x = torch.zeros((1,)+self.input_shape)
        x = self.cnn(x)
        x = x.reshape(x.shape[0], -1, x.shape[-1])
        return x.shape[1]
    

    def forward(self, x):
        x = self.cnn(x)
        x = x.reshape(x.shape[0], -1, x.shape[-1])
        x = x.permute(2, 0, 1)
        x, _ = self.lstm(x)
        x = self.fc(x)
        return x
net = CRNN(n_classes, input_shape=(3, height, width))
inputs = torch.zeros((32, 3, height, width))
outputs = net(inputs)
print(outputs.shape) # LSTM默认输出的形状是 Length在前
net.cuda();
torch.Size([12, 32, 37])

三, 训练模型

# 解码函数和计算准确率函数

def decode_target(sequence):
    return ''.join([characters[x] for x in sequence]).replace(' ', '')

def decode(sequence):
    a = ''.join([characters[x] for x in sequence])
    s = ''.join([x for j, x in enumerate(a[:-1]) if x != characters[0] and x != a[j+1]])
    if len(s) == 0:
        return ''
    if a[-1] != characters[0] and s[-1] != a[-1]:
        s += a[-1]
    return s


def eval_acc(targets, preds):
    preds_argmax = preds.detach().permute(1, 0, 2).argmax(dim=-1)
    targets = targets.cpu().numpy()
    preds_argmax = preds_argmax.cpu().numpy()
    a = np.array([decode_target(gt) == decode(pred) for gt,
                  pred in zip(targets, preds_argmax)])
    return a.mean()
import torch.nn.functional as F 
from torchkeras import KerasModel

#我们覆盖KerasModel的StepRunner以实现自定义训练逻辑。
#注意这里把acc指标的结果写在了step_loss中以便和loss一样在Epoch上求平均,这是一个非常灵活而且有用的写法。

class StepRunner:
    def __init__(self, net, loss_fn, accelerator, stage = "train", metrics_dict = None, 
                 optimizer = None, lr_scheduler = None
                 ):
        self.net,self.loss_fn,self.metrics_dict,self.stage = net,loss_fn,metrics_dict,stage
        self.optimizer,self.lr_scheduler = optimizer,lr_scheduler
        self.accelerator = accelerator
        if self.stage=='train':
            self.net.train() 
        else:
            self.net.eval()
    
    def __call__(self, batch):
        
        images, targets, input_lengths, target_lengths = batch
        
        #loss
        preds = self.net(images)
        preds_log_softmax = F.log_softmax(preds, dim=-1)
        loss = F.ctc_loss(preds_log_softmax, targets, input_lengths, target_lengths)
        acc = eval_acc(targets,preds)
            

        #backward()
        if self.optimizer is not None and self.stage=="train":
            self.accelerator.backward(loss)
            self.optimizer.step()
            if self.lr_scheduler is not None:
                self.lr_scheduler.step()
            self.optimizer.zero_grad()
            
            
        all_loss = self.accelerator.gather(loss).sum()
        
        #losses
        step_losses = {self.stage+"_loss":
                       all_loss.item(),
                       self.stage+'_acc':acc}
        
        #metrics
        step_metrics = {}
        if self.stage=="train":
            if self.optimizer is not None:
                step_metrics['lr'] = self.optimizer.state_dict()['param_groups'][0]['lr']
            else:
                step_metrics['lr'] = 0.0
        return step_losses,step_metrics
    
    
KerasModel.StepRunner = StepRunner
model = KerasModel(net,
                   loss_fn=None,
                   optimizer = torch.optim.AdamW(net.parameters(),lr = 2e-6)
                   )

model.load_ckpt('ctc_crnn.pt')
model.fit(
    train_data = dl_train,
    val_data= dl_val,
    ckpt_path='ctc_crnn.pt',
    epochs=30,
    patience=10,
    monitor="val_acc", 
    mode="max",
    plot = True,
    wandb = False,
    callbacks=[visdis],
    quiet = lambda epoch: epoch>5
)

b3660ec7195f1b7848bcd21a94d4f218.png

四,评估模型

def display_fn(model):
    model.eval()
    right = True
    while right:
        image, target, input_length, label_length = ds_test[0]
        output = model(image.unsqueeze(0).cuda())
        output_argmax = output.detach().permute(1, 0, 2).argmax(dim=-1)
        right = (decode_target(target) == decode(output_argmax[0]))
        print('gt:', decode_target(target),' ','pred:', decode(output_argmax[0]))
    display(to_pil_image(image))
    
    
from torchkeras.kerascallbacks import VisDisplay
visdis = VisDisplay(display_fn,model)

207e86800485cbaa61de4000aab6a625.png

五,使用模型

def predict(model,image):
    model.cuda()
    tensor = to_tensor(image)
    output = model(tensor.unsqueeze(0).cuda())
    output_argmax = output.detach().permute(1, 0, 2).argmax(dim=-1)
    preds = decode(output_argmax[0])
    return preds
model.load_ckpt('ctc_crnn.pt')
generator = ImageCaptcha(width=width, height=height)
image = generator.generate_image('ABBD')
image
predict(model,image)

11911d09501d490f47ee7896503488d1.png

六,保存模型

torch.save(model.net.state_dict(),'best.pt')

公众号算法美食屋后台回复关键词:CRNN,获取本文notebook源代码和B站视频讲解。

pytorch验证码识别crnn+ctcloss+beam_search_decoder从0到1(附避坑要点!) 阅读详情

相关推荐

CRNN+CTC介绍以及验证码识别的应用

卷积神经网络 一个卷积神经网络主要由一下5种结构组成: 输入层。输入层是整个网络结构的输入,在处理图像的卷积神经网络结构中, 它一般代表了一张图片的像素矩阵。可以使用一个三维矩阵来代表一张图片,三维矩阵中的长和宽代表了图像的大小,而三维矩阵的深度代表了图像的色彩通道(channel)。比如黑白图片的深度为1,而在RGB色彩模式下,图像深度为3。 卷积层。卷积层是一个卷积神经网络中最为重要的部分。...

youn 2779

基于CRNN实现验证码识别

AI小项目:基于CRNN的验证码识别,使用PaddlePaddle和Pytorch的完整代码实现

CV小菜鸟的博客 1184

Tensorflow应用之简单验证码识别

1.Tensorflow的安装方式: 这个项目中 采用了tensorflow 1.1版本 安装方式 pip install tensorflow==1.1.0rc2 或者 1.2.1 版本 pip install tensorflow==1.2.1 2.训练集训练集以及测试及如下(纯手工打造,所以数量不多): 3.实现代码部分(参考了网上的一些实现来完成的) mai

huplion的专栏 1万+

CRNN不定长验证码识别

blank为0使得我们在计算CTCLoss之前需要对样本进行移位,例如a、b、c对应的标签为0、1、2,我们需要把相应的标签改为1、2、3,才能计算CTCLoss。而在进行推理的过程中,则需要把预测的结果的index进行减一,映射回原始正确的标签。关于验证码识别的任务,我们可以通过使用卷积神经网络采用多标签分类的方法来完成,但是当验证码是不定长的时候,就无法使用多标签分类的方法来解决了,在这类任务中,识别的目标是类似于序列的长条形图片,我们将会使用自然语言处理以及时间序列预测任务中的循环神经网络算法。

爱编程的鱼的博客 740

验证码识别(任何验证)

顺心远程代答http://sx.softsf.com 验证码人工识别,正确率99.9%,速度5秒内,7*24小时不间断答题

详细解读文字识别工具———Tesseract-OCR

   在尝试破解12306验证码的时候,提前了解了一下应对各种验证码的解决方案,这里主要是学习到了面对文字图片验证码,例如亚马逊、豆瓣等平台的登录时会遇到的情况,效果还不错。 一、工具介绍 ​    Tesseract-OCR 是一款由HP实验室开发由Google维护的开源OCR(Optical Character Recognition...

别看我只是一只羊 2万+

【机器学习】基于CNN-RNN模型的验证码图片识别

本篇博文深入探讨了OCR技术在验证码识别领域的广泛应用与发展。首先,我们概述了OCR技术的重要性,包括其在提升用户体验和保障系统安全方面的作用。接着,我们详细介绍了OCR模型的工作原理,包括图像预处理、字符识别等关键步骤,并展示了其在不同领域的应用潜力。随后,我们详细阐述了OCR模型的构建、训练与优化过程,强调了CTC损失层在处理序列识别问题中的重要性。最后,我们讨论了模型的推理预测阶段,并通过可视化工具展示了模型的识别效果。展望未来,OCR技术将持续进步,并在网络安全和用户体验提升方面发挥更大作用。

MUKAMO的博客 2976

9 HAL库驱动框架简述(STM32HAL库)

HAL库外设的使用步骤总结如下:1、定义并填充xxx外设句柄结构体。2、如果遵循HAL库规范,通过HAL_xxx_MspInit()函数,实现外设底层资源的初始化,包括但不限于GPIO、时钟、DMA、中断等资源的初始化。3、调用HAL库的对应外设初始化函数,形如:HAL_xxx_Init()。4、初始化完成,开始使用外设。5、使用方法具体查看对应外设的HAL库驱动包中的说明:补充:HAL库使用主线外设初始化外设使用。

qq_25218501的博客 1983

crnn验证码识别

验证码识别流程图 验证码识别效果 Crnn验证码识别模块 早期的验证码破解主要对字符检测,切割,后对单个字符的识别。该方法只能对传统的背景清晰,文字较为端正简单的验证码进行识别,无法适应复杂背景的验证码文字。该验证码识别采用样本自动生成及加入相应网站验证码图片,crnn进行训练识别。 训练样本的自动生成 <1>:生成验证码词库,比如字符只有0-9 a-z A-Z 零-...

u013293750的博客 4028

比亚迪璇玑架构:10ms级响应引领智能驾驶革命

比亚迪璇玑架构通过三大创新,实现10ms级控制响应时延,使AEB刹车距离比竞品缩短20米。

百态·数智思维 | 聚焦大数据、量化与未来AI 1257

[附源码]计算机毕业设计-Steam游戏平台系统论文Springboot程序

项目运行环境配置:(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可4.

JSP、ssm毕设程序源码 1494

CNN卷积神经网络识别验证码

用卷积神经网络训练可以帮你识别验证码的ai

JJ-Li的博客 1559

搞定安卓11+抓包难题:用Kitsune Mask、magic_overlayfs和LSPosed三件套绕过SSL Pinning(保姆级教程)

本文详细解析了安卓11+系统中抓包面临的核心挑战,包括SSL Pinning和Root检测机制,并提供了使用Kitsune Mask、magic_overlayfs和LSPosed三件套的完整解决方案。通过动态分区技术解析和工具链配置,帮助开发者绕过安全限制,实现高效抓包分析。

weixin_42665255的博客 444

RNN入门(二)识别验证码

介绍   作为RNN的第二个demo,笔者将会介绍RNN模型在识别验证码方面的应用。   我们的验证码及样本数据集来自于博客: CNN大战验证码,在这篇博客中,我们已经准备好了所需的样本数据集,不需要在辛辛苦苦地再弄一遍,直接调用data.csv就可以进行建模了。 RNN模型   用TensorFlow搭建简单RNN模型,因为是多分类问题,所以在最后的输出部分再加一softmax层,损失函数采用对...

山阴少年 2255

软件设计师考试下午题代码部分详解:23种设计模式全面解析

软件设计师考试的下午题通常会考察设计模式的应用,这部分内容既是重点也是难点。本文将系统地介绍考试中常见的23种设计模式,通过详细代码示例和通俗易懂的讲解,帮助考生掌握这些核心知识点,提高应试能力。概念:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。适用场景:系统要独立于产品的创建、组合和表示时;系统要由多个产品系列中的一个来配置时。@Override@Override@Override@Override// 产品族A@Override。

4万+

goahead(嵌入式Web服务器)之openssl 应用篇

1、环境配置 在me.h文件里修改以下宏定义 ME_COM_MBEDTLS 0 ME_COM_MATRIXSSL 0 ME_COM_NANOSSL 0 ME_COM_OPENSSL 1 2、添加 goahead-openssl.c goahead-openssl.c这个文件在有些goahead源码中是没有的,后面的章节中会提供openssl应用测例 3、依赖的库 goahead的openssl 应用需要依赖libssl.a与libcrypto.a(libssl.so与libcrypto.so)两个库,做好

weixin_40732273的博客 2089

用CNN识别验证码

一,基本思路 生成数据(验证码样本) 1.验证码类型 我们这里生成的验证码是当前最常见的验证码即由26位大小写英文字母和0到9十个数字组成的字符型验证码。 2.生成方式 我们可以选择两种方式来生成我们的训练数据。一种是一次性生成几万张图(保存到本地),另一种是定义一个数据生成器(数据未被保存)。两种方式各有千秋,第一种方式的好处是训练的时候显卡利用率高,如果你需要经常调参,可以一次生成,...

qq_40155500的博客 7003

【Android面试八股文】Android Application为什么是单例?

这道题相对简单,就是考察大家是否了解application的创建流程。的实例,它用来存储和处理整个全局变量的一些事情,它同时还是一个。为空的时候,才会创建,从而保证了它是一个单例对象。一样有自己的生命周期,但是它并没有那么复杂,因为。对象的创建过程,找出它为什么是单例的原因。全局进行一些配置,比如配置插件。的时候才会创建,所以说可以在。凭什么是单例,我们查看下。启动的时候都会创建一个。是怎么一步步创建的。是一个单例,即每一个。

字节卷动 532

CRNN----CTC配置

【代码】CRNN----CTC配置。

weixin_45866058的博客 662

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

[验证码识别技术]字符验证码杀手--CNN

字符验证码杀手--CNN 1 abstract  目前随着深度学习,越来越蓬勃的发展,在图像识别和语音识别中也表现出了强大的生产力。对于普通的深度学习爱好者来说,一上来就去跑那边公开的大型数据库,比如ImageNet或者CoCo,可以会觉得这个屠龙之技离生活好遥远。那么本文就是希望将此技术运用到一些普通用户日常就能感知的场景上,让普通用户切实能够体会到深度学习工具的非凡能力。 关键字:深度学...

weixin_33991418的博客 511

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

CRNN+CTC实现不定长验证码识别(keras模型-训练篇)

本文旨在讲解如何使用以tensorflow作为后端的keras构建一个使用CTC为loss的CRNN,并针对训练过程进行了优化(tricks),避免模型不收敛的问题。本文不着重原理的阐述、网络结构优化等内容,并假定读者已经了解过CTC、CNN、RNN的基本原理。.

gdhy9064的博客 5306

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【模型训练】-图形验证码识别

MaxPool2d :减少数据空间大小,池化窗口的大小,通常设置为2×2。减少参数数量和计算量,同时也能提高模型的鲁棒性。BatchNorm(512):对输入数据进行归一化处理,使得每个通道的数据均值为0,方差为1,提高模型的泛化能力。dropout:随机丢弃神经元的输出来减少模型的复杂度和过拟合的风险。padding 完成卷积后是否填充空白。

宣晨光 1870

crnn pytorch 训练、测试

1.仓库地址 https://github.com/meijieru/crnn.pytorch 原版用lua实现的:https://github.com/bgshih/crnn 需要用到的warp_ctc_pytorch: https://github.com/SeanNaren/warp-ctc 2.环境安装 普通的环境都可以吧,我是cuda10.0,torch1.2.0 python3.6...

无左无右的博客 3528

用pytorch实现crnn+ctc来识别验证码

pytorch 实现crnn+ctc来识别验证码说明环境搭建训练服务搭建 说明 利用crnn和ctc来进行验证码识别是现在主流的机器学习的方式,本文期望利用pytorch来实现单个验证码的识别,同时整合多个训练样本,期望能通过增量识别的方式,最终通过一个模型来识别多个验证码。 本文采用的是阿里云的gpu的服务器。 源码地址:https://github.com/linlihuiyang/ocr-p...

5842

CNN+LSTM深度学习文字检测

CNN+LSTM深度学习文字检测 最近看到论文Detecting Text in Natural Image with Connectionist Text Proposal Network 对文字的检测效果挺不错的,就把它提到了windows平台上。在我的笔记本上cpu模式下大概要10s,gpu模式大概800ms吧。先看下论文运行的效果。 整体效果还是挺好的,作者提供的代码没有对

u013293750的博客 4万+

验证码识别

验证码识别是3年前的一个小愿望了(当时是做一个自动回帖器,抽奖iphone),但自己这两年主要在做分布式架构,今年终于抽出了空,又战胜了对数学的恐惧,在coursera上学习了吴恩达的机器学习和深度学习,验证码识别也算是对部分课程的实践,下面就来整理一下这次识别的过程。 验证码识别主流程 识别细节 1 目标检测检测出验证码图片中的字符边距 11 labelImg使用 12 darknet使用

zxx的专栏 1万+
上一篇: 60分钟吃掉detectron2
下一篇: YOLOv8 训练自己的数据集
算法美食屋
博客等级 码龄9年 2万+粉丝 154原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值