603浏览
查看: 603|回复: 2

[官方教程] Maixduino系列实验(16)---零基础学MaixPy之人脸识别

[复制链接]

Maixduino系列实验(16)---零基础学MaixPy之人脸识别

人脸识别

从古至今,人脸是进行身份辨识的重要方式。在古代,政府为了达到对特定人员的身份识别、防控围捕的目的,会发布“海捕文书”。海捕文书中包括了人员的画像、涉案信息等,通过悬赏及威慑测试调动人民群众积极性,实现对人员的发现、举报、抓捕;在现代,在身份证、驾驶证、护照等重要的个人证件上,均会印刷或粘贴人脸照片,但是这种身份识别本质上是“见物如见人,认物不认人”,它忽视了人们最本质的需要,而人脸识别技术的出现和日益成熟,在实际应用中显现出巨大的优势。

人脸识别是基于人的脸部特征信息进行身份识别的一种生物识别技术。针对输入的人脸图像或者视频流,首先判断其是否存在人脸,如果存在人脸,则进一步的给出每个脸的位置、大小和各个主要面部器官的位置信息。然后依据这些信息,进一步提取每个人脸中所蕴涵的身份特征数据,并将其与已知的人脸进行对比,从而识别每个人脸的身份。人脸识别主要用于身份识别。由于视频监控正在快速普及,众多的视频监控应用迫切需要一种远距离、用户非配合状态下的快速身份识别技术,以求远距离快速确认人员身份,实现智能预警,而人脸识别技术无疑是最佳的选择。

TueMarch-202103029739..png

人脸识别技术优势

  • 非强制性:系统在用户在无意识的状态下就可获取人脸图像,不需要专门配合

  • 非接触性:用户不需要和设备直接接触,就能获取人脸图像,提取人脸特征进行检测

  • 并发性:在实际应用场景下可以进行同时多个人脸的分拣、判断及识别

除此之外,还有操作简单、结果直观、隐蔽性好等特点。

TueMarch-202103021335..png

Maixpy人脸识别模型(Maixpy Face-Recognition Model)

  1. 获取key gen机器码 (Get key Gen machine code)

  2. 下载此模型 (Download this model)

  3. 使用kflash烧录模型 (Burning model with kflash)

  4. 获 取mpy脚本 (Get MPY script)

  5. 使用Maixpy ide 运行脚本 (Running scripts using maixpy IDE)

  6. 使用boot按键录入人脸 (Using the boot button to enter the face)

  7. 开始识别 (Start recognition)

第一步:获取key gen机器码(Get key Gen machine code)并下载

下载地址:https://en.bbs.sipeed.com/uploads/default/original/1X/bca0832bed92a1ada63bd05327688784e2ef14d1.zip

解压到 key_gen_v1.2.bin

第二步:使用kflash_gui 烧录key_gen_v1.2.bin

TueMarch-202103028848..png

TueMarch-202103029073..png

TueMarch-202103023156..png

TueMarch-202103023990..png

Generate key end 生成密钥结束

TueMarch-202103024594..png

第三步:获取mpy脚本 (Get MPY script)

demo_face_recognition.py

TueMarch-202103028853..png

第四步:访问Maixhub 模型平台首页, 注册并登录

https://www.maixhub.com/index.php/index/user/index.html

第五步:选择[MaixPy 人脸识别模型],点击下载按钮

https://www.maixhub.com/index.php/index/index/detail/id/235

第六步:填写32位机器码,点击提交即可获得人脸识别模型

注意:此步点击提交后需耐心等待约30秒,未开始下载前请不要关闭页面。
Note: Please wait patiently for about 30 seconds after clicking Submit in this step Please do not close the page before downloading..

第七步:可以将获得的kfpkg后缀改为zip, 解压获得四个模型文件以及Maixpy精简版固件。kfpkg中打包的Maixpy固件可能会版本过时, 用户可以自行替换为最新的精简版固件(可选步骤)。

注意:目前不支持在完整版Maixpy固件中使用人脸识别模型
Note: Face recognition models are not currently supported in the full version of Maixpy firmware

打包Kfpkg固件

