K210学习笔记(十一)——MaixHub在线训练模型(在线炼丹)

K210学习笔记(十一)——MaixHub在线训练模型(在线炼丹),第1张

文章目录
  • 前言
  • 一、MaixHub功能介绍
  • 二、Maixhub模型训练使用方法
  • 三、图片采集
  • 四、标注数据集(目标分类跳过这一步)
  • 五、打包数据集
  • 六、上传数据集进行训练
  • 总结


前言

个人觉得K210与openmv最大的区别就是可以跑模型了,虽然不能跑yolov5得这类大型模型,但是还是可以使用一些yolov2、Mobilenet V1等轻量化模型。

一、MaixHub功能介绍

想要训练一个可用得模型,奈何电脑显卡不给力,没关系,我们可以使用Spieed的MaixHub模型在线训练来训练模型。Maixhub 模型训练平台帮助大家快速训练想要的 AI模型, 不需要任何训练环境搭建和代码运行, 只需要选择训练类型,上传(标注)数据集, Maixhub就会自动进行训练,训练结束后下载即可。
MaixHub目前有两种训练:
1、目标分类
识别图片所属的种类,只是识别出图片的种类,并没有显示识别物体的坐标(没有框出来),比如:
2、目标检测
既能识别出物体,又能将识别到的物体的坐标输出出来(框出来),比如:

二、Maixhub模型训练使用方法

首先要确定自己需要训练那种模型,如果只是要识别出物体,那就先目标分类,如果既要识别出物体类别,还要输出识别到的物体坐标,那就选择目标检测。
确定分类。 包括分类数量, 具体分类。 比如这里以识别红色小球和玩具为例:


所以共两个分类: ball 和 toy, 我们也称之为标签(label),
注意!!! 分类名(标签/label)只能使用英文字符和下划线

确定分辨率:以下为Maixhub目前支持的分辨率,其它分辨率将会训练失败(使用推荐分辨率识别准确率更高):

目标分类: 224x224(推荐)

目标检测: 224x224(推荐), 240x240

确定采集数据集数量:另外也要满足 Maixhub 的要求:

目标分类: 每类图片数量不低于40张,比如采集 200 张

目标检测: 每类图片数量不低于100张, 比如采集200张
上限为2000张

最后要注意上传的zip文件不能超过20MiB

三、图片采集

采集图片有以下几种方式:
1、使用开发板采集到SD卡, 直接采集成需要的分辨率 (推荐)
2、使用现成的图片, 使用预处理工具处理成需要的分辨率, 注意, 处理完后一定要手动检查数据是否符合要求, 不然可能影响训练精准度
3、手机拍照, 然后使用预处理工具处理成需要的分辨率, 注意, 处理完后一定要手动检查数据是否符合要求, 不然可能影响训练精准度

使用开发板进行数据采集
因为之前已经了解了MAIX BIT的拍照原理,所以这里我们主要是用开发板来采集图片。
使用这个脚本来进行采集图片

#根据你的开发板修改摄像头和屏幕配置, 比如lcd.rotation
#准备一张支持 SPI 模式的 SD 卡, 分区为 MBR (msdos), 格式化为 FAT32
#将目录下的boot.py文件拷贝到 SD 卡根目录
#开发板断电, 将SD卡插入开发板
#开发板上电, 程序会自动创建一个目录cap_images_1, 下次上电会创建cap_images_2, 这样就避免了覆盖
#采集一个分类的图片 按开发板上的boot按键,然后松开按键来采集一张图片, 这会将图片保存到cap_images_1/0/0.jpg, 采集的图片的名字会自动增长, 比如0.jpg 1.jpg ...
#长按boot按键切换类别目录 这会创建一个新目录,比如cap_images_1/1/, 后面采集的图片都会被保存到这个新的目录, 比如cap_images_1/1/0.jpg
#开发板断电,取出SD卡插到电脑, 打开文件管理器就可以看到采集的图片了
import sensor, lcd
from Maix import GPIO
from fpioa_manager import fm
from board import board_info
import os, sys
import time
import image

#### image size ####
set_windowing = (224, 224)       

#### sensor config ####

sensor.reset(freq=22000000, dual_buff=False)
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA) # 320x240
try:
    sensor.set_jb_quality(95)         # for IDE display quality
except Exception:
    pass # no IDE support
if set_windowing:
    sensor.set_windowing(set_windowing)

sensor.skip_frames()

#### lcd config ####
lcd.init(type=1, freq=15000000)
lcd.rotation(2)

#### boot key ####
boot_pin = 16 # board_info.BOOT_KEY
fm.register(boot_pin, fm.fpioa.GPIOHS0)
key = GPIO(GPIO.GPIOHS0, GPIO.PULL_UP)

######################################################

