贵州交通建设集团有限公司网站百度快速收录接口
本文介绍了一种基于嵌入式平台开发的图像识别部署装置,其主要功能包括实现机器与人的“猜拳博弈”,其组成分为三个部分:
手势检测数据集
图像识别模型训练
模型格式部署
maixbit开发板部署
手势检测数据集:本项目的数据集包括三种标签:石头,剪刀,布。数据集采用的是自己采集,自行采集数据集有两个优点:1.对最终的部署于maixbit开发板进行识别更加具有针对性;2.可以任意控制数据集的数量。

如上图所示:maixpy提供了线上的数据集制作平台,进行训练集以及验证集的编写,通过手动标注数据集,由于本项目中所使用的是图像分类的识别模型,不需要进行手动标注。
数据集的样本采集方式使用手机端进行直接的训练样本采集,上传至maixHub的后端服务器,图像样本以及对应的标签。

选取模型进行模型的训练,使用的分类模型为mobilenet,进行数据集的拟合。
踩坑经验:数据集三种标签的样本采集数量应该严格相等,同时尽可能数量多,不低于80张采集样本图片。模型选择方面,仅支持官方推荐的几种模型,也是因为芯片的RAM较小,并且其中固件占据了太多部分的内存。
选择部署方式,本项目最终部署的平台是maixBit开发板,因此适用于nncase的部署方式,如果选择部署于树莓派与安卓平台时,可以选择ncnn的部署方式。

配置项选择全部结束,创建训练任务,日志平台进行训练日志的监控,主要包括损失函数loss的下降趋势监控,以及模型acc准确率的显示等,训练完成的模型进行终端部署相关操作。
maixhub帮助我们实现了一个初步的推理代码,实现部署直接应用模型,即可实现调用maixbit开发进行模型的图像识别。
import sensor, image, lcd, time
import KPU as kpu
import gc, sysinput_size = (224, 224)
labels = ['cloth', 'Scissors', 'Stone']def lcd_show_except(e):import uioerr_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 1try: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 = Nonetask = kpu.load(model_addr)while(True):img = sensor.snapshot()t = time.ticks_ms()fmap = kpu.forward(task, img)t = time.ticks_ms() - tplist=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 efinally: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主板示意图如下图所示:

maix bit开发板示意图
maix bit开发板的内部包含KPU神经网络处理器,类似华为的NPU芯片,可以加快模型的推理速度。
目前手上有可以识别石头剪刀布三种手势的模型设备,需要进行人机交互层面的实现工作。
选取上电运行的主界面图片:

具体需要实现的交互功能为根据人的手势,识别其具体的手势类别,再做出相应的手势反应。
主界面的上电运行图片进行实际的切分,分为剪刀图片,石头图片以及布图片:

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

其显示屏的参数对于项目的区别在于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 uioerr_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 = Nonetask = kpu.load(model_addr)lcd.clear()while(True):img = sensor.snapshot()t = time.ticks_ms()if img is None or img == "":continuefmap = kpu.forward(task, img)t = time.ticks_ms() - tfps = 1000/tplist=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 efinally: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芯片)的图像识别猜拳手势博弈装置的最终效果,完整源代码通过关注我的公众号“千与编程”,有详细教程。其实这个项目是我一早就很想做的项目,现在也算完整完成了,做一个完整的项目,用编程改变世界加油!
我是千与千寻,我们下期见!