基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置

本文介绍了一种基于嵌入式平台开发的图像识别部署装置,其主要功能包括实现机器与人的“猜拳博弈”,其组成分为三个部分:

  1. 手势检测数据集

  1. 图像识别模型训练

  1. 模型格式部署

  1. maixbit开发板部署

手势检测数据集:本项目的数据集包括三种标签:石头,剪刀,布。数据集采用的是自己采集,自行采集数据集有两个优点:1.对最终的部署于maixbit开发板进行识别更加具有针对性;2.可以任意控制数据集的数量。

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第1张图片

如上图所示:maixpy提供了线上的数据集制作平台,进行训练集以及验证集的编写,通过手动标注数据集,由于本项目中所使用的是图像分类的识别模型,不需要进行手动标注。

数据集的样本采集方式使用手机端进行直接的训练样本采集,上传至maixHub的后端服务器,图像样本以及对应的标签。

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第2张图片

选取模型进行模型的训练,使用的分类模型为mobilenet,进行数据集的拟合。

踩坑经验:数据集三种标签的样本采集数量应该严格相等,同时尽可能数量多,不低于80张采集样本图片。模型选择方面,仅支持官方推荐的几种模型,也是因为芯片的RAM较小,并且其中固件占据了太多部分的内存。

选择部署方式,本项目最终部署的平台是maixBit开发板,因此适用于nncase的部署方式,如果选择部署于树莓派与安卓平台时,可以选择ncnn的部署方式。

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第3张图片

配置项选择全部结束,创建训练任务,日志平台进行训练日志的监控,主要包括损失函数loss的下降趋势监控,以及模型acc准确率的显示等,训练完成的模型进行终端部署相关操作。

maixhub帮助我们实现了一个初步的推理代码,实现部署直接应用模型,即可实现调用maixbit开发进行模型的图像识别。

import sensor, image, lcd, time
import KPU as kpu
import gc, sys

input_size = (224, 224)
labels = ['cloth', 'Scissors', 'Stone']

def lcd_show_except(e):
    import uio
    err_str = uio.StringIO()
    sys.print_exception(e, err_str)
    err_str = err_str.getvalue()
    img = image.Image(size=input_size)
    img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
    lcd.display(img)

def main(labels = None, model_addr="/sd/m.kmodel", sensor_window=input_size, lcd_rotation=0, sensor_hmirror=False, sensor_vflip=False):
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing(sensor_window)
    sensor.set_hmirror(sensor_hmirror)
    sensor.set_vflip(sensor_vflip)
    sensor.run(1)

    lcd.init(type=1)
    lcd.rotation(lcd_rotation)
    lcd.clear(lcd.WHITE)

    if not labels:
        with open('labels.txt','r') as f:
            exec(f.read())
    if not labels:
        print("no labels.txt")
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "no labels.txt", color=(255, 0, 0), scale=2)
        lcd.display(img)
        return 1
    try:
        img = image.Image("startup.jpg")
        lcd.display(img)
    except Exception:
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "loading model...", color=(255, 255, 255), scale=2)
        lcd.display(img)

    try:
        task = None
        task = kpu.load(model_addr)
        while(True):
            img = sensor.snapshot()
            t = time.ticks_ms()
            fmap = kpu.forward(task, img)
            t = time.ticks_ms() - t
            plist=fmap[:]
            pmax=max(plist)
            max_index=plist.index(pmax)
            img.draw_string(0,0, "%.2f : %s" %(pmax, labels[max_index].strip()), scale=2, color=(255, 0, 0))
            img.draw_string(0, 200, "t:%dms" %(t), scale=2, color=(255, 0, 0))
            lcd.display(img)
    except Exception as e:
        raise e
    finally:
        if not task is None:
            kpu.deinit(task)


if __name__ == "__main__":
    try:
        # main(labels=labels, model_addr=0x300000)
        main(labels=labels, model_addr="/sd/model-26548.kmodel")
    except Exception as e:
        sys.print_exception(e)
        lcd_show_except(e)
    finally:
        gc.collect()

maixbit开发使用摄像头以及LCD屏幕进行图像的结果显示,包括实时视频检测的结果以及模型识别的推理时间,进行显示。

maix bit主板示意图如下图所示:

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第4张图片

maix bit开发板示意图

maix bit开发板的内部包含KPU神经网络处理器,类似华为的NPU芯片,可以加快模型的推理速度。

目前手上有可以识别石头剪刀布三种手势的模型设备,需要进行人机交互层面的实现工作。

选取上电运行的主界面图片:

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第5张图片

具体需要实现的交互功能为根据人的手势,识别其具体的手势类别,再做出相应的手势反应。

主界面的上电运行图片进行实际的切分,分为剪刀图片,石头图片以及布图片:

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第6张图片

三种手势图片

图片进行显示预处理,maix bit开发板的显示屏采用的LCD液晶显示屏,其如下图所示:

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第7张图片

