【深度学习系列】用PaddlePaddle进行车牌识别(二)
上节我们讲了第一部分,如何用生成简易的车牌,这节课中我们会用PaddlePaddle来识别生成的车牌。
数据读取
在上一节生成车牌时,我们可以分别生成训练数据和测试数据,方法如下(完整代码在这里):
# 将生成的车牌图片写入文件夹,对应的label写入label.txt
def genBatch(self, batchSize,pos,charRange, outputPath,size):
if (not os.path.exists(outputPath)):
os.mkdir(outputPath)
outfile = open('label.txt','w')
for i in xrange(batchSize):
plateStr,plate = G.genPlateString(-1,-1)
print plateStr,plate
img = G.generate(plateStr);
img = cv2.resize(img,size);
cv2.imwrite(outputPath + "/" + str(i).zfill(2) + ".jpg", img);
outfile.write(str(plate)+"\n")
生成好数据后,我们写一个reader来读取数据 ( reador.py )
def reader_creator(data,label):
def reader():
for i in xrange(len(data)):
yield data[i,:],int(label[i])
return reader
灌入模型时,我们需要调用paddle.batch函数,将数据shuffle后批量灌入模型中:
# 读取训练数据
train_reader = paddle.batch(paddle.reader.shuffle(
reador.reader_creator(X_train,Y_train),buf_size=200),
batch_size=16) # 读取验证数据
val_reader = paddle.batch(paddle.reader.shuffle(
reador.reader_creator(X_val,Y_val),buf_size=200),
batch_size=16)
trainer.train(reader=train_reader,num_passes=20,event_handler=event_handler)
构建网络模型
因为我们训练的是端到端的车牌识别,所以一开始构建了两个卷积-池化层训练,训练完后同步训练7个全连接层,分别对应车牌的7位字符,最后将其拼接起来,与原始的label计算Softmax值,预测训练结果。
def get_network_cnn(self):
# 加载data和label
x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(self.data))
y = paddle.layer.data(name='y', type=paddle.data_type.integer_value(self.label))
# 构建卷积-池化层-1
conv_pool_1 = paddle.networks.simple_img_conv_pool(
input=x,
filter_size=12,
num_filters=50,
num_channel=1,
pool_size=2,
pool_stride=2,
act=paddle.activation.Relu())
drop_1 = paddle.layer.dropout(input=conv_pool_1, dropout_rate=0.5)
# 构建卷积-池化层-2
conv_pool_2 = paddle.networks.simple_img_conv_pool(
input=drop_1,
filter_size=5,
num_filters=50,
num_channel=20,
pool_size=2,
pool_stride=2,
act=paddle.activation.Relu())
drop_2 = paddle.layer.dropout(input=conv_pool_2, dropout_rate=0.5) # 全连接层
fc = paddle.layer.fc(input = drop_2, size = 120)
fc1_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc1 = paddle.layer.fc(input = fc1_drop,size = 65,act = paddle.activation.Linear()) fc2_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc2 = paddle.layer.fc(input = fc2_drop,size = 65,act = paddle.activation.Linear()) fc3_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc3 = paddle.layer.fc(input = fc3_drop,size = 65,act = paddle.activation.Linear()) fc4_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc4 = paddle.layer.fc(input = fc4_drop,size = 65,act = paddle.activation.Linear()) fc5_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc5 = paddle.layer.fc(input = fc5_drop,size = 65,act = paddle.activation.Linear()) fc6_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc6 = paddle.layer.fc(input = fc6_drop,size = 65,act = paddle.activation.Linear()) fc7_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc7 = paddle.layer.fc(input = fc7_drop,size = 65,act = paddle.activation.Linear()) # 将训练好的7个字符的全连接层拼接起来
fc_concat = paddle.layer.concact(input = [fc21, fc22, fc23, fc24,fc25,fc26,fc27], axis = 0)
predict = paddle.layer.classification_cost(input = fc_concat,label = y,act=paddle.activation.Softmax())
return predict
训练模型
构建好网络模型后,就是比较常见的步骤了,譬如初始化,定义优化方法, 定义训练参数,定义训练器等等,再把第一步里我们写好的数据读取的方式放进去,就可以正常跑模型了。
class NeuralNetwork(object):
def __init__(self,X_train,Y_train,X_val,Y_val):
paddle.init(use_gpu = with_gpu,trainer_count=1) self.X_train = X_train
self.Y_train = Y_train
self.X_val = X_val
self.Y_val = Y_val def get_network_cnn(self): x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(self.data))
y = paddle.layer.data(name='y', type=paddle.data_type.integer_value(self.label))
conv_pool_1 = paddle.networks.simple_img_conv_pool(
input=x,
filter_size=12,
num_filters=50,
num_channel=1,
pool_size=2,
pool_stride=2,
act=paddle.activation.Relu())
drop_1 = paddle.layer.dropout(input=conv_pool_1, dropout_rate=0.5)
conv_pool_2 = paddle.networks.simple_img_conv_pool(
input=drop_1,
filter_size=5,
num_filters=50,
num_channel=20,
pool_size=2,
pool_stride=2,
act=paddle.activation.Relu())
drop_2 = paddle.layer.dropout(input=conv_pool_2, dropout_rate=0.5) fc = paddle.layer.fc(input = drop_2, size = 120)
fc1_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc1 = paddle.layer.fc(input = fc1_drop,size = 65,act = paddle.activation.Linear()) fc2_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc2 = paddle.layer.fc(input = fc2_drop,size = 65,act = paddle.activation.Linear()) fc3_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc3 = paddle.layer.fc(input = fc3_drop,size = 65,act = paddle.activation.Linear()) fc4_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc4 = paddle.layer.fc(input = fc4_drop,size = 65,act = paddle.activation.Linear()) fc5_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc5 = paddle.layer.fc(input = fc5_drop,size = 65,act = paddle.activation.Linear()) fc6_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc6 = paddle.layer.fc(input = fc6_drop,size = 65,act = paddle.activation.Linear()) fc7_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
fc7 = paddle.layer.fc(input = fc7_drop,size = 65,act = paddle.activation.Linear()) fc_concat = paddle.layer.concact(input = [fc21, fc22, fc23, fc24,fc25,fc26,fc27], axis = 0)
predict = paddle.layer.classification_cost(input = fc_concat,label = y,act=paddle.activation.Softmax())
return predict # 定义训练器
def get_trainer(self): cost = self.get_network() #获取参数
parameters = paddle.parameters.create(cost) optimizer = paddle.optimizer.Momentum(
momentum=0.9,
regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
learning_rate=0.001,
learning_rate_schedule = "pass_manual") # 创建训练器
trainer = paddle.trainer.SGD(
cost=cost, parameters=parameters, update_equation=optimizer)
return trainer # 开始训练
def start_trainer(self,X_train,Y_train,X_val,Y_val):
trainer = self.get_trainer() result_lists = []
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
if event.batch_id % 10 == 0:
print "\nPass %d, Batch %d, Cost %f, %s" % (
event.pass_id, event.batch_id, event.cost, event.metrics)
if isinstance(event, paddle.event.EndPass):
# 保存训练好的参数
with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
parameters.to_tar(f)
# feeding = ['x','y']
result = trainer.test(
reader=val_reader)
# feeding=feeding)
print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics) result_lists.append((event.pass_id, result.cost,
result.metrics['classification_error_evaluator'])) # 开始训练
train_reader = paddle.batch(paddle.reader.shuffle(
reador.reader_creator(X_train,Y_train),buf_size=200),
batch_size=16) val_reader = paddle.batch(paddle.reader.shuffle(
reador.reader_creator(X_val,Y_val),buf_size=200),
batch_size=16)
# val_reader = paddle.reader(reador.reader_creator(X_val,Y_val),batch_size=16) trainer.train(reader=train_reader,num_passes=20,event_handler=event_handler)
输出结果
上一步训练完以后,保存训练完的模型,然后写一个test.py进行预测,需要注意的是,在预测时,构建的网络结构得和训练的网络结构相同。
#批量预测测试图片准确率
python test.py /Users/shelter/test ##输出结果示例
output:
预测车牌号码为:津 K 4 2 R M Y
输入图片数量:100
输入图片行准确率:0.72
输入图片列准确率:0.86
如果是一次性只预测一张的话,在终端里会显示原始的图片与预测的值,如果是批量预测的话,会打印出预测的总准确率,包括行与列的准确率。
总结
车牌识别的方法有很多,商业化落地的方法也很成熟,传统的方法需要对图片灰度化,字符进行切分等,需要很多数据预处理的过程,端到端的方法可以直接将原始的图片灌进去进行训练,最后出来预测的车牌字符的结果,这个方法在构建了两层卷积-池化网络结构后,并行训练了7个全连接层来进行车牌的字符识别,可以实现端到端的识别。但是在实际训练过程中,仍然有一些问题,譬如前几个训练的全连接层的准确率要比最后一两个的准确率高,大家可以分别打印出每一个全连接层的训练结果准确率对比一下,可能是由于训练还没有收敛导致的,也可能有其他原因,如果在做的过程中发现有什么问题,或者有更好的方法,欢迎留言~
参考文献:
1.我的github:https://github.com/huxiaoman7/mxnet-cnn-plate-recognition
【深度学习系列】用PaddlePaddle进行车牌识别(二)的更多相关文章
- 【深度学习】用PaddlePaddle进行车牌识别(二)
上节我们讲了第一部分,如何用生成简易的车牌,这节课中我们会用PaddlePaddle来识别生成的车牌. 数据读取 在上一节生成车牌时,我们可以分别生成训练数据和测试数据,方法如下(完整代码在这里): ...
- 【深度学习系列】PaddlePaddle垃圾邮件处理实战(二)
PaddlePaddle垃圾邮件处理实战(二) 前文回顾 在上篇文章中我们讲了如何用支持向量机对垃圾邮件进行分类,auc为73.3%,本篇讲继续讲如何用PaddlePaddle实现邮件分类,将深度 ...
- 【深度学习系列】PaddlePaddle之手写数字识别
上周在搜索关于深度学习分布式运行方式的资料时,无意间搜到了paddlepaddle,发现这个框架的分布式训练方案做的还挺不错的,想跟大家分享一下.不过呢,这块内容太复杂了,所以就简单的介绍一下padd ...
- 【深度学习系列】手写数字识别卷积神经--卷积神经网络CNN原理详解(一)
上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...
- 【深度学习系列】PaddlePaddle垃圾邮件处理实战(一)
PaddlePaddle垃圾邮件处理实战(一) 背景介绍 在我们日常生活中,经常会受到各种垃圾邮件,譬如来自商家的广告.打折促销信息.澳门博彩邮件.理财推广信息等,一般来说邮件客户端都会设置一定的 ...
- 【深度学习系列】PaddlePaddle之数据预处理
上篇文章讲了卷积神经网络的基本知识,本来这篇文章准备继续深入讲CNN的相关知识和手写CNN,但是有很多同学跟我发邮件或私信问我关于PaddlePaddle如何读取数据.做数据预处理相关的内容.网上看的 ...
- 【深度学习系列】PaddlePaddle可视化之VisualDL
上篇文章我们讲了如何对模型进行可视化,用的keras手动绘图输出CNN训练的中途结果,本篇文章将讲述如何用PaddlePaddle新开源的VisualDL来进行可视化.在讲VisualDL之前,我们先 ...
- 【AI开发】基于深度学习的卡口车型、车牌识别
服务端代码后面给出 卡口车型.车牌识别demo截图 服务器:
- 【深度学习系列】关于PaddlePaddle的一些避“坑”技巧
最近除了工作以外,业余在参加Paddle的AI比赛,在用Paddle训练的过程中遇到了一些问题,并找到了解决方法,跟大家分享一下: PaddlePaddle的Anaconda的兼容问题 之前我是在服务 ...
- 【深度学习系列】用PaddlePaddle进行车牌识别(一)
小伙伴们,终于到了实战部分了!今天给大家带来的项目是用PaddlePaddle进行车牌识别.车牌识别其实属于比较常见的图像识别的项目了,目前也属于比较成熟的应用,大多数老牌厂家能做到准确率99%+.传 ...
随机推荐
- java中的异常类
Java中的异常: 1. Throwable是所有异常的根,java.lang.Throwable Throwable包含了错误(Error)和异常(Exception),Exception又包含了运 ...
- 创建python虚拟环境如果速度很慢
conda create -n jjenv python=3.6如果我们这样子创建的话下载速度很慢,那就可以用如下方式,相当于改了下载源. conda create -n jjenv python=3 ...
- Bootstrap 常用属性
一,关于按钮 btn系列 二.关于div 移动位置 col 系列 col-md 系列 col-lg系列 这些都是让多个div在当前页面等大小 三.居中系列 1.文本居中 text-center 2.图 ...
- CRT破解版
1.先去https://www.ttrar.com/html/VanDyke-SecureCRT.html上面下载一个CRT软件 2.下载一个注册机 http://www.ddooo.com/soft ...
- Unity进阶----AssetBundle_03(2018/11/07)
1. 为啥有AB包? 因为资源需要更新, 避免更新一次打包一次 动态修改. 2. AB包注意啥? 依赖关系 找依赖关系应该找到对应的平台!!! 3. 打包策略是分场景打包 若文件被文件夹包含打包出来的 ...
- 使用Apache服务部署静态网站
1970年,作为互联网前身的ARPANET(阿帕网)已初具雏形,并开始向非军用部门开放,许多大学和商业部门开始接入.虽然彼时阿帕网的规模(只有4台主机联网运行)还不如现在的局域网成熟,但是它依然为网络 ...
- js操作DOM对象
js操作DOM对象 (Document Object Model)文档对象模型 nodeType返回值 1:元素节点 2:属性节点 3:文本节点 8:注释节点 9: 文档节点 nodeName 节点 ...
- 脚本语言丨Batch入门教程第三章:逻辑判断
通过学习Batch入门教程的前两章内容,我们已经大致掌握了基本概念和认识变量的相关内容,今天我们要跟大家继续分享第三章内容:Batch入门教程之逻辑判断. 前期回顾 ◀Batch入门教程丨部署与H ...
- 中间人攻击——ARP欺骗的原理、实战及防御
1.1 什么是网关 首先来简单解释一下什么是网关,网关工作在OSI七层模型中的传输层或者应用层,用于高层协议的不同网络之间的连接,简单地说,网关就好比是一个房间通向另一个房间的一扇门. 1.2 A ...
- 微信小程序快速开发上手
微信小程序快速开发上手 介绍: 从实战开发角度,完整系统地介绍了小程序的开发环境.小程序的结构.小程序的组件与小程序的API,并提供了多个开发实例帮助读者快速掌握小程序的开发技能,并能自己动手开发出小 ...