《DNK210使用指南 -CanMV版 V1.0》第三十九章 YOLO2人脸检测实验

第三十九章 YOLO2人脸检测实验

从本章开始,将通过几个实例介绍Kendryte K210上的KPU,以及CanMV下KPU的使用方法,本章将先介绍YOLO2网络的人脸检测应用在CanMV上的实现。通过本章的学习,读者将学习到YOLO2网络的人脸检测应用在CanMV上的实现。

本章分为如下几个小节:

39.1 maix.KPU模块介绍

39.2 硬件设计

39.3 程序设计

39.4 运行验证

39.1 maix.KPU模块介绍

Kendryte K210片上拥有一个KPU,KPU是通用的神经网络处理器,它可以在低功耗的情况下实现卷据神经网络的计算,实时获取被检测目标的大小、坐标和种类,对人脸或者物体进行检测和分类。

Kendryte K210片上KPU的主要特点如下所示:

1. 支持计算多层卷积神经网络,每层卷积神经网络的控制参数可单独配置

2. 支持中断模式,可配置加速器在每层卷积结束后是否产生中断信号

3. 支持输入图像片上存储,存储容量大小为2M字节,卷积结果可由DMA读出

4. 支持输入输出通道数目、输入输出图像行高列宽可配置,其中通道数目范围在1~1024之间,输出行高列宽与输入相同,或者是输入处于2或者4且向下取整

5. 支持两种卷积内核,分别为1*1和3*3,卷积步长为1,十种池化方式,包括bypass、步长为1且大小为2*2的均值、步长为1且大小为2*2的最大值、步长为2且大小为2*2的均值、步长为2且大小为2*2的最大值、步长为2且大小为2*2的左上值、步长为2且大小为2*2的右上值、步长为4且大小为4*4的均值、步长为4且大小为4*4的最大值、步长为4且大小为4*4的左上值

6. 支持两种padding方式,分别为任意填充和取最近值

7. 支持在输入图像行高超过256时,自动对卷积结果进行抽样,仅保留奇数行奇数列结果

8. 支持卷积参数、批归一化参数、激活参数配置,AI加速器主动读取,读取地址可配置

9. 支持卷据参数片上存储,存储容量为72K字节,可以边卷积边读取卷据参数,每层网络最多可以读取64次

10. 支持mobilenet-V1

11. 实时工作时最大支持神经网络参数大小为5.5MiB到5.9MiB

12. 非实时工作最大支持网络参数大小为Flash大小扣除软件占用大小

在CanMV中可以使用CanMV提供的maix.KPU模块操作Kendryte K210上的KPU。maix.KPU模块对图像进行卷积运算,并提供了一些网络的支持,使得开发者能够很方便地在Kendryte K210上使用CanMV实现一些需要卷积神经网络计算的应用。

maix.KPU模块提供了KPU构造函数,用于创建一个KPU对象,KPU构造函数如下所示:

class KPU()

通过KPU构造函数可以创建并初始化一个KPU对象。

KPU构造函数的使用示例如下所示:

from maix import KPU

kpu = KPU()

maix.KPU为KPU对象提供了load_kmodel()方法,用于从文件系统或Flash中加载网络模型,load_kmodel()方法如下所示:

load_kmodel(path, size)

load_kmodel()方法用于为KPU对象从文件系统或Flash中加载网路模型,网络模型加载后会被加载到内存中等待使用。

path指的是网络模型在文件系统中的路径或网络模型在Flash中的起始地址。

size指的是网络模型在Flash中的大小,当使用文件系统的方式加载网络模型时,该参数无效。

load_kmodel()方法的使用示例如下所示:

from maix import KPU

kpu = KPU()

kpu.load_kmode("/sd/KPU/face_detect_320x240.kmodel")

maix.KPU模块为KPU对象提供了init_yolo2()方法,用于初始化yolo2网络模型,init_yolo2()方法如下所示:

KPU.init_yolo2(anchor=None, anchor_num=5, img_w=320, img_h=240, net_w=320, net_h=240, layer_w=10, layer_h=8, threshold=0.7, nms_value=0.4, classes=1)

init_yolo2()方法用于初始化yolo2网络模型,同时为yolo2网络传入一些必要的参数,只有在使用YOLO2网络模型时,才需要用到该方法。

anchor指的是锚点参数,锚点参数是网络在训练前就确定下来的一组数据,同一个网络模型的锚点参数是固定的,锚点参数与网络模型绑定。

anchor_num指的是锚点的数量,固定为len(anchor)//2,即锚点参数数据大小的一半。

img_w和img_h指的是输入图像的宽度和高度,这决定了画框的边界,如果输入图像是由一张小尺寸的图像扩充来的,可以将这两个参数设置为原图的宽度和高度。

net_w和net_h指的是模型需要的图像的宽度和高度,这是在网络模型训练前就确定好的,与网络模型绑定。

layer_w和layer_h指的是网络模型的层宽和层高,这是在网络模型训练前就确定号的,与网路模型绑定。

threshold指的是概率阈值,在网络识别到物体后,之后当被识别物体的可信度大于概率阈值,才会输出该结果,取值范围为[0, 1],默认为0.7。

nums_value指的是box_iou门限,为了防止同一个物体被框出多个框,当在同一个物体上框出两个框时,这两个框的交叉区域占两个框总占用面积的比例如果小于这个参数值,就取其中概率最大的一个框,默认为0.4。

classes指的是网络要分辨目标的类数,这是在网络模型训练前就确定好的,与网络模型绑定,默认为1。

init_yolo2()方法的使用示例如下所示:

from maix import KPU

import image

anchor = (0.1075, 0.126875, 0.126875, 0.175, 0.1465625, 0.2246875, 0.1953125, 0.25375, 0.2440625, 0.351875, 0.341875, 0.4721875, 0.5078125, 0.6696875, 0.8984375, 1.099687, 2.129062, 2.425937)

names = ['face']

kpu = KPU()

kpu.load_kmode("/sd/KPU/face_detect_320x240.kmodel")

kpu.init_yolo2(anchor, anchor_num=len(anchor) // 2, img_w=320, img_h=240, net_w=320, net_h=240, layer_w=10, layer_h=8, threshold=0.5, nms_value=0.2, classes=len(names))

maix.KPU模块为KPU对象提供了run_with_output()方法,用于将图像送入KPU进行运算,并获取运算结果,run_with_output()方法如下所示:

KPU.run_with_output(input, getlist, get_feature)

run_with_output()方法用于将图像送入KPU进行运算,并获取运算结果,且能够指定返回结果的数据类型。

input指的是输入的图像,需要是Image对象,因此可以是摄像头的输出图像,或是文件系统中的图像文件。

getlist指的是是否返回浮点数列表,当为True时,返回浮点数列表,默认为False。

get_feature指的是是否返回L2归一化后的浮点特征值(最大允许256),当为True时,返回L2归一化后的浮点特征值,默认为False。

run_with_output()方法的使用示例如下所示:

from maix import KPU

import image

img = image.Image(size=(320, 240))

anchor = (0.1075, 0.126875, 0.126875, 0.175, 0.1465625, 0.2246875, 0.1953125, 0.25375, 0.2440625, 0.351875, 0.341875, 0.4721875, 0.5078125, 0.6696875, 0.8984375, 1.099687, 2.129062, 2.425937)

names = ['face']

kpu = KPU()

kpu.load_kmode("/sd/KPU/face_detect_320x240.kmodel")

kpu.init_yolo2(anchor, anchor_num=len(anchor) // 2, img_w=320, img_h=240, net_w=320, net_h=240, layer_w=10, layer_h=8, threshold=0.5, nms_value=0.2, classes=len(names))

kpu.run_with_output(input=img, getlist=False, get_feature=False)

maix.KPU模块为KPU对象提供了regionlayer_yolo2()方法,用于进行YOLO2运算,并获取其运算结果,regionlayer_yolo2()方法如下所示:

KPU.regionlayer_yolo2()

regionlayer_yolo2()方法用于进行YOLO2运算,并返回一个二维列表,每个子列表表示识别到的一个物体的信息,包含了物体在输入图像上左上角的X坐标、Y坐标、宽度、高度,以及class的类别序号,以及置信度。

regionlayer_yolo2()方法的使用示例如下所示:

from maix import KPU

import image

img = image.Image(size=(320, 240))

anchor = (0.1075, 0.126875, 0.126875, 0.175, 0.1465625, 0.2246875, 0.1953125, 0.25375, 0.2440625, 0.351875, 0.341875, 0.4721875, 0.5078125, 0.6696875, 0.8984375, 1.099687, 2.129062, 2.425937)

names = ['face']

kpu = KPU()

kpu.load_kmode("/sd/KPU/face_detect_320x240.kmodel")

kpu.init_yolo2(anchor, anchor_num=len(anchor) // 2, img_w=320, img_h=240, net_w=320, net_h=240, layer_w=10, layer_h=8, threshold=0.5, nms_value=0.2, classes=len(names))

kpu.run_with_output(input=img, getlist=False, get_feature=False)

objs = kpu.regionlayer_yolo2()

for obj in objs:

    print("Rect: %d, %d, %d, %d" % (obj[0], obj[1], obj[2], obj[3]))

    print("Class number: %d" % (obj[4]))

print("Prob: %.2f" % (obj[5]))

maix.KPU模块为KPU对象提供了feature_compare()方法,用于进行特征比对,feature_compare()方法如下所示:

KPU.feature_compare(feature_0, feature_1)

feature_compare()方法用于对两组特征进行特征比对,比对两组特征数据并给出相似度得分,得分越高表示两组特征的相似度也就越高。

feature_0和feature_1指的是两组特征数据,浮点列表,最大值为256。

feature_compare()方法会返回两组比较特征的相似度得分值。

feature_compare()方法的使用示例如下所示:

feature = kpu.run_with_output(img, get_feature = True)

score = kpu.feature_compare(record_feature, feature)

print(score)

39.2 硬件设计

39.2.1 例程功能

1. 获取摄像头输出的图像,并送入KPU进行YOLO2的人脸检测模型运算,后将运算结果和摄像头输出的图像一起显示在LCD上。

39.2.2 硬件资源

本章实验内容,主要讲解maix.KPU模块的使用,无需关注硬件资源。

39.2.3 原理图

本章实验内容,主要讲解maix.KPU模块的使用,无需关注原理图。

39.3 程序设计

39.3.1 maix.KPU模块介绍

有关maix.KPU模块的介绍,请见第39.1小节《maix.KPU模块介绍》。

39.3.2 程序流程图

图39.3.2.1 YOLO2人脸检测实验流程图

39.3.3 main.py代码

main.py中的脚本代码如下所示:

import lcd

import sensor

import gc

from maix import KPU

lcd.init()

sensor.reset()

sensor.set_framesize(sensor.QVGA)

sensor.set_pixformat(sensor.RGB565)

sensor.set_hmirror(False)

anchor = (0.1075, 0.126875, 0.126875, 0.175, 0.1465625, 0.2246875, 0.1953125, 0.25375, 0.2440625, 0.351875, 0.341875, 0.4721875, 0.5078125, 0.6696875, 0.8984375, 1.099687, 2.129062, 2.425937)

names = ['face']

# 构造KPU对象

face_detecter = KPU()

# 加载模型文件

face_detecter.load_kmodel("/sd/KPU/face_detect_320x240.kmodel")

# 初始化YOLO2网络

face_detecter.init_yolo2(anchor, anchor_num=len(anchor) // 2, img_w=320, img_h=240, net_w=320, net_h=240, layer_w=10, layer_h=8, threshold=0.5, nms_value=0.2, classes=len(names))

while True:

    img= sensor.snapshot()

    # 进行KPU运算

   face_detecter.run_with_output(input=img, getlist=False, get_feature=False)

    # 进行YOLO2运算

   faces = face_detecter.regionlayer_yolo2()

    for face in faces:

       img.draw_rectangle(face[0], face[1], face[2], face[3], color=(0, 255, 0))

       img.draw_string(face[0] + 2, face[1] + 2, "%.2f" % (face[5]), color=(0, 255, 0))

       img.draw_string(face[0] + 2, face[1] + 10, names[face[4]], color=(0, 255, 0))

    lcd.display(img)

    gc.collect()

可以看到一开始是先初始化了LCD和摄像头。

接着是构造一个KPU对象,并从文件系统中加载YOLO2人脸检测网络需要用到的网络模型,并初始化YOLO2网络。

然后便是在一个循环中不断地获取摄像头输出的图像,并将其送入KPU中进行运算,然后再进行YOLO2网络运算,最后便得到网络识别出人脸在输入图像上的一些信息,将这些信息绘制到图像上后,在LCD上显示图像。

39.4 运行验证

将DNK210开发板连接CanMV IDE,点击CanMV IDE上的“开始(运行脚本)”按钮后,将摄像头对准人脸,让其采集到人脸图像,随后便能在LCD上看到摄像头输出的图像,同时图像中的人脸均被绿色的矩形框框出,并在矩形框内的左上角标出了人脸的置信度,如下图所示:

图39.4.1 LCD显示YOLO2人脸检测结果
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容