前言
模型训练部分已在上篇介绍:
https://www.jianshu.com/p/22b691696d53
本章将主要讲述如何将模型导入到单片机里,实时地根据摄像头读取的信息,经过我们的网络输出后反馈到单片机,控制输出的高低电平,从而实现温度控制。
设备介绍
我们使用了一款叫做角蜂鸟的可以外接在树莓派的神经网络加速器,它的神经网络计算部分是基于movidius芯片,而且有个大大的好处就是,一般模型转化还需要movidius神经计算棒,而角峰鸟貌似是自带此模块的,可以直接调用相应接口就能实现模型转换。
角峰鸟
树莓派也不用多介绍了,很有名的一块板子
树莓派(左)角峰鸟(右)
上图中,左边是树莓派,右边是角峰鸟,可以看到角峰鸟自带了摄像头,导入进去后直接通过接口调取自带摄像头就好了。
不过要在树莓派上调用角峰鸟,需要事先配置好角峰鸟运行环境
git clone --recursive https://github.com/HornedSungem/SungemSDK-Python.git
git clone https://github.com/HornedSungem/SungemSDK-Python.git
cd SungemSDK-Python
git submodule update --init --recursive # 初始化并更新子模块
模型转换
按照官方的说法,角峰鸟只支持caffe和tensorflow模型,刚好我们的模型符合条件,模型转换接口如下
python3 mvNCCompile.py network # network 为模型文件,如 *.prototxt(Caffe)* 或 *.meta(Tensorflow)*
-h # 显示帮助信息
-w WEIGHTS # 模型权重文件(Caffe), 如 *.caffemodel*
-in INPUTNODE # 输入节点名称,默认Caffe为 *data*, TF为 *input*
-on OUTPUTNODE # 输出节点名称,默认Caffe为最后一层,TF为 *output*
-o OUTFILE # 输出HS Graph路径
-s NSHAVES # 使用Movidius的Shave数量,建议为8,默认为1
-is INPUTSIZE INPUTSIZE # 更改输入网络尺寸,默认为网络输入尺寸。
把之前保存的四个文件meta、index、checkpoint等拉到指定目录,在tool目录下打开命令行,或者cd到tool目录,根据接口的的用法输入对应语句
$ python3 mvNCCompile.py -s 8 ./example/baby_6_26/baby.ckpt-79.meta -in input -on softmax_output -o graph_baby_6_26
注意这里的in和on 就是之前tensorflow模型里面定义的输入和输出节点的名字,分别对应节点为xs,prediction_softmax。
然而万万没想到的是,转换报错了:
Erro:you can not feed a number with type[?,128,128,3]:first dimension must be 1
这才想起来了我们定义xs这个placeholder的时候为了图方便,把格式定义成了
xs = tf.placeholder(tf.float32, [None, 128, 128,3], name = 'input') # 128x128
第一维是None,而这个模型转换只支持第一维是1.
关于转换失败的解决方法
这个问题看起来挺好解决的,但实际操作起来挺让人抓狂的,各种方法都不奏效,甚至卡了我整整一星期·····
用restore重载训练好的参数
首先我想着利用把之前训练好的模型参数,重写一个一样结构的网络,但xs的维度设置为一维
xs = tf.placeholder(tf.float32, [1, 128, 128,3], name = 'input') # 128x128
用save.restore的方式,重新加载网络的参数,就像以前用迁移学习的方法加载预训练的vgg-16网络参数一样,然而不知为何总是失败,也不知道是哪一步写错了,反正最后没走通。
换用mini-batch
后来又想了一个办法,重新换用Mini-batch的思想训练我们的网络,只不过这次每个batch只有一个样本。然而还是失败了,每步训练的loss严重震荡,在正样本时变为0.3,负样本时又突然上升到1.4...
突然意识到可能是优化器的学习率设置太大了,所以每一步训练的长迈的过大,导致一直在局部最优头顶跨来跨去,因此把学习率从1e-4改到1e-5
train_step = tf.train.AdamOptimizer(1e-5).minimize(_loss)
结果证明可行,很好地收敛了
训练结果
将重新训练的模型再次导入树莓派,调用模型转换接口,这次终于转换成功了,获得了转换后的graph文件。
但还是有点想不通的是,之前学习吴恩达机器学习的课程时,说到了mini-batch和full-batch是可以采用一样步长的,mini-batch虽然训练过程会绕来绕去,最终会和full-batch收敛到同一处。
然而我们此例如果不修改步长则会无法收敛,想不明白是什么原因··但总归收敛了,等项目做完了再回头琢磨
紫线mini-batch/蓝线full-batch
调用模型
将刚才生成的graph文件保存在转化模型的统一文件夹里,可以调用角峰鸟的api来开始识别了
首先包含好需要的头文件,记得需要包含接口的头文件hspai,和opencv的头文件cv2,因为需要在输出界面做一些操作
import cv2, numpy, sys
sys.path.append('../../../')
import hsapi as hs # 导入 hsapi 模块, 注意导入路径
设置预处理参数,就是归一化参数了,因为我们是(0~1)范围的归一化,只需要每个像素值乘以0.007843/2就行了,不需要偏移
scale = 0.007843/2 # 图像预处理参数
mean = 0 # 图像预处理参数
开启相机,读取模型
device_list = hs.EnumerateDevices() # 获取所有已连接的角蜂鸟
device = hs.Device(device_list[0]) # 获取Device实例
device.OpenDevice() # 打开角蜂鸟设备
with open('/home/pi/SungemSDK-GraphModels/graphs/graph_baby_6_26', mode='rb') as f:
data = f.read()
graph = device.AllocateGraph(data, scale, mean) # 获取Graph实例
之后相机就会对每张读取的参数进行操作,使用while true循环
try:
while True:
# 使用自带摄像头作为输入
image = graph.GetImage(True) # 用角蜂鸟设备图像作为神经网络输入
size=image.shape
cx=int(size[0]/2)
cy=int(size[1]/2)
dx=int(size[0]*0.3)
dy=int(size[1]*0.3)
output, _ = graph.GetResult() # 获取神经网络输出结果
if output[0] >0.5:
label='baby is covered'
else:
label='baby is not covered'
cv2.putText(image,label,(cy-dy, cx-int(dx*1.1)),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,255),2)
print(output)
cv2.rectangle(image,(cy-dy, cx-dx), (cy+dy, cx+dx),(255,255,0),5)
cv2.imshow("baby_recgonition", image)
cv2.waitKey(1)
finally:
graph.DeallocateGraph() # 释放神经网络资源
device.CloseDevice() # 关闭角蜂鸟设备
上面的output就是图像输入模型得到的输出
output, _ = graph.GetResult() # 获取神经网络输出结果
然后我们需要对输出作翻译,利用opencv将翻译结果输出到屏幕上
if output[0] >0.5:
label='baby is covered'
else:
label='baby is not covered'
cv2.putText(image,label,(cy-dy, cx-int(dx*1.1)),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,255),2)
print(output)
再画一个框,来显示识别的区域,我们先前定义cx,cx,dx,dy就是框的位置和大小
cv2.rectangle(image,(cy-dy, cx-dx), (cy+dy, cx+dx),(255,255,0),5)
cv2.imshow("baby_recgonition", image)
cv2.waitKey(1)
模型嵌入的代码请移步至我的github:https://github.com/huangchuhccc/baby_recognition_by_Horned_sungem_using_tensorflow
最终识别演示如下
https://v.youku.com/v_show/id_XNDI1MDAzOTc0OA==.html?spm=a2h3j.8428770.3416059.1
后续又实现了利用婴儿是否入睡的判定与微信的实时提醒,请移步这篇博客:
https://www.jianshu.com/p/45918d2ed025
网友评论