#### main ####
def capture_main(key):
    def draw_string(img, x, y, text, color, scale, bg=None , full_w = False):
        if bg:
            if full_w:
                full_w = img.width()
            else:
                full_w = len(text)*8*scale+4
            img.draw_rectangle(x-2,y-2, full_w, 16*scale, fill=True, color=bg)
        img = img.draw_string(x, y, text, color=color,scale=scale)
        return img

    def del_all_images():
        os.chdir("/sd")
        images_dir = "cap_images"
        if images_dir in os.listdir():
            os.chdir(images_dir)
            types = os.listdir()
            for t in types:
                os.chdir(t)
                files = os.listdir()
                for f in files:
                    os.remove(f)
                os.chdir("..")
                os.rmdir(t)
            os.chdir("..")
            os.rmdir(images_dir)

    # del_all_images()
    os.chdir("/sd")
    dirs = os.listdir()
    images_dir = "cap_images"
    last_dir = 0
    for d in dirs:
        if d.startswith(images_dir):
            if len(d) > 11:
                n = int(d[11:])
                if n > last_dir:
                    last_dir = n
    images_dir = "{}_{}".format(images_dir, last_dir+1)
    print("save to ", images_dir)
    if images_dir in os.listdir():
        img = image.Image()
        img = draw_string(img, 2, 200, "please del cap_images dir", color=lcd.WHITE,scale=1, bg=lcd.RED)
        lcd.display(img)
        sys.exit(1)
    os.mkdir(images_dir)
    last_cap_time = 0
    last_btn_status = 1
    save_dir = 0
    save_count = 0
    os.mkdir("{}/{}".format(images_dir, save_dir))
    while(True):
        img0 = sensor.snapshot()
        if set_windowing:
            img = image.Image()
            img = img.draw_image(img0, (img.width() - set_windowing[0])//2, img.height() - set_windowing[1])
        else:
            img = img0.copy()
        # img = img.resize(320, 240)
        if key.value() == 0:
            time.sleep_ms(30)
            if key.value() == 0 and (last_btn_status == 1) and (time.ticks_ms() - last_cap_time > 500):
                last_btn_status = 0
                last_cap_time = time.ticks_ms()
            else:
                if time.ticks_ms() - last_cap_time > 5000:
                    img = draw_string(img, 2, 200, "release to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)
                else:
                    img = draw_string(img, 2, 200, "release to capture", color=lcd.WHITE,scale=1, bg=lcd.RED)
                    if time.ticks_ms() - last_cap_time > 2000:
                        img = draw_string(img, 2, 160, "keep push to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)
        else:
            time.sleep_ms(30)
            if key.value() == 1 and (last_btn_status == 0):
                if time.ticks_ms() - last_cap_time > 5000:
                    img = draw_string(img, 2, 200, "change object type", color=lcd.WHITE,scale=1, bg=lcd.RED)
                    lcd.display(img)
                    time.sleep_ms(1000)
                    save_dir += 1
                    save_count = 0
                    dir_name = "{}/{}".format(images_dir, save_dir)
                    os.mkdir(dir_name)
                else:
                    draw_string(img, 2, 200, "capture image {}".format(save_count), color=lcd.WHITE,scale=1, bg=lcd.RED)
                    lcd.display(img)
                    f_name = "{}/{}/{}.jpg".format(images_dir, save_dir, save_count)
                    img0.save(f_name, quality=95)
                    save_count += 1
                last_btn_status = 1
        img = draw_string(img, 2, 0, "will save to {}/{}/{}.jpg".format(images_dir, save_dir, save_count), color=lcd.WHITE,scale=1, bg=lcd.RED, full_w=True)
        lcd.display(img)
        del img
        del img0


def main():
    try:
        capture_main(key)
    except Exception as e:
        print("error:", e)
        import uio
        s = uio.StringIO()
        sys.print_exception(e, s)
        s = s.getvalue()
        img = image.Image()
        img.draw_string(0, 0, s)
        lcd.display(img)
main()

采集好图片后,将SD卡中的图片拷贝到电脑, 整理成下面的目录结构, 所有图片的分辨率为224x224

四、标注数据集(目标分类跳过这一步)

注意: 一定要先保证分辨率正确, 再标注
有两种标注方式,一种是vott(击这里下载),另一种是labelimg(点击这里下载 )。这里我标注主要是用labelimg进行标注(注意:labelimg的路径不能有中文,不然会闪退)。


保存后会生成xml格式的文件(即PascalVOC格式),每张图对应一个xml文件。完成后目录结构和文件如下:

或者两级目录

五、打包数据集

将前面处理好的数据集进行打包, 使用zip压缩,暂不支持其它格式, 而且文件不要超过20MiB。
目标分类:
一个文件夹一个分类, 分类名(标签/label)就是文件夹名

目标检测:
labelimg 的输出zip文件结构,新建了一个labels.txt, 输入标记的标签, 每行一个(这是必须的, 否则数据无效), 比如这里:

然后目录结构如下

或者两级labelimg输出

六、上传数据集进行训练





如果进度一直是0%可以刷新一下,训练完成后点击Download就可以下载训练文件。 下载文件是一个zip压缩文件, 解压后仔细阅读README.txt,使用了中英文对使用方法进行了说明,默认是在有最新版固件的情况下, 将结果文件全部拷贝到SD卡根目录, 断电插入开发板, 然后上电就可以运行了。(注意:提交数据集格式一定要争取,不然会报错不能训练)

总结

以上就是MaixHub在线训练模型大致过程,整体下来还是比较简单的,建议是先进行一次物体分类的训练再进行物体检测的训练。
常见问题:
1、物体分类训练完成后运行训练文件,发现识别到了物体,但是显示的是其它物体的名称,这个时候可以更改boot.py里面的labels的顺序。

labels = ["Recyclable_waste_out", "Other_waste", "Kitchen_waste", "Hazardous_waste_out"]

2、…有待补充…

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/788506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存