Transformer编码器的验证码端到端识别方法

验证码识别是图像文本识别领域的一个重要分支。本文提出一种结合卷积神经网络(CNN)与Transformer编码器的端到端验证码识别方法。首先通过CNN提取二维图像特征,再将其映射为一维时序特征,输入多层Transformer Encoder以捕获全局依赖关系,最后通过全连接层完成多字符预测。实验结果表明,该方法在随机扭曲、噪声干扰等复杂验证码上具有较高的准确率和泛化能力。

一、引言

传统的验证码识别方法多依赖字符分割与OCR识别,但在复杂背景和字符粘连情况下容易失败。近年来,基于深度学习的端到端识别成为主流,其中 CNN + LSTM + CTC 结构较为常见,但 LSTM 的长序列建模效率有限。本文利用 Transformer 的全局注意力机制替代 LSTM,在时序建模方面表现出更强的能力。

二、系统架构

数据生成:随机生成数字与字母验证码,添加旋转与噪声。

图像预处理:灰度化、归一化。
更多内容访问ttocr.com或联系1436423940
特征提取:CNN 网络提取空间特征。

时序建模:Transformer Encoder 捕获全局依赖。

字符预测:全连接层输出每个位置的字符类别。

三、数据集生成
from captcha.image import ImageCaptcha
import random, string, os

CHAR_SET = string.digits + string.ascii_uppercase
CAPTCHA_LEN = 4
IMG_W, IMG_H = 160, 60

def gen_text():
return ''.join(random.choices(CHAR_SET, k=CAPTCHA_LEN))

def gen_dataset(path, num=5000):
os.makedirs(path, exist_ok=True)
gen = ImageCaptcha(width=IMG_W, height=IMG_H)
for _ in range(num):
text = gen_text()
gen.write(text, os.path.join(path, f"{text}.png"))

gen_dataset("data/train", 5000)
gen_dataset("data/test", 1000)

四、模型结构(PyTorch)
import torch
import torch.nn as nn

class CNN_Transformer(nn.Module):
def init(self, num_classes, img_h=60, d_model=256, nhead=8, num_layers=4):
super().init()
self.cnn = nn.Sequential(
nn.Conv2d(1, 64, 3, 1, 1), nn.ReLU(), nn.MaxPool2d(2, 2),
nn.Conv2d(64, 128, 3, 1, 1), nn.ReLU(), nn.MaxPool2d(2, 2),
nn.Conv2d(128, d_model, 3, 1, 1), nn.ReLU()
)
encoder_layer = nn.TransformerEncoderLayer(d_model=d_model, nhead=nhead)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
self.fc = nn.Linear(d_model, num_classes)

def forward(self, x):
x = self.cnn(x) # [B, C, H, W]
b, c, h, w = x.size()
x = x.permute(0, 3, 1, 2).contiguous().view(b, w, ch) # [B, W, CH]
x = self.transformer(x) # [B, W, d_model]
out = self.fc(x) # [B, W, num_classes]
return out
五、训练流程
model = CNN_Transformer(len(CHAR_SET))
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

for epoch in range(20):
for imgs, labels in train_loader:
imgs, labels = imgs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(imgs) # [B, W, num_classes]
loss = criterion(outputs.view(-1, outputs.size(-1)), labels.view(-1))
loss.backward()
optimizer.step()
print(f"Epoch {epoch}, Loss: {loss.item():.4f}")

posted @ 2025-08-14 11:18  ttocr、com  阅读(14)  评论(0)    收藏  举报