当前位置: 首页 > news >正文

用 PyTorch 和 CNN 进行验证码识别

在本教程中,我们将使用 PyTorch 和 卷积神经网络(CNN) 来构建一个验证码识别系统。PyTorch 是一个广泛使用的深度学习框架,特别适合研究和原型设计。卷积神经网络(CNN)是处理图像数据的强大工具,它可以自动从图像中学习特征,并执行图像分类等任务。

  1. 环境准备

首先,确保你已安装以下依赖包:

pip install torch torchvision opencv-python numpy matplotlib pillow
更多内容访问ttocr.com或联系1436423940

torch:PyTorch 框架,支持深度学习模型的训练和推理。

torchvision:提供常用的图像处理功能,及数据集和模型。

opencv-python:用于图像预处理和处理。

numpy:处理数组和矩阵。

matplotlib:用于绘制图表。

  1. 数据集准备与图像预处理

验证码的图像通常包含多个字符,且图像噪声较大,可能还有旋转和扭曲。我们需要对图像进行一些基本的预处理,主要包括灰度化、二值化、去噪和字符分割。

(1) 图像预处理

我们将图像转换为灰度图,然后使用 Otsu 的二值化方法将图像转化为二值图,这将有助于提升字符的识别效果。

import cv2
import numpy as np

def preprocess_image(img_path):
# 读取图像
img = cv2.imread(img_path)

# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 使用 Otsu 的方法进行二值化
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)# 高斯模糊去噪
blurred = cv2.GaussianBlur(binary, (5, 5), 0)return blurred

示例图像路径

img_path = 'captcha_images/test1.png'
processed_img = preprocess_image(img_path)

显示处理后的图像

