基于卷积神经网络的脱机手写签名识别(Pytorch,Opencv,CNN)

前言:

最近做了一个手写签名识别的项目,即判断签名的真伪。使用的深度学习框架为Pytorch,Opencv等等。数据集中共包含17个人的签名。使用resnet18网络进行训练。文末附有源码下载地址。

Bi 设 Dai 坐

视频效果如下所示:

深度学习脱机手写签名识别(Pytorch,Opencv)

resnet18模型结构:

在这里插入图片描述

resnet18实现代码

加载pytorch内部自带resnet18模型,代码较为简单:

from torchvision import models
import torch.nn as nn

#加载resnet18模型
net=models.resnet18(pretrained=False)
#因为输入图片为单通道图片,所以修改模型第一个卷积层
net.conv1=nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
#因为分类个数为34,所以需要修改模型最后一层全连接层
net.fc=nn.Linear(in_features=512, out_features=34, bias=True)
# print(net)

数据集:

部分数据集图像如下所示:
在这里插入图片描述

训练模型:

代码如下所示:

from mymodel import net
from myDataset import MyData
import random
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.optim as optim
import torch
from tqdm import tqdm
import matplotlib.pylab as plt

batch_size=20
Epoch=50
lr=0.0002

lines=open('data.txt','r').readlines()
random.shuffle(lines)
val_lines=random.sample(lines,int(len(lines)*0.1))
train_lines=list(set(lines)-set(val_lines))


train_data=MyData(lines=train_lines)
val_data=MyData(lines=val_lines,train=False)
train_loader=DataLoader(dataset=train_data,batch_size=batch_size,shuffle=True)
val_loader=DataLoader(dataset=val_data,batch_size=batch_size,shuffle=False)

num_train   = len(train_lines)
epoch_step  = num_train // batch_size
BCE_loss     = nn.BCELoss()
optimizer  = optim.Adam(net.parameters(), lr=lr, betas=(0.5, 0.999))
lr_scheduler  = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.99)
#获取学习率函数
def get_lr(optimizer):
    for param_group in optimizer.param_groups:
        return param_group['lr']
#计算准确率函数
def metric_func(pred,lab):
    _,index=torch.max(pred,dim=-1)
    acc=torch.where(index==lab,1.,0.).mean()
    return acc
device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
net=net.to(device)
#设置损失函数
loss_fun     = nn.CrossEntropyLoss()

if __name__ == '__main__':

    T_acc=[]
    V_acc=[]
    T_loss=[]
    V_loss=[]

    # 设置迭代次数200次
    epoch_step = num_train // batch_size
    for epoch in range(1, Epoch + 1):
        net.train()

        total_loss = 0
        loss_sum = 0.0
        train_acc_sum=0.0

        with tqdm(total=epoch_step, desc=f'Epoch {
      
      epoch}/{
      
      Epoch}', postfix=dict, mininterval=0.3) as pbar:
            for step, (features, labels) in enumerate(train_loader, 1):
                features = features.to(device)
                labels = labels.to(device)
                batch_size = labels.size()[0]

                optimizer.zero_grad()
                predictions = net(features)
                loss = loss_fun(predictions, labels)
                loss.backward()
                optimizer.step()
                total_loss += loss
                train_acc = metric_func(predictions, labels)
                train_acc_sum+=train_acc
                pbar.set_postfix(**{
    
    'loss': total_loss.item() / (step),
                                    "acc":train_acc_sum.item()/(step),
                                    'lr': get_lr(optimizer)})
                pbar.update(1)
        T_acc.append(train_acc_sum.item()/(step))
        T_loss.append(total_loss.item() / (step))
        # 验证
        net.eval()
        val_acc_sum = 0
        val_loss_sum=0
        for val_step, (features, labels) in enumerate(val_loader, 1):
            with torch.no_grad():
                features = features.to(device)
                labels = labels.to(device)
                predictions = net(features)
                val_metric = metric_func(predictions, labels)
                loss=loss_fun(predictions,labels)
            val_acc_sum += val_metric.item()
            val_loss_sum+=loss.item()
        print('val_acc=%.4f' % (val_acc_sum / val_step))
        V_acc.append(round(val_acc_sum / val_step,2))
        V_loss.append(val_loss_sum/val_step)

        # 保存模型
        if (epoch) % 2 == 0:
            torch.save(net.state_dict(), 'logs/Epoch%d-Loss%.4f_.pth' % (
                epoch, total_loss / (epoch_step + 1)))

        lr_scheduler.step()

    plt.figure()
    plt.plot(T_acc,'r')
    plt.plot(V_acc,'b')
    plt.title('Training and validation Acc')
    plt.xlabel("Epochs")
    plt.ylabel("Acc")
    plt.legend(["Train_acc", "Val_acc"])
    # plt.show()

    plt.figure()
    plt.plot(T_loss, 'r')
    plt.plot(V_loss, 'b')
    plt.title('Training and validation loss')
    plt.xlabel("Epochs")
    plt.ylabel("loss")
    plt.legend(["Train_loss", "Val_loss"])
    plt.show()


项目结构:

在这里插入图片描述
运行main.py即可弹出界面。项目中包含完整的代码及数据集。

项目下载:下载地址

猜你喜欢

转载自blog.csdn.net/Czqqwer/article/details/130267454