V831本地训练详解及踩坑指南
V831本地训练
提示:看这篇文章前最好先看一遍官方说明,v831的配置只要不是我这种倒霉蛋,一般都是很好配置的,跟着官方文档就能配好
##############################################################################################################
下载源码
官方网址非常慢要翻墙
##############################################################################################################
配置环境
推荐先搞anaconda,搞个虚拟环境,养成好习惯
- python版本3.6以上的应该都可以,以下的没测试过,我最后使用的是3.9的,可以考虑3.8,印象里3.8配置的最快,资源包搜索的很快且安装后面2个包没有小插曲.
- pytorch安装,30系显卡选11以上的
- pip3 install torchsummary pycocotools opencv-python opencv-contrib-python
##############################################################################################################
nncn模型转换工具
编译完之后如果在任意目录下运行:
onnx2ncnn
如果报错找不到命令.
这边提供3个方法
1.想办法把官网的教程里加路径的搞懂,反正我没看懂也没实践出来
2.直接把要转换的文件丢到和onnx2ncnn可执行文件同一个目录下
也就是对应的这个目录下打开终端输入
./onnx2ncnn 需要转换的yolo模型.onnx 转换出来的你想要的文件名.param 转换出来的你想要的文件名.bin
3.直接把onnx2ncnn这个可执行文件cp到/usr/bin里(推荐)
这种方法好处是简单除暴,也不需要在环境变量中加新的环境变量.在当前目录输入
sudo cp onnx2ncnn /usr/bin
##############################################################################################################
照片拍摄
因为我有01家的k210,上面有按键,所以可以按键拍摄,如果是官方的k210,可以采用1s1次自动拍摄,或者用杜邦线一次次短路按键脚口来拍照
ps1:我这个代码会报错,但是不管三七二十一,上电后掉电重启一次,就可以用
ps2:关于摄像头方向和lcd方向的技巧:先调整到开发板怎么转,lcd显示都是符合人的主观的,之后每转90°拍一张照片.
然后掉电把sd卡取下,看一下4张图里有一张图是真正正着的,这样就确定了应该怎么拿'照相机'
拍照代码
#要注意照片实际效果和LCD的显示,多试几次,通过更改sensor.set_vflip(1) 和lcd.rotation(0),甚至还有镜像等
import sensor, lcd, utime
from Maix import GPIO
from fpioa_manager import fm
#注册KEY的外部IO
fm.register(16, fm.fpioa.GPIOHS0, force=True)
#构建KEY对象
KEY=GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP)
#摄像头初始化
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.QVGA) # or sensor.QVGA (or others)
sensor.skip_frames(30) # Let new settings take affect.
sensor.set_windowing((224,224)) # 设置图片大小为224*224(训练需要224的图片,提前转换好)
sensor.set_vflip(1) #摄像头后置模式(0或1)
#LCD初始化
lcd.init()
lcd.rotation(0) # 屏幕旋转(0~3)
key_node = 0 #按键标志位
name_num = 0 #照片名字
##############################################
# 按键和其回调函数
##############################################
def fun(KEY):
global key_node
utime.sleep_ms(10) #消除抖动
if KEY.value()==0: #确认按键被按下
key_node = 1
#开启中断,下降沿触发
KEY.irq(fun, GPIO.IRQ_FALLING)
while True:
lcd.display(sensor.snapshot()) # LCD实时显示
if key_node==1: #按键被按下
key_node = 0 #清空按键标志位
#拍照并保存,保存文件用时间来命名。
lcd.display(sensor.snapshot().save("/sd/"+str(name_num)+".jpg"))
name_num=name_num+1 #名字编码加1
print("Done! Reset the camera to see the saved image.")
#延时0.5秒,观看拍摄图片
utime.sleep_ms(500)
#############################################################################################################
制作数据集
labelimg下载网上资料很多,这里不多说了.
小tip:左边有个标注模式选择一定要选PascalVOC模式.view菜单栏里有自动保存模式,A上一张,D下一张,W开始标注,右边点击使用预设标签,我这边标的是冰墩墩就叫bdd了.
标注完之后
1.来到v831_yolo-master/data/custom/annotations_cache里把所有文件删了,这是缓存数据,如果同一批数据集可以不删,但是如果换数据集了要删除
2.退回到Annotations里放入刚刚标注好的xml文件
3.往JPEGImages里放入图片
4.进入ImageSets/Main
在这个目录制作一个python脚本(代码内容在下方),并运行:
python auto_create.py --first 0 --finish 304 --interval 9
PS:如果没有用我的拍照代码,train.txt和val.txt请自行制作
第一个参数是第一张图片,如果使用我上面的拍照代码,那就是从0 开始
我拍了305张,最后一张是304,所以第二个参数填304,验证集一般取10%左右,第三个参数我填9
之后会生成一个train.txt和val.txt
# coding=utf-8
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--first', default=0, type=int, help='第一个数据集的名字')
parser.add_argument('--finish', default=10, type=int, help='最后一个数据集的名字')
parser.add_argument('--interval',default=5, type=int, help='间隔多少采集一个作为一个验证集')
arg = parser.parse_args()
start = arg.first
last = arg.finish
interval = arg.interval
t = open('train.txt','w')
v = open('val.txt','w')
train_number = 0
val_number = 0
for i in range(start,last+1):
if i % interval == 0:
val_number+=1
v.write(str(i)+'\n')
else:
train_number+=1
t.write(str(i)+'\n')
print('start:%d\nfinish:%d\ntrain_number:%d\nval_number:%d\n'%(start,last,train_number,val_number))
- 修改配置
修改 data/custom.py 中的 CUSTOM_CLASSES 变量为正确的 labels
# CUSTOM_CLASSES = [
# "mouse",
# "sipeed_logo"
# ]
CUSTOM_CLASSES = [
"bdd"
]
##############################################################################################################
训练
正常人弄完就可以开始训练了,并且一般训练了就出结果了
在v831_yolo-master下输入
python3 train.py -d custom --cuda -v slim_yolo_v2 -hr -ms
然后等待训练结束就可以在/v831_yolo-master/weights/custom下找到练出来的参数了
但是我一直有问题,如果你也有问题,可以看看我改的内容.
我一共改了3个地方
第二张图这里本来是32,我是3070,改为了16,再垃圾点的算力改为8就差不多了
第三张图片默认是10,要改为比config.py的max_epoch大才能完成全部训练.
不知道哪里出的问题,一进入检查就报错,但是我确定我的数据集,环境配置是没什么问题的,估计是什么很坑人的坑了,所以我直接不进行检查了
##############################################################################################################
模型转换
python3 test.py -d custom -v slim_yolo_v2 --trained_model weights/custom/slim_yolo_v2/slim_yolo_v2_260.pth --visual_threshold 0.3 -size 224 --export
运行导出模型命令后会在 out 目录下生成
那么这一步如果出现报错
那就跳回到nncn模型转换工具,只要你的转换工具安装没问题,那就可以用我的方法
加工完之后还要再加工一次变成awnn
进入maixhub
工具箱里的模型转换,选择NCNN,RGB,然后按照要求打包文件,上传
要求如下:
也就是2个由转换工具转换出来的bin和param文件加上一个验证数据集,这个数据集从训练的图片里选或者再拍摄一些,当然要确保拍摄手法一致,大约50张.
然后进行压缩,压完上传,进行转换.转换完之后下载下来的文件中有bin和param就是我们需要的模型了.
##############################################################################################################
模型部署
按照历程去模型部署,官网代码我这里也贴出来把
from maix import nn, display, camera, image
from root.classes_label import labels #分类标签,根据个人需求自行替换
import time
model = {
"param": "/root/restnet18_int8.param", #模型文件,需要替换成自己训练的模型路劲
"bin": "/root/restnet18_int8.bin"
}
options = {
"model_type": "awnn",
"inputs": {
"input0": (224, 224, 3)
},
"outputs": {
"output0": (1, 1, len(labels))
},
"first_layer_conv_no_pad": False,
"mean": [127.5, 127.5, 127.5],
"norm": [0.00784313725490196, 0.00784313725490196, 0.00784313725490196],
}
print("-- load model:", model)
m = nn.load(model, opt=options)
print("-- load ok")
while True:
img = camera.capture()
AI_img = img.copy().resize(224, 224)
t = time.time()
out, = m.forward(AI_img, quantize=True)
t = time.time() - t
print("-- forward time: {}s".format(t))
msg = "{}%: {}".format(int(out.max() * 10), labels[out.argmax()])
print(msg)
img.draw_string(0, 0, msg, color = (255, 0, 0))
display.show(img)