手写签名在日常生活中随处可见,简单来说就是亲笔书写自己的名字,在纸质文档上使用手写签名主要用以确定签字者的身份,并表示签字者同意所签署文档中规定的内容,对文档的真实性负责,且具有法律效力。由此看见手写签名的重要性。在现实的生活中不乏有不法分子模仿其他人的字体,进而模仿他人的签名获得不发的利益。尽管会有鉴别字体的工作,但在鉴别时不仅不准确,而且还十分的消耗人力以及财力。为了解决这一客观显示存在的问题,笔者结合着人工智能的思想和并使用计算机视觉技术对手写签名进行训练,得到了高达100%的训练准确率。并将训练模型进行优化后运用实现了一套手写签名识别系统。

1.开发环境

笔者的开发环境如下,大家可以参考进行配置

  • python3.6或python3.7
  • pytorch1.0.1
  • torchvision 0.2.2.post3
  • visom
  • ubuntu16.04和windows10

2. 准备阶段

在完成了上述的环境搭建后,即可进入到准备阶段了。这里准备的有数据集的准备、以及相关代码的主备。

  • 数据集的准备
    笔者这里的数据集是自己准备的,收集了六个人的手写签名,约4500张签名图片

  • 数据集的划分
    笔者这里将数据集进行六分类的划分,每一类约有750张图片
    数据集划分为训练数据、验证数据、测试数据
    其中训练数据、验证数据、测试数据的具体划分如下图所示

  • 载入数据
    在上述的步骤中已经准备好了相应的数据集,同时也划分好了训练数据、验证数据、测试数据的部分。在完成了理论的设计后,该怎么使用代码对数据进行划分呢,代码如下所示

class Data(Dataset):def __init__(self,root,resize,mode):super(Data,self).__init__()# 保存参数self.root=rootself.resize=resize# 给每一个类做映射self.name2label={}  # "daj":0 ,"hjj":1……for name in sorted(os.listdir(os.path.join(root))):# 过滤掉文件夹if not os.path.isdir(os.path.join(root,name)):continue# 保存在表中;将最长的映射作为最新的元素的label的值self.name2label[name]=len(self.name2label.keys())# print(self.name2label)# 加载文件self.images,self.labels=self.load_csv('images.csv')# 裁剪数据if mode=='train':self.images=self.images[:int(0.6*len(self.images))]   # 将数据集的60%设置为训练数据集合self.labels=self.labels[:int(0.6*len(self.labels))]   # label的60%分配给训练数据集合elif mode=='val':self.images = self.images[int(0.6 * len(self.images)):int(0.8 * len(self.images))]  # 从60%-80%的地方self.labels = self.labels[int(0.6 * len(self.labels)):int(0.8 * len(self.labels))]else:self.images = self.images[int(0.8 * len(self.images)):]   # 从80%的地方到最末尾self.labels = self.labels[int(0.8 * len(self.labels)):]# image+label 的路径

在使用上述的代码后即可将已有的数据集的60%划分为训练数据、20%划分为验证数据、20%划分为测试数据。

3. 训练阶段

在完成了上述的操作后,即可进入到训练阶段。这里笔者使用的是比较经典的神经网络结构–ResNet.
由何凯明团队所提出来的。其深度残差网络(Deep Residual Network)在2015年的ImageNet上取得冠军。具体网络的特点,读者可自行Google了解,这里笔者就不再赘述。

  • 搭建ResNet网络结构
    搭建的网络结构代码如下:
class ResBlk(nn.Module):def __init__(self, ch_in, ch_out, stride=1):super(ResBlk, self).__init__()self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=stride, padding=1)self.bn1 = nn.BatchNorm2d(ch_out)self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)self.bn2 = nn.BatchNorm2d(ch_out)self.extra = nn.Sequential()if ch_out != ch_in:# [b, ch_in, h, w] => [b, ch_out, h, w]self.extra = nn.Sequential(nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=stride),nn.BatchNorm2d(ch_out))def forward(self, x):out = F.relu(self.bn1(self.conv1(x)))out = self.bn2(self.conv2(out))# short cut.# extra module: [b, ch_in, h, w] => [b, ch_out, h, w]# element-wise add:out = self.extra(x) + outout = F.relu(out)return outclass ResNet18(nn.Module):def __init__(self, num_class):super(ResNet18, self).__init__()self.conv1 = nn.Sequential(nn.Conv2d(3, 16, kernel_size=3, stride=3, padding=0),nn.BatchNorm2d(16))# followed 4 blocks# [b, 16, h, w] => [b, 32, h ,w]self.blk1 = ResBlk(16, 32, stride=3)# [b, 32, h, w] => [b, 64, h, w]self.blk2 = ResBlk(32, 64, stride=3)# # [b, 64, h, w] => [b, 128, h, w]self.blk3 = ResBlk(64, 128, stride=2)# # [b, 128, h, w] => [b, 256, h, w]self.blk4 = ResBlk(128, 256, stride=2)# [b, 256, 7, 7]self.outlayer = nn.Linear(256*3*3, num_class)def forward(self, x):x = F.relu(self.conv1(x))# [b, 64, h, w] => [b, 1024, h, w]x = self.blk1(x)x = self.blk2(x)x = self.blk3(x)x = self.blk4(x)# print(x.shape)x = x.view(x.size(0), -1)x = self.outlayer(x)return xdef main():blk = ResBlk(64, 128)tmp = torch.randn(2, 64, 224, 224)out = blk(tmp)print('block:', out.shape)model = ResNet18(5)tmp = torch.randn(2, 3, 224, 224)out = model(tmp)print('resnet:', out.shape)p = sum(map(lambda p:p.numel(), model.parameters()))print('parameters size:', p)if __name__ == '__main__':main()
  • 训练
    在完成了网络的搭建后,即可对数据进行训练。
    笔者这里设置如下
    batchsz=128
    lr = 1e-3
    epochs = 10