K210 的固件包主要有两种格式: .bin 和 .kfpkg,.kfpkg可以包含多个.bin文件或者模型文件。

  1. 烧录 .bin 或者 .kfpkg 文件
    烧录.bin和.kfpkg文件只需要使用kflash进行烧录就可以了,两者使用起来没什么区别,烧录方法参考MaixPy 的文档。

  2. 创建自己的 .kfpkg 文件

    .bin文件是固件内容,作为参数传给烧录软件,软件会默认烧录到flash开头,完成后重启即可运行。

    但是有时候我们需要烧录其它二进制文件到flash,比如烧录 模型、文件系统 或者自己定义的其它数据,这时需要指定烧录的地址,光是 .bin(二进制) 文件烧录工具不知道我们想把数据烧录到flash的哪里,打包一个.kfpkg格式的文件则是为了实现这个目的。

  3. 最后,将这三个文件(XXX.bin, YYY.bin, flash-list.json)压缩成zip文件,然后改后缀名为.kfpkg 即可被烧录工具识别,并按照指定地址烧录到flash。当然,具体的文件个数看自己的需求了。

其他没有动,只把 Maixpy固件换成了maixpy_v0.5.0_34_ga1b47a3_minimum_with_ide_support,也不知对否,只能试试看了。

第八步:使用 kflash_gui 烧录上一步获取的kfpkg模型

Use kflash_gui to flash the kfpkg model obtained in the previous step.

试了三次,下载出错了

后来尝试下载烧录器的最新版本v1.5.5,安装好重新烧录
链接:https://github.com/sipeed/kflash_gui/releases/tag/v1.5.5

自己打包kfpkg,试着整了好几次,都是无法烧录,只好不做第七步了,直接把前面获得的人脸识别模型烧录了
自己打包kfpkg,试着整了好几次,都是无法烧录,只好不做第七步了,直接把前面获得的人脸识别模型烧录了

烧录完成后,打开IDE串口,确认开发板Maixpy固件的版本,好像是前期的稳定版本V0.4.0

第九步:使用 MaixPy IDE 运行 MaixPy 人脸识别脚本

Run MaixPy Face Recognition Script with MaixPy IDE

**icroPython动手做(09)——零基础学MaixPy之人脸识别

实验程序:简单的人脸识别之一**

`#MicroPython动手做(09)——零基础学MaixPy之人脸识别
#实验程序:简单的人脸识别之一

import sensor,image,lcd
import KPU as kpu

lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(0)
sensor.run(1)

task = kpu.load(0×300000)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
img_lcd=image.Image()

while(True):
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
for i in code:
a = img.draw_rectangle(i.rect())
a = lcd.display(img)
a = kpu.deinit(task)
`

运行出错,串口输出

init i2c2
[MAIXPY]: find gc3028
True
encryp[MAIXPY]kpu: img w=320,h=240, but model w=128,h=128

Traceback (most recent call last):
File “<stdin>”, line 21, in <module>
ValueError: [MAIXPY]kpu: check img format err!

MicroPython v0.4.0-103-g913682433 on 2019-11-29; Sipeed_M1 with kendryte-k210

继续实验,更换程序

**icroPython动手做(09)——零基础学MaixPy之人脸识别

实验程序:简单的人脸识别之二**

