AI模型部署到行空板学习笔记
本帖最后由 怀若谷 于 2023-2-28 21:22 编辑https://www.bilibili.com/video/BV14G4y1U75M/
演示视频
背景说明
刚刚过去的寒假,有幸参加了首届“新一代人工智能教师成长营”的学习。AI教师成长营课程由上海人工智能实验室智能教育中心AI科创教育顾问谢作如带领教研团队精心设计,内容包括人工智能的发展和应用、AI模型训练、模型转换与部署等,分为入门课程、进阶课程以及项目实践三个部分。以前本人做过的AI项目基本依赖AI三剑客——语音合成模块、语音识别模块、图像识别模块来完成。说句实话,这些模块就相当于创客器材中的传感器和执行器,使用者根本不需要掌握人工智能知识,也对人工智能学习产生不了多少影响,处于体验层面。而这次学习,让我了解了更专业的人工智能知识,特别是基于深度学习的人工智能应用。
项目实践环节我们小组完成了AI猜拳机器人项目。这个项目是大家熟知的项目,最早是由日本东京大学研制并发布的。我曾使用DFRobot的视觉传感器——二哈识图制作过一个。(项目链接:【HUSKYLENS Inside】AI猜拳机器人)虽然项目没有新意,最后的实现结果也差强人意,但是整个的制作过程仍能体现这次的学习成果。我想,把这个项目的制作过程记录下来,可以作为学习笔记供今后复习,如果他人能从中有所收获,那就更有意义啦。
使用的平台、软件及器材1. 浦育青少年人工智能开放创新平台OpenInnoLab(下称“平台”)平台网址:openinnolab.org.cn
2. Mind+软件下载地址:https://mindplus.cc
3. 器材:行空板*1 IO扩展板*1 SG90舵机*3USB摄像头*1
前置准备登录openinnolab.org.cn,进行注册。
新建项目——“AI猜拳机器人”
熟悉操作界面在平台上运行程序,需要先在“服务器运行环境”中选择启动“CPU版”或者“GPU版”。
制作流程
制作数据集—模型训练—推理测试—模型转换—应用部署—结构设计加工—组装调试
1. 制作数据集拍摄石头、剪刀、布三种手势的图片各200张,拍摄环境背景图片200张。拍照时,每张照片从拍摄角度、距离远近、光线强弱等方面进行调整,力求每张照片都是独一无二的。在本地电脑上建立一个文件夹“mypic”(名称可自拟),在里面建立4个子文件夹,将拍摄的照片按类别放在4个文件夹中,分别命名为“background”、“paper”、“rock”、“scissors”。
调用下面Python程序制作数据集(也可以手工进行分类整理),可生成ImageNet格式的数据集。该程序可在平台运行,也可以在本地的Python编程软件中运行。【源程序可在附件中下载】
------------------------------------------------------------------------------------------------------------------path=input(r'请输入您的数据集地址,如E:\人工智能教师成长营\mypic') #执行后,输入文件夹“mypic”在本地的路径
train_rate=float(input('请输入训练集的比例大小,范围是0-1,如0.8')) #一般按8:1:1的比例分配给训练集、验证集、测试集,即输入0.8、0.1、0.1
val_rate=float(input('请输入验证集的比例大小,范围是0-1,如0.1'))
test_rate=float(input('请输入测试集的比例大小,范围是0-1,如0.1'))
import os
save_path=(input('请输入需要保存的路径,默认为'+os.getcwd()+'\my_dataset')) #可以不填,默认保存在文件夹“mypic”中
import shutil
# 列出指定目录下的所有文件名,确定分类信息
classes = os.listdir(path)
# 定义创建目录的方法
def makeDir(folder_path):
if not os.path.exists(folder_path):# 判断是否存在文件夹如果不存在则创建为文件夹
os.makedirs(folder_path)
# 指定文件目录
read_dir = path+'/' # 指定原始图片路径
if save_path=='':
save_path=os.getcwd()+'\my_dataset'
else:
save_path+='\my_dataset'
train_dir = save_path+r'\training_set\\' # 指定训练集路径
val_dir = save_path+r'\val_set\\'# 指定验证集路径
test_dir = save_path+r'\test_set\\'# 指定测试集路径
for cnt in range(len(classes)):
r_dir = read_dir + classes + '/'# 指定原始数据某个分类的文件目录
files = os.listdir(r_dir)# 列出某个分类的文件目录下的所有文件名
offset1 = int(len(files) * train_rate)
offset2 = int(len(files) * (train_rate+val_rate))
training_data = files[:offset1]
val_data = files
test_data = files
# 根据拆分好的文件名新建文件目录放入图片
for index,fileName in enumerate(training_data):
w_dir = train_dir + classes + '/'# 指定训练集某个分类的文件目录
makeDir(w_dir)
shutil.copy(r_dir + fileName, w_dir + str(index) + '.jpg')
for index,fileName in enumerate(val_data):
w_dir = val_dir + classes + '/'# 指定测试集某个分类的文件目录
makeDir(w_dir)
shutil.copy(r_dir + fileName, w_dir + str(index) + '.jpg')
for index,fileName in enumerate(test_data):
w_dir = test_dir + classes + '/'# 指定验证集某个分类的文件目录
makeDir(w_dir)
shutil.copy(r_dir + fileName, w_dir + str(index) + '.jpg')
print('转换完成,请到'+save_path+'查看')
------------------------------------------------------------------------------------------------------------------------------
2.模型训练
2.1 上传数据集
打开项目,选择“项目文件”,点击上传按钮,以“上传目录”的方式将制作好的本地数据集“my_dataset”上传到项目文件中(也可以上传到数据集中)。
2.2 上传预训练模型文件
点击上传按钮,以“上传文件”的方式将获得的预训练模型权重文件上传到项目文件中,可自行建立目录。使用预训练模式进行训练,可以获得较理想的效果。
2.3 编写训练程序
以“上传文件”的方式导入训练程序文件,也可以自行新建文件后手动输入代码。
------------------------------------------------------------------------------------------------------------------------------
from MMEdu import MMClassification as cls# 导入库
model = cls(backbone='MobileNet') #项目实例化
model.num_classes = 4 # 设置种类数,该项目种背景和手势共4类
model.load_dataset(path='my_dataset') # 数据集路径
model.save_fold = 'checkpoints/cls_model' # 权重文件保存路径
checkpoint = 'checkpoints/pre_model/Pre-trained.pth' # 预训练模型路径,如果从0开始训练,该行代码可删除
model.train(epochs=50, lr=0.01, batch_size=4,validate=True,checkpoint = checkpoint)#训练模型,如果不采用预训练模型,checkpoint = checkpoint可删除
------------------------------------------------------------------------------------------------------------------------------
2.4 启动程序训练
启动容器,点击“运行”,运行程序。
到权重文件保存路径下查看训练日志。
当训练轮数太多时,可及时删除不是最佳的训练模型文件,已节省存储空间。
3.推理测试
3.1编写推理程序
以“上传文件”的方式导入推理程序文件,也可以自行新建文件后手动输入代码。
------------------------------------------------------------------------------------------------------
from MMEdu import MMClassification as cls# 导入库
model = cls(backbone='MobileNet') #项目实例化
model.num_classes = 4 # 类别数,该项目中共4类
checkpoint = 'checkpoints/cls_model/best_accuracy_top-1_epoch_30.pth'# 权重文件路径,训练出来的最佳结果
class_path = 'my_dataset/classes.txt' # 类型说明文件路径,训练后在“my_dataset”路径下自动生成
img_path = 'test_pic/8.jpg'# 测试图片路径,图片可上传到项目文件中,也可以利用数据集中的测试图片
result = model.inference(image=img_path,show=True, class_path=class_path,checkpoint = checkpoint) #进行推理
model.print_result(result)#显示推理结果
------------------------------------------------------------------------------------------------------
3.2运行程序
运行程序,查看推理结果。
如果置信度不理想,可以返回训练环节继续训练或者修改数据集。
4.模型转换
模型经过推理验证,符合预期后,需要将平台上能否运行的模型转换为能在开源硬件运行的模型。
4.1 编写模型转换程序
以“上传文件”的方式导入模型转换程序文件,也可以自行新建文件后手动输入代码。
--------------------------------------------------------------------------------------------------------------
!pip install onnx
!pip install onnxruntime
!pip install onnxsim
from MMEdu import MMClassification as cls
model = cls(backbone='MobileNet')
model.num_classes = 4
checkpoint = 'checkpoints/cls_model/best_accuracy_top-1_epoch_30.pth'
out_file="out_file/ImageNet1k.onnx"#存放模型转换结果文件路径
model.convert(checkpoint=checkpoint, backend="ONNX", out_file=out_file, class_path='my_dataset/classes.txt')
-----------------------------------------------------------------------------------------------------------------
4.2 运行转换程序
点击“运行”按钮运行程序。
模型转换成功后,在输出结果文件夹下可以看到“ImageNet1k.onnx”和“ImageNet1k.py” 两个文件。其中ImageNet1k.onnx”为模型文件,ImageNet1k.py”为应用示例程序。
4.3 下载相关文件
部署到硬件上需要用到转化结果的两个文件“ImageNet1k.onnx”、“ImageNet1k.py”和项目文件中的“BaseData.py”。
可以手工单个下载,也可以编写程序进行打包下载。
程序如下:
------------------------------------------------------------------------------------------------------
!tar -cvf AI猜拳机器人.tar BaseData.py./out_file
------------------------------------------------------------------------------------------------------
运行程序后,项目文件中会生成一个文件“AI猜拳机器人.tar”,将其下载到本地后解压。
5.应用部署
5.1 硬件搭建
将行空板插在扩展板的插槽中;三个舵机分别连接到P2、P3、P10引脚;USB摄像头插入行空板的USB口。
5.2 编写程序
5.2.1 连接设备
将行空板连接电脑
打开Mind+软件,切换到“Python模式”
开启远程连接终端后,连接IP为10.1.2.3的远程终端
5.2.2 上传文件
将“ImageNet1k.onnx”、“ImageNet1k.py”和“BaseData.py”三个文件上传到行空板,注意存放路径。
5.2.3 新建主程序文件
新建一个主程序“main.py”, 将示例程序“ImageNet1k.py”中的代码复制到主程序中。
5.2.4 完善主程序
根据应用需求,完善程序。
------------------------------------------------------------------------------------
import cv2
import BaseData
import onnxruntime as rt
import numpy as np
from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from pinpong.board import Board
from pinpong.board import Servo
import time
Board().begin()
#初始化舵机引脚,设置初始角度15°
servo1 = Servo(Pin((Pin.P2)))
servo1.write_angle(15)
time.sleep(1)
servo2 = Servo(Pin((Pin.P3)))
servo2.write_angle(15)
time.sleep(1)
servo3 = Servo(Pin((Pin.P10)))
servo3.write_angle(15)
screen_rotation = True
cap = cv2.VideoCapture(0)# 设置摄像头编号,如果只插了一个USB摄像头,基本上都是0
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)# 设置摄像头图像宽度
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)# 设置摄像头图像高度
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)# 设置OpenCV内部的图像缓存,可以极大提高图像的实时性。
cv2.namedWindow('camera', cv2.WND_PROP_FULLSCREEN)# 窗口全屏
cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)# 窗口全屏
sess = rt.InferenceSession('out_file/ImageNet1k.onnx', None)
input_name = sess.get_inputs()[0].name
out_name = sess.get_outputs()[0].name
cnt = 4
global idx
idx = 0
tag =['backgroup','paper', 'rock', 'scissors']
def onnx_cls(img):
dt = BaseData.ImageData(img, size=(224, 224))
input_data = dt.to_tensor()
pred_onx = sess.run(, {input_name: input_data})
result = np.argmax(pred_onx[0], axis=1)[0]
return result
while cap.isOpened():
success, image = cap.read()
cnt = cnt - 1
if not success:
print("Ignoring empty camera frame.")
break
if screen_rotation:# 是否要旋转屏幕
image = cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE)# 旋转屏幕
if cnt == 0:
idx = onnx_cls(image)
if idx == 1:
servo2.write_angle(100)
time.sleep(2)
servo2.write_angle(15)
else:
if idx == 2:
servo3.write_angle(100)
time.sleep(2)
servo3.write_angle(15)
else:
if idx == 3:
servo1.write_angle(100)
time.sleep(2)
servo1.write_angle(15)
#print('result:' + tag)
cnt = 4
#cv2.putText(image, tag, (0, 40), cv2.FONT_HERSHEY_TRIPLEX, 1, (150, 0, 180), 1)
cv2.imshow('camera',image)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
-----------------------------------------------------------------------------------------------
相较于示例程序,本程序增加了行空板屏幕图像显示、预测结果显示及多模态交互模块。这个环节比较考验编程能力,对Python编程及开源硬件控制不熟悉的人来说,比较困难,我就是一个!!!
6.结构设计加工6.1 绘制图纸
使用二维建模软件进行结构及外型的绘制
6.2 切割制件
使用激光切割机切割加工椴木板
7.组装调试
将木件及电子模块组装起来,进行反复调试。
写在最后
这次学习经历是难忘的,因为期间遇到了很多问题,经历了无从下手的时刻。由于花的时间有限,上面的项目也是在囫囵吞枣式的消化后完成的。如有不当之处,望朋友们指正!
不错不错 好好学习天天向上 喜欢,很好的案例 如何获取权重文件呢 arcshubag 发表于 2024-8-7 16:30
如何获取权重文件呢
有存放路径的,到里面下载即可
页:
[1]