batchsz = 128
lr = 1e-3
epochs = 10device = torch.device('cuda')
train_db = Data('train_data', 224, mode='train')
val_db = Data('train_data', 224, mode='val')
test_db = Data('train_data', 224, mode='test')
train_loader = DataLoader(train_db, batch_size=batchsz, shuffle=True,num_workers=4)
val_loader = DataLoader(val_db, batch_size=batchsz, num_workers=4)
test_loader = DataLoader(test_db, batch_size=batchsz, num_workers=4)
viz = visdom.Visdom()def evalute(model, loader):model.eval()correct = 0total = len(loader.dataset)for x, y in loader:x, y = x.to(device), y.to(device)with torch.no_grad():logits = model(x)pred = logits.argmax(dim=1)correct += torch.eq(pred, y).sum().float().item()return correct / totaldef main():model = ResNet18(6).to(device)optimizer = optim.Adam(model.parameters(), lr=lr)criteon = nn.CrossEntropyLoss()best_acc, best_epoch = 0, 0global_step = 0viz.line([0], [-1], win='loss', opts=dict(title='loss'))viz.line([0], [-1], win='val_acc', opts=dict(title='val_acc'))for epoch in range(epochs):if epoch % 1 == 0:print('第 '+str(epoch+1)+' training……')val_acc = evalute(model, val_loader)if val_acc > best_acc:best_epoch = epochbest_acc = val_acctorch.save(model.state_dict(), 'best.mdl')viz.line([val_acc], [global_step], win='val_acc', update='append')print('最好的准确率:', best_acc, '最好的批次:', best_epoch)model.load_state_dict(torch.load('best.mdl'))print('正在加载模型……')test_acc = evalute(model, test_loader)print('测试准确率:', test_acc)if __name__ == '__main__':main()

训练可视化结果如下:

这里也许读者会想有没有过拟合呢??

可以看到,也没有出现过拟合的问题。

4. 模型使用及系统实现

将训练获得的训练模型装载,并系统的使用其进行签名的识别。
这里笔者结合着计算机视觉常用的库opencv进行使用模型。
同时笔者为了能够更加符合日常的使用,这里笔者将opencv显示进行了中文化。
其代码如下:

def prediect(img_path):net=torch.load('model.pkl')net=net.to(device)torch.no_grad()img=Image.open(img_path)img=transform(img).unsqueeze(0)img_ = img.to(device)outputs = net(img_)_, predicted = torch.max(outputs, 1)print(classes[predicted[0]])begin = Speak()begin.speak(str(classes[predicted[0]]))img = cv2.imread(img_path)  # 如想读取中文名称的图片文件可用cv2.imdecode()pil_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # cv2和PIL中颜色的hex码的储存顺序不同,需转RGB模式pilimg = Image.fromarray(pil_img)  # Image.fromarray()将数组类型转成图片格式,与np.array()相反draw = ImageDraw.Draw(pilimg)  # PIL图片上打印汉字font = ImageFont.truetype("simhei.ttf", 20,encoding="utf-8")  # 参数1:字体文件路径,参数2:字体大小draw.text((0, 0), classes[predicted[0]], (255, 0, 0), font=font)img = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR)  # 将图片转成cv2.imshow()可以显示的数组格式cv2.imshow("show", img)if cv2.waitKey(0)==ord(' '):cv2.destroyAllWindows()

并使用系统进行实际的手写签名识别,其结果图下

同时在识别完成后,系统还会自动的将识别结果以语音的形式播报出来。

你听:澜江全 、狄爱景、陆春宇、王雅君……

最后申明:由于笔者知识水平有限,在问题描述上难免会有不准确的地方,还请大家谅解。希望大家多动手实践,共同进步。如若在实践的过程中出现问题,可以同我进行交流qq:1017190168

申明近期笔者接计算机视觉方面的毕业设计、比赛,有需要的欢迎联系!!!