`#MicroPython动手做(09)——零基础学MaixPy之人脸识别
#实验程序:简单的人脸识别之二

import sensor,image,lcd
import KPU as kpu
import time
from Maix import FPIOA,GPIO
task_fd = kpu.load(0×200000)
task_ld = kpu.load(0×300000)
task_fe = kpu.load(0×400000)
clock = time.clock()
key_pin=16
fpioa = FPIOA()
fpioa.set_function(key_pin,FPIOA.GPIO7)
key_gpio=GPIO(GPIO.GPIO7,GPIO.IN)
last_key_state=1
key_pressed=0
def check_key():
global last_key_state
global key_pressed
val=key_gpio.value()
key_pressed=0
if last_key_state == 1 and val == 0:
time.sleep(0.02) # debouncing
val=key_gpio.value() # read again
if val == 0:
key_pressed=1
last_key_state = val

lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(1)
sensor.set_vflip(1)
sensor.run(1)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025) #anchor for face detect
dst_point = [(44,59),(84,59),(64,82),(47,105),(81,105)] #standard face key point position
a = kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor)
img_lcd=image.Image()
img_face=image.Image(size=(128,128))
a=img_face.pix_to_ai()
record_ftr=[]
record_ftrs=[]
names = [‘Mr.1’, ‘Mr.2’, ‘Mr.3’, ‘Mr.4’, ‘Mr.5’, ‘Mr.6’, ‘Mr.7’, ‘Mr.8’, ‘Mr.9’ , ‘Mr.10’]
while(1):
check_key()
img = sensor.snapshot()
clock.tick()
code = kpu.run_yolo2(task_fd, img)
if code:
for i in code:

Cut face and resize to 128×128
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))
del(face_cut_128)

calculate face feature vector
fmap = kpu.forward(task_fe, img_face)
feature=kpu.face_encode(fmap[:])
reg_flag = False
scores = []
for j in range(len(record_ftrs)):
score = kpu.face_compare(record_ftrs[j], feature)
scores.append(score)
max_score = 0
index = 0
for k in range(len(scores)):
if max_score < scores[k]:
max_score = scores[k]
index = k
if max_score > 85:
a = img.draw_string(i.x(),i.y(), (“%s :%2.1f” % (names[index], max_score)), color=(0,255,0),scale=2)
else:
a = img.draw_string(i.x(),i.y(), (“X :%2.1f” % (max_score)), color=(255,0,0),scale=2)
if key_pressed == 1:
key_pressed = 0
if len(record_ftrs) < len(names): # prevent appending more than the number of names.
record_ftr = feature
record_ftrs.append(record_ftr)
break
fps =clock.fps()
print(“%2.1f fps”%fps)
a = lcd.display(img)
#kpu.memtest()

#a = kpu.deinit(task_fe)
#a = kpu.deinit(task_ld)
#a = kpu.deinit(task_fd)
`

运行程序,可以识别,阴天情况下大约9-12fps

      

视频:人脸识别的小实验

https://v.youku.com/v_show/id_XNDYyMjA0NjcxMg==.html?spm=a2h0k.11417342.soresults.dtitle

   

识别脚本解读

Interpretation of face recognition script