cv2.imshow('Processed Image', processed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

(2) 提取字符区域

验证码中的每个字符通常由轮廓框住。我们使用 OpenCV 的轮廓检测方法来提取字符区域,并将其分割开。

def extract_characters(processed_img):
contours, _ = cv2.findContours(processed_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
char_images = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
if w > 10 and h > 10: # 忽略小的噪点
char_img = processed_img[y:y+h, x:x+w]
char_images.append(char_img)

# 按照字符从左到右的顺序排序
char_images.sort(key=lambda x: x[0][0])  # 排序依据是字符的左上角 x 坐标
return char_images

提取字符区域

char_images = extract_characters(processed_img)

显示提取的字符

for i, char_img in enumerate(char_images):
cv2.imshow(f'Character {i+1}', char_img)
cv2.waitKey(0)

cv2.destroyAllWindows()

  1. 构建卷积神经网络(CNN)

接下来,我们使用 PyTorch 来构建一个卷积神经网络(CNN)。CNN 由多个卷积层和池化层组成,能够自动从图像中提取特征,并对图像进行分类。

(1) 定义 CNN 模型

我们将构建一个简单的 CNN,包括两个卷积层、两个池化层,并在最后使用全连接层输出验证码的类别。

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader

class CNNModel(nn.Module):
def init(self):
super(CNNModel, self).init()
# 卷积层1
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(2, 2)
# 卷积层2
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
# 全连接层
self.fc1 = nn.Linear(64 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 36) # 36 类(假设验证码由数字和字母组成)

def forward(self, x):# 卷积层1 -> 池化层x = self.pool(torch.relu(self.conv1(x)))# 卷积层2 -> 池化层x = self.pool(torch.relu(self.conv2(x)))# 展平x = x.view(-1, 64 * 7 * 7)# 全连接层1x = torch.relu(self.fc1(x))# 输出层x = self.fc2(x)return x

初始化模型

model = CNNModel()
print(model)

  1. 数据加载与训练准备

为了训练模型,我们需要准备数据集。我们将加载图像并将其调整为 28x28 的大小,这样便于 CNN 进行处理。同时,我们需要将图像像素值规范化到 [0, 1] 之间。

(1) 创建数据集类

我们需要定义一个自定义的 PyTorch 数据集类,用于加载和处理验证码图像。

class CaptchaDataset(Dataset):
def init(self, image_paths, labels, transform=None):
self.image_paths = image_paths
self.labels = labels
self.transform = transform

def __len__(self):return len(self.image_paths)def __getitem__(self, idx):img_path = self.image_paths[idx]label = self.labels[idx]# 读取图像img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)img = cv2.resize(img, (28, 28))  # 调整图像大小img = np.expand_dims(img, axis=0)  # 添加频道维度 (28, 28, 1)img = img.astype(np.float32) / 255.0  # 归一化# 转换为 tensorimg = torch.tensor(img)label = torch.tensor(label)return img, label

示例数据集路径和标签

image_paths = ['captcha_images/train1.png', 'captcha_images/train2.png']
labels = [0, 1] # 假设标签是整数类别(0-9 或字母)

创建数据集

dataset = CaptchaDataset(image_paths, labels)

数据加载器

dataloader = DataLoader(dataset, batch_size=2, shuffle=True)

  1. 训练模型

接下来,我们使用训练集训练模型。我们将使用 交叉熵损失 和 Adam 优化器 来训练模型。

(1) 训练循环
def train_model(model, dataloader, num_epochs=5):
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

for epoch in range(num_epochs):running_loss = 0.0for images, labels in dataloader:# 将图像和标签传入模型images = images.unsqueeze(1)  # 添加频道维度 (batch_size, 1, 28, 28)optimizer.zero_grad()  # 清除之前的梯度# 前向传播outputs = model(images)loss = criterion(outputs, labels)# 反向传播和优化loss.backward()optimizer.step()# 记录损失running_loss += loss.item()print(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(dataloader)}")

训练模型

train_model(model, dataloader)

  1. 测试与预测

训练完成后,我们可以使用测试数据对模型进行评估,并进行预测。

(1) 测试模型
def evaluate_model(model, dataloader):
model.eval() # 设置为评估模式
correct = 0
total = 0
with torch.no_grad(): # 不计算梯度
for images, labels in dataloader:
images = images.unsqueeze(1) # 添加频道维度
outputs = model(images)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

accuracy = correct / total
print(f'Accuracy: {accuracy * 100:.2f}%')

测试模型

evaluate_model(model, dataloader)

(2) 预测新的验证码
def predict(model, img_path):
img = preprocess_image(img_path)
img = cv2.resize(img, (28, 28))
img = np.expand_dims(img, axis=0) # 添加批次维度
img = np.expand_dims(img, axis=0) # 添加频道维度
img = torch.tensor(img, dtype=torch.float32) / 255.0

model.eval()
with torch.no_grad():outputs = model(img)_, predicted = torch.max(outputs, 1)return predicted.item()

预测新的验证码

predicted_label = predict(model, 'captcha_images/test1.png')
print(f"Predicted label: {predicted_label}")

http://www.wxhsa.cn/company.asp?id=6989

相关文章:

  • 用 Keras 和 CNN 进行验证码识别
  • 从 Bank Conflict 数学表示看 Buffer 设计 Trade-Off
  • 被彼此笼罩 任泪水将我们缠绕 深陷入恶魔的拥抱 在阴冷黑暗处灼烧 吞下这毒药
  • mysql无法连接服务器的mysql #mysql8
  • DAG 最小路径覆盖问题 笔记
  • SP3D c# 开发独立的exe
  • python错误code
  • 瑞 ping 我
  • java八股文笔记 - 指南
  • NOIP 模拟赛十六
  • 【AT_dp_y】Grid 2 - Harvey
  • C#十五天 026多态重写 027抽象类与开闭原则 028接口,依赖反转,单元测试
  • 解题报告-P11844 [USACO25FEB] Friendship Editing G
  • 两种判断计算机大小端模式的方法
  • CSP-S模拟23
  • CF1413F Roads and Ramen
  • 复现The Annotated Transformer代码时遇到的问题和相关链接
  • Node.js 文件上传中文文件名乱码难题,为什么只有Node会有乱码困难,其他后端框架少见?
  • ROS2之节点
  • 9.17日总结
  • ECT-OS-JiuHuaShan 框架,元推理AGI奇迹
  • Mapper与Mapper.xml的关系
  • Rocky Linux10.0安装zabbix7.4详细步骤 - 教程
  • 【P3158】放棋子 - Harvey
  • 最强AI语音克隆和文本配音工具!与真人无异,CosyVoice下载介绍
  • 近日C++线上练习结果
  • 密力根油滴实验实验报告
  • Linux 系统插入U盘/移动硬盘实现自动挂载
  • 来点人瑞平我
  • 【P2051】中国象棋 - Harvey