深度学习实战之手写签名识别(100%准确率、语音播报)相关推荐

  1. 深度学习数字仪表盘识别_【深度学习系列】手写数字识别实战

    上周在搜索关于深度学习分布式运行方式的资料时,无意间搜到了paddlepaddle,发现这个框架的分布式训练方案做的还挺不错的,想跟大家分享一下.不过呢,这块内容太复杂了,所以就简单的介绍一下padd ...

  2. 深度学习入门实践学习——手写数字识别(百度飞桨平台)——上篇

    一.项目平台 百度飞桨 二.项目框架 1.数据处理: 2.模型设计:网络结构,损失函数: 3.训练配置:优化器,资源配置: 4.训练过程: 5.保存加载. 三.手写数字识别任务 1.构建神经网络流程: ...

  3. 【第一个深度学习模型应用-手写数字识别】

    基于BP神经网络的手写数字识别报告 基于BP神经网络的手写数字识别报告 一.任务描述 二.数据集来源 三.方法 3.1 数据集处理方法 3.2.模型结构设计 3.3.模型算法 四.实验 4.1.实验环 ...

  4. 深度学习,实现手写字体识别(大数据人工智能公司)

    手写字体识别是指给定一系列的手写字体图片以及对应的标签,构建模型进行学习,目标是对于一张新的手写字体图片能够自动识别出对应的文字或数字.通过深度学习构建普通神经网络和卷积神经网络,处理手写字体数据.通 ...

  5. pytorch深度学习神经网络实现手写字体识别

    利用平pytorch搭建简单的神经网络实现minist手写字体的识别,采用三层线性函数迭代运算,使得其具备一定的非线性转化与运算能力,其数学原理如下: 其具体实现代码如下所示:import torch ...

  6. [深度学习-1]神经网络-手写数字识别

    Date:2018年9月29记 数据及彭亮给出的数据集和源码在下面网址: https://github.com/mnielsen/neural-networks-and-deep-learning 在 ...

  7. 如何验签名真伪?法大大手写签名识别功能来了!

    以往,我们习惯以签名作为赋予文件法律效力的手段.传统的手写签名验证只需要对手写的静态笔迹与当事人以往的笔迹进行比对,即可检验签名真伪.那么,在电子签名盛行的无纸化办公时代,我们又该如何辨别手写电子签名 ...

  8. AI Studio 飞桨 零基础入门深度学习笔记6.3-手写数字识别之数据处理

    AI Studio 飞桨 零基础入门深度学习笔记6.3-手写数字识别之数据处理) 概述 前提条件 读入数据并划分数据集 扩展阅读:为什么学术界的模型总在不断精进呢? 训练样本乱序.生成批次数据 校验数 ...

  9. 【学习日记】手写数字识别及神经网络基本模型

    2021.10.7 [学习日记]手写数字识别及神经网络基本模型 1 概述 张量(tensor)是数字的容器,是矩阵向任意维度的推广,其维度称为轴(axis).深度学习的本质是对张量做各种运算处理,其分 ...

最新文章

  1. 赠书 | 联邦学习如何在视觉领域应用?
  2. 涌现:21世纪科学的统一主题
  3. 【BZOJ】1630: [Usaco2007 Demo]Ant Counting(裸dp/dp/生成函数)
  4. Fibonacci in the Pocket
  5. 上海有哪些计算机技术专科学校,上海计算机专业大学排名,第一名居然是这所大学!...
  6. repr方法字符串输出实例对象的值
  7. 浪潮业务稳定连续性获Global Data唯一“Leader”评级 蝉联数据中心整体能力“Very Strong”评级
  8. JimuReport积木报表1.3.3 版本发布,可视化报表工具
  9. golang 代理地址
  10. 城池俱坏,英雄安在?云龙几度相交代?想兴衰,^
  11. [UI界面]-UIWindow
  12. 转:卷积神经网络_(1)卷积层和池化层学习
  13. vi/vim常用命令积累
  14. Linux学习手册大全
  15. 直播APP源码开发,直播APP源码搭建,如何优化程序?
  16. android ios9 rom,谁说安卓不如苹果?看Android7.0如何逆袭iOS9.3
  17. scrapy爬虫折腾系列-02
  18. java实现ln10_Java数学函数
  19. centos 7, 8 的区别
  20. matlab中左移右移如何表示,汇编语言SHLD(双精度左移)和SHRD(双精度右移)指令...

热门文章

  1. 可能是国内最火的开源项目 —— C/C++ 篇
  2. TML5 App 开发框架收集
  3. 开发中很实用的10个效果
  4. 做好开源项目 需要坚持
  5. Windows平台下搭建Git服务器的图文教程
  6. 阿里java规范_阿里Java规范
  7. python调用opengl_python的opengl操作
  8. php点广告送积分,PHP猜一猜奇偶商城积分促销模式
  9. Yahoo Programming Contest 2019 E - Odd Subrectangles
  10. 创建向导时为其添加path,指为jar添加到path里面