幼敏悟过人,读书辄成诵。这篇文章主要讲述深度学习实战之手写签名识别(100%准确率语音播报)相关的知识,希望能为你提供帮助。
【深度学习实战之手写签名识别(100%准确率语音播报)】 手写签名在日常生活中随处可见,简单来说就是亲笔书写自己的名字,在纸质文档上使用手写签名主要用以确定签字者的身份,并表示签字者同意所签署文档中规定的内容,对文档的真实性负责,且具有法律效力。由此看见手写签名的重要性。在现实的生活中不乏有不法分子模仿其他人的字体,进而模仿他人的签名获得不发的利益。尽管会有鉴别字体的工作,但在鉴别时不仅不准确,而且还十分的消耗人力以及财力。为了解决这一客观显示存在的问题,笔者结合着人工智能的思想和并使用计算机视觉技术对手写签名进行训练,得到了高达100%的训练准确率。并将训练模型进行优化后运用实现了一套手写签名识别系统。1.开发环境笔者的开发环境如下,大家可以参考进行配置
- python3.6或python3.7
- pytorch1.0.1
- torchvision 0.2.2.post3
- visom
- ubuntu16.04和windows10
- 数据集的准备
文章图片
文章图片
- 数据集的划分
数据集划分为训练数据、验证数据、测试数据
其中训练数据、验证数据、测试数据的具体划分如下图所示
文章图片
- 载入数据
class Data(Dataset):
def __init__(self,root,resize,mode):
super(Data,self).__init__()
# 保存参数
self.root=root
self.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) + out
out = F.relu(out)
return out
class 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
推荐阅读
- OSPF多域配置
- 5个实用的PDF自动化办公操作~1行Python代码搞定(解密加水印PPT/Word/TxT转PDF)
- OSPF多区域间配置
- java WebSocket 即时通讯服务端代码
- 《处理电脑故障必要技能——备份与恢复WiFi配置》
- 第一篇博文福利新人博主,快来get你的专属福利
- Java 获取Excel分页坐标位置(单元格)
- Java 8之后的那些新特性(局部变量var)
- iptables防火墙filter表控制扩展匹配nat表典型应用