上次仔爸尝试过在行空板部署ONNX轻量模型并实现图像的分类识别,这次借着参加DFROBOT的树莓派活动,将这个项目从行空板移植到树莓派上。
ONNX 的全称是“Open Neural Network Exchange”,即“开放的神经网络切换”,旨在实现不同神经网络开发框架之间的互通互用。ONNXRuntime是微软推出的一款推理框架,支持多种运行后端包括CPU,GPU,TensorRT,DML等,是对ONNX模型最原生的支持。“mobilenetv2.onnx”为使用MMEdu训练并转换的“ImageNet1000分类”数据集模型。在MMEdu中,可以用model对象的convert方法来转换。本模型的数据集介绍(1000种分类哦):https://zhuanlan.zhihu.com/p/522690833
一、使用到的硬件器材
树莓派4B x1
USB免驱摄像头 x1
有道小图灵主控板(M5Core) x1
二、部署环境
首先我们需要在树莓派上安装操作系统,这个本篇不再赘述,可自行参考树莓派官网相关教程。然后将USB免驱摄像头(我使用的是罗技摄像头)插入到树莓派的USB口。
在树莓派的系统中,分别通过pip安装以下python扩展模块: onnxruntime, opencv-python, pillow, microblocks_wifi_radio
使用下面的命令更新一下pip版本
pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple/
安装扩展模块命令:
pip install 模块名
在梅莓派用户目录下,创建一个onnx的文件夹,将准备好的onnx数据集文件和BaseData.py文件(此文件由上海人工智能实验室编写及提供)复制过来。
三、程序编写
本程序共分二部分,首先是树莓派上运行的主程序,由python编写,实现USB摄像头拍照并进行推理。第二部分编写在有道小图灵主控板上,通过WIFI广播与树莓派之间的通信,遥控树莓派,实现远距离控制的功能。
1.在树莓派上编写python程序,并保存在onnx文件夹下,命名为main.py
主程序实现的功能是,运行程序后,等待M5Core主控板按键,如按下A键,开始拍照并进行一次推理,然后将推理的结果显示在图片上。按下B键,退出主程序。
import onnxruntime as rt #用于使用onnx模型
import BaseData #即项目文件夹下的BaseData.py文件
import numpy as np
import cv2 #opencv-python模块,用于使用摄像头
import time
from PIL import Image,ImageDraw,ImageFont #图像显示与处理
from microblocks_wifi_radio import Radio #WiFi广播
def get_tag(path): #获取识别后的标签,即对应Imagenet1000中的某个序号
with open(path,'r',encoding='utf-8') as f:
tag=[e.rstrip("\n") for e in f.readlines()]
return tag
def infer(img,pth,backbone): #使用权重文件pth和网络backbone对img图像进行推理
sess=rt.InferenceSession(pth,None)
input_name=sess.get_inputs()[0].name
out_name=sess.get_outputs()[0].name
dt=BaseData.ImageData(img,backbone=backbone)
input_data=dt.to_tensor()
pred_onx=sess.run([out_name],{input_name:input_data})
ort_output=pred_onx[0]
print(ort_output)
idx=np.argmax(ort_output,axis=1)[0]
return [idx,ort_output[0][idx]]
tag=get_tag('cls/dataset/imagenet.txt') #标签文件
backbone='MobileNet' #使用网络
pth='cls/checkpoints/mobilenetv2_output.onnx' #模型文件
r=Radio()
while True:
time.sleep(0.1)
if r.message_received(): #判断是否接收到WiFi广播消息
msg = r.last_string #将最新收到的字符串消息存入变量
print(msg)
if msg=="recognize": #如果接收到的消息是recognize,则开始拍照并推理
print("start recognize...")
time.sleep(1)
cap=cv2.VideoCapture(0) #调用外接USB摄像头
ret,frame=cap.read() #拍一张照片
cv2.imwrite('test1.jpg',frame) #将拍摄的照片存储成文件
idx,acc=infer(frame,pth,backbone)#进行一次推理
print('result:'+tag[idx]+',and acc:'+str(acc))
text = tag[idx] #将推理文字写入照片左上角
img = Image.open('test1.jpg')
width,heigh=img.size
draw = ImageDraw.Draw(img)
font = ImageFont.truetype('FreeSans.ttf',36)
textwidth,textheigh=draw.textsize(text,font)
margin = 10
draw.text((margin,margin),text,font=font,fill=(255,0,0))
img.show()
time.sleep(2)
cap.release() #释放摄像头资源
#cv2.destroyAllWindows()
if msg == "exit": #接收到exit则退出
print('exit now')
break
在调试运行中,发现onnx的数据集出现了版本新和旧的问题,如下图,通过网上查找,从github上下载一个remove_initializer_from_imput.py文件,对数据集文件进行了转换。
要解决这个问题,方法一是升级到最新版的onnx,然后重新把pytorch模型转换为onnx模型,因为我们是直接拿来现成的模型文件,因此采用方法二,使用下面的命令进行转换:
python remove_initializer_from_input.py --input mobilenetv2.onnx --output mobilenetv2_output.onnx
2.在有道小图灵上编写MicroBlocks程序
最近在学习和研究MicroBlocks软件,所以在本项目中,尝试使用MicroBlocks编写遥控端程序,通过WiFi广播的方式,来控制树莓派上的程序。需要确保树莓派和有道小图灵在同一网段(连接相同的路由器即可)。
步骤一:打开MicroBlocks软件,单击连接按钮,通过串口连接。连接成功后,连接按钮出现绿色圆形。
步骤二:单击积木库右侧的“+”,在弹出的对话框中选择“网络”文件夹,再在网络中选择“WiFi广播”扩展模块,这样就会在左侧扩展积木库列表中显示“WiFi广播”。
步骤三:编程程序。程序主要由三个程序块组成。当启动程序时,连接WiFi网络,并进行相应的提示。另外两个按键程序实现按下A或B键发送相应的WiFi广播,并提示。
四、运行和调试
接下来我们测试一下程序,在树莓派上运行python程序,程序等待遥控按键,按下A键,开始拍照,并进行一次推理,然后弹出一个新窗口显示拍摄的照片,并将推理结果的文字显示在左上角。
单击观看演示视频
后记
通过这次DF的活动,总算把吃灰多年的树莓派给用了起来,因为之前用过ubuntu系统,所以树莓派系统上手还是比较简单的,安装软件就使用“sudo apt install 软件名”这样的命令进行安装。
此外,本项目还尝试通过WiFi模式进行两个设备之间远距离的通信,可应用于很多项目,如智能家居类,学校各种智慧项目等。
由于本项目附件超过10M,无法上传,可联系仔爸(V:xdh-pc)索取。