赞
踩
个人觉得K210与openmv最大的区别就是可以跑模型了,虽然不能跑yolov5得这类大型模型,但是还是可以使用一些yolov2、Mobilenet V1等轻量化模型。
想要训练一个可用得模型,奈何电脑显卡不给力,没关系,我们可以使用Spieed的MaixHub模型在线训练来训练模型。Maixhub 模型训练平台帮助大家快速训练想要的 AI模型, 不需要任何训练环境搭建和代码运行, 只需要选择训练类型,上传(标注)数据集, Maixhub就会自动进行训练,训练结束后下载即可。
MaixHub目前有两种训练:
1、目标分类
识别图片所属的种类,只是识别出图片的种类,并没有显示识别物体的坐标(没有框出来),比如:
2、目标检测
既能识别出物体,又能将识别到的物体的坐标输出出来(框出来),比如:
首先要确定自己需要训练那种模型,如果只是要识别出物体,那就先目标分类,如果既要识别出物体类别,还要输出识别到的物体坐标,那就选择目标检测。
确定分类。 包括分类数量, 具体分类。 比如这里以识别红色小球和玩具为例:
所以共两个分类: 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、…有待补充…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。