`import sensor,image,lcd # import 相关库
import KPU as kpu
import time
from Maix import FPIOA,GPIO
task_fd = kpu.load(0×200000) # 从flash 0×200000 加载人脸检测模型
task_ld = kpu.load(0×300000) # 从flash 0×300000 加载人脸五点关键点检测模型
task_fe = kpu.load(0×400000) # 从flash 0×400000 加载人脸196维特征值模型
clock = time.clock() # 初始化系统时钟,计算帧率
key_pin=16 # 设置按键引脚 FPIO16
fpioa = FPIOA()
fpioa.set_function(key_pin,FPIOA.GPIO7)
key_gpio=GPIO(GPIO.GPIO7,GPIO.IN)
last_key_state=1
key_pressed=0 # 初始化按键引脚 分配GPIO7 到 FPIO16
def check_key(): # 按键检测函数,用于在循环中检测按键是否按下,下降沿有效
global last_key_state
global key_pressed
val=key_gpio.value()
if last_key_state == 1 and val == 0:
key_pressed=1
else:
key_pressed=0
last_key_state = val

lcd.init() # 初始化lcd
sensor.reset() #初始化sensor 摄像头
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(1) #设置摄像头镜像
sensor.set_vflip(1) #设置摄像头翻转
sensor.run(1) #使能摄像头
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025) #anchor for face detect 用于人脸检测的Anchor
dst_point = [(44,59),(84,59),(64,82),(47,105),(81,105)] #standard face key point position 标准正脸的5关键点坐标 分别为 左眼 右眼 鼻子 左嘴角 右嘴角
a = kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor) #初始化人脸检测模型
img_lcd=image.Image() # 设置显示buf
img_face=image.Image(size=(128,128)) #设置 128 * 128 人脸图片buf
a=img_face.pix_to_ai() # 将图片转为kpu接受的格式
record_ftr=[] #空列表 用于存储当前196维特征
record_ftrs=[] #空列表 用于存储按键记录下人脸特征, 可以将特征以txt等文件形式保存到sd卡后,读取到此列表,即可实现人脸断电存储。
names = [‘Mr.1’, ‘Mr.2’, ‘Mr.3’, ‘Mr.4’, ‘Mr.5’, ‘Mr.6’, ‘Mr.7’, ‘Mr.8’, ‘Mr.9’ , ‘Mr.10’] # 人名标签,与上面列表特征值一一对应。
while(1): # 主循环
check_key() #按键检测
img = sensor.snapshot() #从摄像头获取一张图片
clock.tick() #记录时刻,用于计算帧率
code = kpu.run_yolo2(task_fd, img) # 运行人脸检测模型,获取人脸坐标位置
if code: # 如果检测到人脸
for i in code: # 迭代坐标框

Cut face and resize to 128×128
a = img.draw_rectangle(i.rect()) # 在屏幕显示人脸方框
face_cut=img.cut(i.x(),i.y(),i.w(),i.h()) # 裁剪人脸部分图片到 face_cut
face_cut_128=face_cut.resize(128,128) # 将裁出的人脸图片 缩放到128 * 128像素
a=face_cut_128.pix_to_ai() # 将猜出图片转换为kpu接受的格式
#a = img.draw_image(face_cut_128, (0,0))

Landmark for face 5 points
fmap = kpu.forward(task_ld, face_cut_128) # 运行人脸5点关键点检测模型
plist=fmap[:] # 获取关键点预测结果
le=(i.x()+int(plist[0]i.w() - 10), i.y()+int(plist[1]i.h())) # 计算左眼位置, 这里在w方向-10 用来补偿模型转换带来的精度损失
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] # 图片中 5 坐标的位置
T=image.get_affine_transform(src_point, dst_point) # 根据获得的5点坐标与标准正脸坐标获取仿射变换矩阵
a=image.warp_affine_ai(img, img_face, T) #对原始图片人脸图片进行仿射变换,变换为正脸图像
a=img_face.ai_to_pix() # 将正脸图像转为kpu格式
#a = img.draw_image(img_face, (128,0))
del(face_cut_128) # 释放裁剪人脸部分图片

calculate face feature vector
fmap = kpu.forward(task_fe, img_face) # 计算正脸图片的196维特征值
feature=kpu.face_encode(fmap[:]) #获取计算结果
reg_flag = False
scores = [] # 存储特征比对分数
for j in range(len(record_ftrs)): #迭代已存特征值
score = kpu.face_compare(record_ftrs[j], feature) #计算当前人脸特征值与已存特征值的分数
scores.append(score) #添加分数总表
max_score = 0
index = 0
for k in range(len(scores)): #迭代所有比对分数,找到最大分数和索引值
if max_score < scores[k]:
max_score = scores[k]
index = k
if max_score > 85: # 如果最大分数大于85, 可以被认定为同一个人
a = img.draw_string(i.x(),i.y(), (“%s :%2.1f” % (names[index], max_score)), color=(0,255,0),scale=2) # 显示人名 与 分数
else:
a = img.draw_string(i.x(),i.y(), (“X :%2.1f” % (max_score)), color=(255,0,0),scale=2) #显示未知 与 分数
if key_pressed == 1: #如果检测到按键
key_pressed = 0 #重置按键状态
record_ftr = feature
record_ftrs.append(record_ftr) #将当前特征添加到已知特征列表
break
fps =clock.fps() #计算帧率
print(“%2.1f fps”%fps) #打印帧率
a = lcd.display(img) #刷屏显示
#kpu.memtest()

#a = kpu.deinit(task_fe)
#a = kpu.deinit(task_ld)
#a = kpu.deinit(task_fd)
`

方向了,默认的人脸识别固件是横屏的。横屏过来识别看看,准确率和速度会好很多

Sipeed-大佬鼠  版主

发表于 2021-3-3 11:01:15

帖子有一点老旧了,还有代码排版乱了喔
回复

使用道具 举报

驴友花雕  高级技匠
 楼主|

发表于 2021-6-30 15:23:14

Sipeed-大佬鼠 发表于 2021-3-3 11:01
帖子有一点老旧了,还有代码排版乱了喔

一年前发的学习记录贴,确实有点落后了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2021 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail