K210学习笔记(八)——人脸检测和人脸识别

前言

人脸检测是人脸识别算法的第一步,人脸识别过程主要分为人脸图像获取、人脸检测、人脸配准、人脸表征以及人脸图像匹配与识别。人脸检测的目标是找出图像中所有的人脸对应的位置,算法的输出是人脸外接矩形(椭圆)在图像中的坐标,可能还包括姿态如倾斜角度等信息。人脸检测在安防监控,人证比对,人机交互,社交和娱乐等方面有很强的应用价值。

人脸识别是在人脸检测的基础上除了检测到人脸的位置以外, 还可以识别到这个人是谁,利用分析比较是基于人的脸视觉部特征信息进行身份鉴识别的计算机一种生物识别技术。

一、KPU模块方法

1、

KPU.load(offset, file_path)

从flash或者文件系统中加载模型
参数说明:
offset: 模型在 flash 中的偏移大小,如 0xd00000 表示模型烧录在13M起始的地方, 0x300000表示在 Flash 3M的地方。
file_path: 模型在文件系统中为文件名, 如 “/sd/xxx.kmodel”
注意:offset 和 file_path 参数只能二选一,不需要关键词,直接传参即可。

返回值:
kpu_net: kpu 网络对象
如果正确加载,会返回返回值, 否则会抛出错误, 请看抛出的错误提示, 另外错误代码参考这里如果发现错误代码是小于 2000 的值, 则是固件版本太低,需要更新固件版本

2、

kpu.load_flash(model_addr, is_dual_buf, batch_size, spi_speed)

与 load 方法作用相同.
参数说明:
model_addr:Flash addr 经过预处理的模型烧录到 flash 中的偏移地址。注意,这里需要预处理模型文件说明。
is_dual_buf:0,单一缓冲区加载,使用较少的 RAM 和较慢的速度动态加载该模型文件; 1,开启双缓冲加载,需要更大的 RAM, 运行速度相对较快。
batch_size:将 is_dual_buf 设置为 1 时,需要设置 load batch_size,建议值为 0x4000~0x10000,可以测试出模型的最佳值。如果 is_dual_buf 为 0 则设置为 0
spi_speed:使用 SPI flash 加载模型文件时,我们会暂时将 flash 设置为高速模式,并设置所需的 spi 时钟频率。该值应 <= 80000000(实际频率,设值可能不等于实际频率。)

返回值:
kpu_net: kpu 网络对象

3、

KPU.init_yolo2(kpu_net, threshold, nms_value, anchor_num, anchor)

为yolo2网络模型传入初始化参数, 只有使用yolo2时使用
比如:

import KPU as kpu
task = kpu.load(0x300000)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)

参数说明:
pu_net: kpu 网络对象, 即加载的模型对象, KPU.load()的返回值
threshold: 概率阈值, 只有是这个物体的概率大于这个值才会输出结果, 取值范围:[0, 1]
nms_value: box_iou 门限, 为了防止同一个物体被框出多个框,当在同一个物体上框出了两个框,这两个框的交叉区域占两个框总占用面积的比例 如果小于这个值时, 就取其中概率最大的一个框
anchor_num: anchor 的锚点数, 这里固定为 len(anchors)//2
anchor: 锚点参数与模型参数一致,同一个模型这个参数是固定的,和模型绑定的(训练模型时即确定了), 不能改成其它值。

返回值:
success: bool类型, 是否成功

4、

KPU.deinit(kpu_net)

释放模型占用的内存, 立即释放, 但是变量还在,可以使用delkpu_net_object 的方式删除,另外也可以直接只使用del kpu_net_object来标记对象已被删除,下一次GC进行内存回收或者手动调用gc.collect()时,会自动释放内存
比如:

import KPU as kpu
import gc
task = kpu.load(0x300000)
kpu.deinit(task)
del task
gc.collect()

或者:

import KPU as kpu
import gc
task = kpu.load(0x300000)
del task
gc.collect()

参数说明:
kpu_net: KPU.load() 返回的 kpu_net 对象
返回值:
success: bool 类型, 是否成功

5、

kpu.run_yolo2(task, img)

运行模型
比如:

import KPU as kpu
import image
task = kpu.load(offset or file_path)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
img = image.Image()
kpu.run_yolo2(task, img)

参数说明:
task: kpu_load 返回的 kpu_net 对象
image_t:从 sensor 采集到的图像
返回值:
list: kpu_yolo2_find 的列表

二、人脸检测

因为还没有学习到训练模型章节,所以我使用的是现成的模型,需要到这里下载 face_model_at_0x300000.kfpkg 这个模型文件。
K210学习笔记(八)——人脸检测和人脸识别_第1张图片
然后用用 kflash_gui 下载模型到 Flash, 或者放到 SD 卡中,这里我将模型下载到Flash中。接下来运行脚本即可,脚本代码在这里,如果LCD显示方向颠倒,可以将代码中

sensor.set_vflip(sensor_vflip)
#修改为
sensor.set_vflip(1)

运行效果:

MAIX BIT(K210)人脸检测

二、人脸识别

1.获取机器码

人脸识别就是在人脸检测的基础上,除了检测人脸的位置外,还可以检测出这个人是谁(需要先对准人按按钮学习)。
先到 maixhub 按照说明下载模型K210学习笔记(八)——人脸检测和人脸识别_第2张图片
, 获得模型smodel, 就是 加密版本的kmodel。下载后缀为.smodel模型需要用到机器码。机器码是一机一码的一种加密方式,用于模型文件的加密。如果使用别的机器码去加密或者下载以 smodel 为文件后缀的模型文件,开发板是无法使用该模型文件的。
获取机器码的步骤:
1、将 key_gen.bin 这个固件通过 Kflash 烧录到开发板上。烧录这个机器码固件之后,开发板是处于一个不能使用的状态(就是什么功能都不能使用,包括IDE),上电屏幕只会变成一个白屏。
K210学习笔记(八)——人脸检测和人脸识别_第3张图片
2、
这时将开发板通过 USB 连接到电脑上,利用【串口连接】中的方式来连接开发板。注:IDE 中的串口终端和 IDE 的连接方式相对独立的,而且串口不能通过多种方式进行连接。
3、
利用串口软件连接上开发板,这时按下开发板上的 reset 的按键,就会出现一串字符在终端窗口上,这就机器码。

k210机器码获取

2.使用方法

获取机器码后就可以下载模型了,下载后会的到三个模型,这个三个模型要分别烧录到地址为0x300000、0x400000、0x500000,
烧录地址要和模型一一对应,不然会覆盖固件,K210学习笔记(八)——人脸检测和人脸识别_第4张图片
在烧录模型前需要更新固件为支持V4模型的固件K210学习笔记(八)——人脸检测和人脸识别_第5张图片
如果要使用ide注意要下载支持ide的固件,不然是连接不上ide的,
下载完成后运行脚本查看效果

if code:
        for i in code:
            # Cut face and resize to 128x128
            a = img.draw_rectangle(i.rect())
            face_cut = img.cut(i.x(), i.y(), i.w(), i.h())
            face_cut_128 = face_cut.resize(128, 128)
            a = face_cut_128.pix_to_ai()
            # a = img.draw_image(face_cut_128, (0,0))
            # Landmark for face 5 points
            fmap = kpu.forward(task_ld, face_cut_128)
            plist = fmap[:]
            le = (i.x() + int(plist[0] * i.w() - 10), i.y() + int(plist[1] * i.h()))
            re = (i.x() + int(plist[2] * i.w()), i.y() + int(plist[3] * i.h()))
            nose = (i.x() + int(plist[4] * i.w()), i.y() + int(plist[5] * i.h()))
            lm = (i.x() + int(plist[6] * i.w()), i.y() + int(plist[7] * i.h()))
            rm = (i.x() + int(plist[8] * i.w()), i.y() + int(plist[9] * i.h()))
            a = img.draw_circle(le[0], le[1], 4)
            a = img.draw_circle(re[0], re[1], 4)
            a = img.draw_circle(nose[0], nose[1], 4)
            a = img.draw_circle(lm[0], lm[1], 4)
            a = img.draw_circle(rm[0], rm[1], 4)
            # align face to standard position
            src_point = [le, re, nose, lm, rm]
            T = image.get_affine_transform(src_point, dst_point)
            a = image.warp_affine_ai(img, img_face, T)
            a = img_face.ai_to_pix()
            # a = img.draw_image(img_face, (128,0))

完整代码参考这里。
程序理解:
总共用了三个模型, 分别是:
人脸检测模型, 这和前面的人脸检测使用的是同一个模型, 即找到人脸
人脸关键点检测模型,从前面找到的人脸中找到人脸的 眼睛 鼻子 和 嘴巴 的位置
人脸特征提取模型, 从一张人脸图片中得出一个特征值
步骤如下:
1、检测到人脸
2、裁出人脸,找到人脸的眼睛鼻子嘴巴, 这里裁成了128x128的图
3、把人脸图中的脸旋转到标准位置
4、用特征提取模型提取出人脸的特征值

运行效果:

maix bit人脸识别

总结

MAIX BIT(K210)上可以进行人脸检测和人脸识别,相比来说,人脸检测更加容易实现,人脸识别虽然能识别出人脸,但是识别出是同一人的概率较低,后期可以更换模型来达到更好的效果。

你可能感兴趣的:(K210学习笔记,人工智能,python)