【K210】K210学习笔记七——使用K210拍摄照片并在MaixHub上进行训练
前言
本人大四学生,电赛生涯已经走到尽头,一路上踩过不少坑,但运气也不错拿了两年省一,思来想去,决定开始写博客,将电赛经验分享一二,能力有限,高手轻喷。 往期的博客讲述了 K210 的感光元件模块 sensor 的配置,机器视觉模块 image 中部分函数的使用(目前是用 find_blobs 函数实现一些寻找不同颜色的目标点,寻找不同颜色的线,后面会更新更多 image 模块中的函数使用方法),按键、LCD、LED的使用,定时器的使用,串口通信的方法,以及如何使用MaixHub平台在线训练模型。
sensor 的学习笔记传送门 【K210】K210学习笔记一——sensor image 的学习笔记传送门 【K210】K210学习笔记二——image 按键、LCD、LED的使用 的学习笔记传送门 【K210】K210学习笔记三——按键、LCD、LED的使用 定时器的使用传送门 【K210】K210学习笔记四——定时器的使用 串口通信传送门 【K210】K210学习笔记五——串口通信 MaixHub在线模型训练传送门 【K210】K210学习笔记六——MaixHub在线模型训练识别数字
串口通信(往期)传送门 【串口通信】K210与STM32串口通信、K210与OpenMV串口通信
本文着重于如何使用K210拍摄图片,并将图片上传到MaixHub平台进行模型训练。补充一下一些经验心得,比如一些训练参数的设置。
K210准备工作
由于K210的RAM只有8M,为了让运行的模型可以更大,避免出现内存不够的情况,需要刷入小一点的固件,固件及刷固件工具如下,我设置的是0积分免费下载。 固件烧入 将压缩包解压,点开kflash文件夹,双击运行程序。 在打开的程序中点击打开文件,然后选择要刷入的固件。 然后点击下载即可开始刷入固件。
K210如何拍摄照片
准备工作
这里需要用到SD卡,首先需要用读卡器打开SD卡,在SD卡根目录下创建一个名为img的文件夹。 然后将SD卡直接插到K210上即可。
拍摄相关代码定义
导入模块,这里打算用K210上自带的按键KEY进行拍照(该按键自动接到16脚),所以除了必要的感光元件模块以外,还需要引入引脚注册模块,lcd是方便脱机拍照(代码烧入后,可以拿个充电宝或者其他的可以输出5V电压的给K210供电,就可以拿着K210拍照了,不然还要带个笔记本电脑怪麻烦的)。
import sensor, time, image
import utime
from fpioa_manager import fm
from Maix import GPIO
import lcd
感光元件的设置,比起之前的设置,只是多了倒数第二行的设置图像大小为224 x 224。
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_auto_exposure(0)
sensor.set_auto_gain(0, gain_db = 16)
sensor.set_auto_whitebal(0)
sensor.set_vflip(1)
sensor.set_hmirror(1)
sensor.set_windowing((224,224))
sensor.skip_frames(time = 2000)
LED的设置,这一步可以没有,我只是用来判断按键有没有被按下才加的这个,我设置的是,如果按键按下的话,LED会切换。
fm.register(14, fm.fpioa.GPIO2, force = True)
fm.register(13, fm.fpioa.GPIO1, force = True)
fm.register(12, fm.fpioa.GPIO0, force = True)
LED_R = GPIO(GPIO.GPIO2, GPIO.OUT)
LED_G = GPIO(GPIO.GPIO1, GPIO.OUT)
LED_B = GPIO(GPIO.GPIO0, GPIO.OUT)
def LED_Control(led_flag):
if led_flag == 0:
LED_R.value(0)
LED_G.value(0)
LED_B.value(0)
elif led_flag == 1:
LED_R.value(1)
LED_G.value(1)
LED_B.value(1)
elif led_flag == 2:
LED_R.value(0)
LED_G.value(1)
LED_B.value(1)
elif led_flag == 3:
LED_R.value(1)
LED_G.value(0)
LED_B.value(1)
elif led_flag == 4:
LED_R.value(1)
LED_G.value(1)
LED_B.value(0)
else:
LED_R.value(0)
LED_G.value(1)
LED_B.value(0)
按键的设置,和往期一样的,只是把另外三个按键删掉了而已,然后在按键0的回调函数中加入了拍照函数。
class Key_Control():
cnt = 0
cs = 0
csmax = 0
csflag = 0
cinput = 0
control = 0
img_cnt = 0
key = Key_Control()
key.csmax = 3
fm.register(16, fm.fpioa.GPIOHS0, force = True)
KEY0 = GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP)
def Key0_Switch(KEY0):
utime.sleep_ms(10)
if KEY0.value() == 0:
key.csflag = 1
if key.cs < key.csmax:
key.cs = key.cs + 1
else:
key.cs = 0
Get_Image(key)
KEY0.irq(Key0_Switch, GPIO.IRQ_FALLING)
拍照函数如下所示,主要就是根据计数器的值保存照片,可以支持保存0000.jpg到9999.jpg共1万张照片,如果你要保存超过1万张,再加个判断就好了(emm应该也没有什么电赛题目识别的东西需要这么大的数据集吧)
def Get_Image(key):
if key.img_cnt < 10:
sensor.snapshot().save("/sd/img/000"+str(key.img_cnt)+".jpg")
elif key.img_cnt < 100:
sensor.snapshot().save("/sd/img/00"+str(key.img_cnt)+".jpg")
elif key.img_cnt < 1000:
sensor.snapshot().save("/sd/img/0"+str(key.img_cnt)+".jpg")
elif key.img_cnt < 10000:
sensor.snapshot().save("/sd/img/"+str(key.img_cnt)+".jpg")
key.img_cnt = key.img_cnt + 1
然后就是LCD的设置,这一步最好要有,有了会比较方便,还可以在LCD上看到当前拍摄了几张图片(第一行img_cnt后面显示的数字就是拍摄照片的张数)
lcd.init()
def LCD_Show():
lcd.draw_string(0, 0, "img_cnt: "+str(key.img_cnt), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 15, "Gain : "+str(sensor.get_gain_db()), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 30, "RGBGain: "+str(sensor.get_rgb_gain_db()), lcd.BLUE, lcd.WHITE)
主函数如下所示,key.img_cnt这一句话是设置从第几个序号开始保存照片,举个例子。 比如设置为0,那么就是从0000开始保存。 设置为100,就是从0100开始保存。 这一个设置的目的就是,方便后续添加数据集,比如我现在只拍摄了31张图片,那么img文件夹里面的照片是从0000.jpg到0030.jpg,如果要添加新。的数据集,那么需要将key.img_cnt的值改成31,就可以从0031.jpg开始保存,如果从0000开始的话会覆盖掉之前的照片。
key.img_cnt = 0
while(True):
clock.tick()
img=sensor.snapshot()
lcd.display(img)
LCD_Show()
LED_Control(key.cs)
完整代码如下,可以复制然后用K210拍摄你的数据集了!
import sensor, time, image
import utime
from fpioa_manager import fm
from Maix import GPIO
import lcd
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_auto_exposure(0)
sensor.set_auto_gain(0, gain_db = 16)
sensor.set_auto_whitebal(0)
sensor.set_vflip(1)
sensor.set_hmirror(1)
sensor.set_windowing((224,224))
sensor.skip_frames(time = 2000)
clock = time.clock()
fm.register(14, fm.fpioa.GPIO2, force = True)
fm.register(13, fm.fpioa.GPIO1, force = True)
fm.register(12, fm.fpioa.GPIO0, force = True)
LED_R = GPIO(GPIO.GPIO2, GPIO.OUT)
LED_G = GPIO(GPIO.GPIO1, GPIO.OUT)
LED_B = GPIO(GPIO.GPIO0, GPIO.OUT)
def LED_Control(led_flag):
if led_flag == 0:
LED_R.value(0)
LED_G.value(0)
LED_B.value(0)
elif led_flag == 1:
LED_R.value(1)
LED_G.value(1)
LED_B.value(1)
elif led_flag == 2:
LED_R.value(0)
LED_G.value(1)
LED_B.value(1)
elif led_flag == 3:
LED_R.value(1)
LED_G.value(0)
LED_B.value(1)
elif led_flag == 4:
LED_R.value(1)
LED_G.value(1)
LED_B.value(0)
else:
LED_R.value(0)
LED_G.value(1)
LED_B.value(0)
class Key_Control():
cnt = 0
cs = 0
csmax = 0
csflag = 0
cinput = 0
control = 0
img_cnt = 0
key = Key_Control()
key.csmax = 3
fm.register(16, fm.fpioa.GPIOHS0, force = True)
KEY0 = GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP)
def Key0_Switch(KEY0):
utime.sleep_ms(10)
if KEY0.value() == 0:
key.csflag = 1
if key.cs < key.csmax:
key.cs = key.cs + 1
else:
key.cs = 0
Get_Image(key)
KEY0.irq(Key0_Switch, GPIO.IRQ_FALLING)
def Get_Image(key):
if key.img_cnt < 10:
sensor.snapshot().save("/sd/img/000"+str(key.img_cnt)+".jpg")
elif key.img_cnt < 100:
sensor.snapshot().save("/sd/img/00"+str(key.img_cnt)+".jpg")
elif key.img_cnt < 1000:
sensor.snapshot().save("/sd/img/0"+str(key.img_cnt)+".jpg")
elif key.img_cnt < 10000:
sensor.snapshot().save("/sd/img/"+str(key.img_cnt)+".jpg")
key.img_cnt = key.img_cnt + 1
lcd.init()
def LCD_Show():
lcd.draw_string(0, 0, "img_cnt: "+str(key.img_cnt), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 15, "Gain : "+str(sensor.get_gain_db()), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 30, "RGBGain: "+str(sensor.get_rgb_gain_db()), lcd.BLUE, lcd.WHITE)
key.img_cnt = 0
while(True):
clock.tick()
img=sensor.snapshot()
lcd.display(img)
LCD_Show()
LED_Control(key.cs)
用K210拍摄到的照片在MaixHub平台上训练模型
因为手头上刚刚好有一个橘子,所以我就用它来做一个识别水果的(但我只做了一个识别橘子),将K210上电,然后对着橘子,按下KEY键即可拍照了。 然后,要用读卡器打开K210上的SD卡,将文件夹img复制到电脑桌面。 然后打开MaixHub平台,链接如下,账号没注册的注册一个就好(上一期有说) MaixHub在线训练平台 需要新建一个项目,名称就叫水果识别,类型选择图像检测(图像分类只能分类图像,并不能获取目标的坐标信息,因此图像检测用的比较多) 然后创建一个数据集,命名为水果。 然后选中该数据集。 然后将img中的图片上传到该训练集。 然后这一步是上一篇教程中所没有的,需要随机选择几张图片放到验证集中,因为如果验证集中没图片,训练的时候会随机抽取几张图片放到验证集。 然后就是添加标签,设置默认标签,然后一张张开始打标签了。 直到打完所有标签,就可以开始训练了。 训练参数设置如下,这里随机处理中的选项都不选(随机镜像、随机旋转、随机模糊),模型选择nncase,参数是训练200次,批数据量大小是4,然后创建任务即可。 然后需要记住训练的ID,不然后面找不到。 因为是在线训练,不妨我们再创建一个任务,这次将图像增强中的随即部分全部勾选上,其他参数不变,再创建一个训练任务,最后与之前的训练任务比较一下。 同样的需要记住训练ID。 等待训练结束,可以看到,平台告诉我们准确率有1,但是在K210上未必每次都能正确识别到,因为我这里数据量太小了,就拍摄了四十几张图片,镜头拉近拉远可能就无法识别了,如果对镜头到目标的距离有要求的,可以根据实际情况靠近或者远一点拍摄图片。 数据增强的那个训练任务也完成了,可以看到,这个训练的准确度比没数据增强的高出不少。 然后就是下载压缩包,进行测试了。
测试
首先要将压缩包内的模型复制到SD卡中,这里我复制了两个,一个是48,一个是50,48是没有数据增强的,50是有数据增强的。 然后打开48的测试代码测试即可。 记得将这两个参数设置为1哦,这是开启镜头转置。
未开启数据增强的测试结果
未开启数据增强的(序号48)的测试结果不难看出,概率偏低,这是因为我拍摄的大部分图片角度都差不多是同一个角度,因此可能我测试的时候角度换了一点,概率就下降了。 拿在手上的测试结果也不太理想,经常无法识别。
开启数据增强的测试结果
可以看出,概率明显上升了不少。 拿在手上,识别的效果也会比没开启数据增强的好上不少。 由此可得出,若需要提高识别的精准度,需要开启数据增强,如果开启数据增强后效果还是不理想,则需要增大数据集。
小结
使用K210拍摄照片,在MaixHub平台进行模型训练的教程已经做完了,并且分析了下数据增强对实际测试效果的影响。由于我并不是专门学这方面的,因此我感觉我这篇教程还写的不是很好,有新的心得的话,后面我会持续更新的。 下一期主要说怎么将识别到的坐标通过串口通信传输到STM32,因为这里用的代码是MaixHub平台提供的,我需要将其中用得到的部分加入我之前的代码中,然后通过串口通信发送出去,主要是为了方便大家使用,我想让大家可以轻松的搞应用,在各种比赛拿奖,总之我的比赛之路是走到尽头了,就是想将这些经验传承下去吧!下期再见咯!
|