其显示屏的参数对于项目的区别在于320x240的视频显示分辨率,因此其主界面的图片显示应调整分辨率为320x240的图像分辨率,这里使用的是画图软件,进行图片大小的调整。

部署模型Python代码如下所示:

import sensor, image, lcd, time
import KPU as kpu
import gc, sys
input_size = (224, 224)
labels = ['cloth', 'Scissors', 'Stone']
cloth_pic = "/sd/bu.jpg"
Scissors_pic = "/sd/jian.jpg"
Stone_pic = "/sd/shi.jpg"
def lcd_show_except(e):
    import uio
    err_str = uio.StringIO()
    sys.print_exception(e, err_str)
    err_str = err_str.getvalue()
    img = image.Image(size=input_size)
    img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
    lcd.display(img)
def main(labels = None, model_addr="", sensor_window=input_size, lcd_rotation=0, sensor_hmirror=False, sensor_vflip=False):
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing(sensor_window)
    sensor.set_hmirror(sensor_hmirror)
    sensor.set_vflip(sensor_vflip)
    sensor.run(1)
    lcd.init(type=1)
    lcd.rotation(lcd_rotation)
    lcd.clear(lcd.WHITE)
    try:
        img = image.Image("/sd/start.jpg")
        lcd.display(img)
        time.sleep(2)
        lcd.clear()
        img = image.Image(size=(320, 240))
        img.draw_string(80, 110, "Mora Guess Game", color=(255, 255, 255), scale=2)
        lcd.display(img)
        time.sleep(2)
    except Exception:
        img = image.Image(size=(320, 240))
        img.draw_string(50, 50, "model exception...", color=(255, 255, 255), scale=2)
        lcd.display(img)
    try:
        task = None
        task = kpu.load(model_addr)
        lcd.clear()
        while(True):
            img = sensor.snapshot()
            t = time.ticks_ms()
            if img is None or img == "":
                continue
            fmap = kpu.forward(task, img)
            t = time.ticks_ms() - t
            fps = 1000/t
            plist=fmap[:]
            pmax=max(plist)
            max_index=plist.index(pmax);
            img.draw_string(0,0, "%.2f: %s" %(pmax,labels[max_index].strip()), scale=2, color=(000, 0,255))
            img.draw_string(0, 200, "fps :%.1f" %(fps), scale=2, color=(0, 0, 255))
            lcd.display(img,roi=(0, 0, 160, 240), oft=(0, 0))
            if max_index == 0:
                Scissors = image.Image(Scissors_pic)
                lcd.display(Scissors,roi=(0, 0, 160, 240), oft=(160, 0))
            elif max_index == 1:
                Stone = image.Image(Stone_pic)
                lcd.display(Stone,roi=(0, 0, 160, 240), oft=(160, 0))
            elif max_index == 2:
                cloth = image.Image(cloth_pic)
                lcd.display(cloth,roi=(0, 0, 160, 240), oft=(160, 0))
    except Exception as e:
        raise e
    finally:
        if not task is None:
            kpu.deinit(task)
if __name__ == "__main__":
    try:
        main(labels=labels, model_addr="/sd/model-26548.kmodel")
    except Exception as e:
        sys.print_exception(e)
        lcd_show_except(e)
    finally:
        gc.collect()

maix bit可以外接SD卡配置,将进行显示所用的文件为了节约芯片的内存,将LCD屏幕的320x240的屏幕进行一分为二,因此以上三个手势图片分辨率为160x240。

进行视频显示视频流显示与模型处理结果进行分割,针对视频流采集的图片进行预测,进行模型的前向传播,获取各个预测标签对应的概率。获取最大的概率所对应的索引,输出对应的预测标签结果。

博弈操作的逻辑代码如下:

if max_index == 0:
    Scissors = image.Image(Scissors_pic)
    lcd.display(Scissors,roi=(0, 0, 160, 240), oft=(160, 0))
elif max_index == 1:
    Stone = image.Image(Stone_pic)
    lcd.display(Stone,roi=(0, 0, 160, 240), oft=(160, 0))
elif max_index == 2:
    cloth = image.Image(cloth_pic)
    lcd.display(cloth,roi=(0, 0, 160, 240), oft=(160, 0))

将图像识别的标签进行分布为[石头,布,剪刀],通过识别的图片结果,读取sd卡中的图像数据,在半个LCD显示屏进行操作结果的显示,以此类推。

如图为本智能设备的最终识别效果:

基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第8张图片
基于MaixBit(K210芯片)的图像识别猜拳手势博弈装置_第9张图片

以上为MaixBit(K210芯片)的图像识别猜拳手势博弈装置的最终效果,完整源代码通过关注我的公众号“千与编程”,有详细教程。其实这个项目是我一早就很想做的项目,现在也算完整完成了,做一个完整的项目,用编程改变世界加油!

我是千与千寻,我们下期见!

你可能感兴趣的:(深度学习模型压缩部署,机器学习,深度学习,人工智能)