Canmv K210开发板案例——人脸特征识别

学习目标:

在Canmv IDE环境下使用K210学习人脸检测功能,使用通用的神经网络处理器KPU以及实时目标检测的卷积神经网络yolov2来检测人脸。将摄像头采集的画面分析、比对人脸68关键点检测模型,如果有人脸则框出来并且打印相关信息

人脸68关键点:

  • 人脸68关键点是指在面部分析中使用的一组68个精确的面部特征点,这些点覆盖了眼睛、鼻子、嘴巴、眉毛等主要面部结构的位置
  • 该技术广泛应用于面部识别、表情识别、三维面部建模、人脸动画以及医学领域如整形外科。通过深度学习算法,尤其是卷积神经网络,可以高效地检测这些关键点

学习内容:

1、导入相关库,并初始化摄像头和LCD显示屏

import sensor, image, time, lcd
from maix import KPU #导入Maix类的KPU模块


lcd.init()  # 初始化LCD显示屏
sensor.reset()  # 复位并初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 设置摄像头输出格式为 RGB565
sensor.set_framesize(sensor.QVGA)  # 设置摄像头输出大小为 QVGA (320x240)
sensor.skip_frames(time = 1000) # 等待摄像头稳定
clock = time.clock()  # 创建一个clock对象,用来计算帧率

2、初始化KPU相关的参数,加载人脸检测模型以及yolo2网络模型,kpu需要加载kmodel文件

# 人脸检测锚点;锚点参数与模型参数一致,同一个模型这个参数是固定的(即训练模型时确定了)
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)
kpu = KPU()#创建一个KPU类,用于人脸检测

# 从文件系统中加载人脸检测模型(也可以flash地址加载方式),如 "/sd/xxx.kmodel"{(flash_offset, size)(偏移大小,模型大小)}
kpu.load_kmodel("/sd/KPU/yolo_face_detect/face_detect_320x240.kmodel")

# 为yolo2网络模型传入初始化参数, 只有使用yolo2时使用;锚点参数,anchor的锚点数,输入图像的宽,输入图像的高,模型需要的图的宽,模型需要的图的高,模型层宽,模型层高,概率阈值,box_iou门限,要分辨的目标类数量
kpu.init_yolo2(anchor, anchor_num=9, img_w=320, img_h=240, net_w=320 , net_h=240 ,layer_w=10 ,layer_h=8, threshold=0.7, nms_value=0.2, classes=1)
lm68_kpu = KPU() # 创建一个kpu对象,用于人脸68关键点检测
print("ready load model")
lm68_kpu.load_kmodel("/sd/KPU/face_detect_with_68landmark/landmark68.kmodel") # 从文件系统中加载人脸68关键点检测模

3、初始化KPU相关的参数,加载人脸68关键点检测模型

lm68_kpu = KPU() # 创建一个kpu对象,用于人脸68关键点检测
print("ready load model")
lm68_kpu.load_kmodel("/sd/KPU/face_detect_with_68landmark/landmark68.kmodel") # 从文件系统中加载人脸68关键点检测模

4、提取检测到的人脸信息

def extend_box(x, y, w, h, scale):
    x1_t = x - scale*w
    x2_t = x + w + scale*w
    y1_t = y - scale*h
    y2_t = y + h + scale*h
    x1 = int(x1_t) if x1_t>1 else 1
    x2 = int(x2_t) if x2_t<320 else 319
    y1 = int(y1_t) if y1_t>1 else 1
    y2 = int(y2_t) if y2_t<240 else 239
    cut_img_w = x2-x1+1
    cut_img_h = y2-y1+1
    return x1, y1, cut_img_w, cut_img_h

5、使用while循环将图像传入KPU循环进行计算,使用yolo2神经网络算法进行解算,首先检测到人脸,再将人脸检测到的位置信息提取出来,再传入KPU计算并提取面部特征68点,并将脸部器官用符号圈出来。

while True:
    clock.tick()  # 更新计算帧率的clock
    img = sensor.snapshot()  # 拍照,获取一张图像
    kpu.run_with_output(img) # 将输入图像送入kpu运算,并获取结果
    dect = kpu.regionlayer_yolo2() # yolo2运算,并获取结果
    fps = clock.fps() # 打印FPS
    if len(dect) > 0: #识别到人脸
        print("dect:",dect)
        for l in dect :
            # 对检测到的人脸框扩大0.08倍后裁剪
            x1, y1, cut_img_w, cut_img_h = extend_box(l[0], l[1], l[2], l[3], scale=0.08) # 扩大人脸框
            face_cut = img.cut(x1, y1, cut_img_w, cut_img_h) # 从img中裁剪出人脸图
            a = img.draw_rectangle(l[0],l[1],l[2],l[3], color=(0, 255, 0)) # 画人脸框
            face_cut_128 = face_cut.resize(128, 128) # 对人脸图调整大小到128*128
            face_cut_128.pix_to_ai()  # 对rgb565的image生成ai运算需要的r8g8b8格式存储
            out = lm68_kpu.run_with_output(face_cut_128, getlist=True)  # kpu运算并获取结果
            #print("out:",len(out)) #打印特征点的数量

            for j in range(68):# 画矩形框
                x = int(KPU.sigmoid(out[2 * j])*cut_img_w + x1) # 将数据归一化到[0, 1]范围
                y = int(KPU.sigmoid(out[2 * j + 1])*cut_img_h + y1) # 将数据归一化到[0, 1]范围
                # a = img.draw_cross(x, y, size=1, color=(0, 0, 255)) # 画十字
                a = img.draw_circle(x, y, 2, color=(0, 0, 255), fill=True) # 画圆
            del (face_cut_128)
            del (face_cut)

实验分析:

Performing Face Detection:

在这里插入图片描述

Serial Terminal Printing:

在这里插入图片描述

等待摄像头稳定,在画面中检测到人脸时,就会画矩形框住人脸,计算并提取面部特征68点,并将脸部器官用符号圈出来并在串行终端打印出人脸的数据包括:人脸目标框的左上角x,y坐标、人脸框的宽w高h、类别序号、概率值([0, 1])、特征点的数量


实验过程与总结:

实验过程:

  • 在Canmv IDE环境下,利用K210开发板进行人脸检测实验。实验通过初始化摄像头和LCD显示屏,加载人脸检测和yolov2模型至KPU。
  • 实时图像采集后,通过while循环进行人脸检测,识别人脸后提取位置信息,进一步定位68个面部关键点。关键点信息在LCD上可视化,并通过打印输出。需要用到的的模型 下载链接

总结:

  • 在本次实验中,在K210开发板上利用KPU和yolov2卷积神经网络实现了人脸检测及68关键点定位,通过实时摄像头采集的图像进行人脸检测与特征点的标记处理,不仅验证了K210在执行深度学习任务时的高效性,而且通过LCD直观显示检测结果,增强了交互体验。
  • 实验过程中,探索了KPU参数配置和模型优化,为未来在类似硬件上部署深度学习模型奠定了基础。
  • 面部器官检测先要定位人脸,再将人脸图像输入KPU进行运算,以提取器官特征,最终绘制出器官轮廓。

完整代码展示:

# Face_detect_68lm - By: Jack - 周六 4月 20 2024

import sensor, image, time, lcd
from maix import KPU #导入Maix类的KPU模块


lcd.init()  # 初始化LCD显示屏
sensor.reset()  # 复位并初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 设置摄像头输出格式为 RGB565
sensor.set_framesize(sensor.QVGA)  # 设置摄像头输出大小为 QVGA (320x240)
sensor.skip_frames(time = 1000) # 等待摄像头稳定
clock = time.clock()  # 创建一个clock对象,用来计算帧率

# 人脸检测锚点;锚点参数与模型参数一致,同一个模型这个参数是固定的(即训练模型时确定了)
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)
kpu = KPU()#创建一个KPU类,用于人脸检测

# 从文件系统中加载人脸检测模型(也可以flash地址加载方式),如 "/sd/xxx.kmodel"{(flash_offset, size)(偏移大小,模型大小)}
kpu.load_kmodel("/sd/KPU/yolo_face_detect/face_detect_320x240.kmodel")

# 为yolo2网络模型传入初始化参数, 只有使用yolo2时使用;锚点参数,anchor的锚点数,输入图像的宽,输入图像的高,模型需要的图的宽,模型需要的图的高,模型层宽,模型层高,概率阈值,box_iou门限,要分辨的目标类数量
kpu.init_yolo2(anchor, anchor_num=9, img_w=320, img_h=240, net_w=320 , net_h=240 ,layer_w=10 ,layer_h=8, threshold=0.7, nms_value=0.2, classes=1)
lm68_kpu = KPU() # 创建一个kpu对象,用于人脸68关键点检测
print("ready load model")
lm68_kpu.load_kmodel("/sd/KPU/face_detect_with_68landmark/landmark68.kmodel") # 从文件系统中加载人脸68关键点检测模


def extend_box(x, y, w, h, scale):
    x1_t = x - scale*w
    x2_t = x + w + scale*w
    y1_t = y - scale*h
    y2_t = y + h + scale*h
    x1 = int(x1_t) if x1_t>1 else 1
    x2 = int(x2_t) if x2_t<320 else 319
    y1 = int(y1_t) if y1_t>1 else 1
    y2 = int(y2_t) if y2_t<240 else 239
    cut_img_w = x2-x1+1
    cut_img_h = y2-y1+1
    return x1, y1, cut_img_w, cut_img_h

while True:
    clock.tick()  # 更新计算帧率的clock
    img = sensor.snapshot()  # 拍照,获取一张图像
    kpu.run_with_output(img) # 将输入图像送入kpu运算,并获取结果
    dect = kpu.regionlayer_yolo2() # yolo2运算,并获取结果
    fps = clock.fps() # 打印FPS
    if len(dect) > 0: #识别到人脸
        print("dect:",dect)
        for l in dect :
            # 对检测到的人脸框扩大0.08倍后裁剪
            x1, y1, cut_img_w, cut_img_h = extend_box(l[0], l[1], l[2], l[3], scale=0.08) # 扩大人脸框
            face_cut = img.cut(x1, y1, cut_img_w, cut_img_h) # 从img中裁剪出人脸图
            a = img.draw_rectangle(l[0],l[1],l[2],l[3], color=(0, 255, 0)) # 画人脸框
            face_cut_128 = face_cut.resize(128, 128) # 对人脸图调整大小到128*128
            face_cut_128.pix_to_ai()  # 对rgb565的image生成ai运算需要的r8g8b8格式存储
            out = lm68_kpu.run_with_output(face_cut_128, getlist=True)  # kpu运算并获取结果
            #print("out:",len(out)) #打印特征点的数量

            for j in range(68):# 画矩形框
                x = int(KPU.sigmoid(out[2 * j])*cut_img_w + x1) # 将数据归一化到[0, 1]范围
                y = int(KPU.sigmoid(out[2 * j + 1])*cut_img_h + y1) # 将数据归一化到[0, 1]范围
                # a = img.draw_cross(x, y, size=1, color=(0, 0, 255)) # 画十字
                a = img.draw_circle(x, y, 2, color=(0, 0, 255), fill=True) # 画圆
            del (face_cut_128)
            del (face_cut)

    a = img.draw_string(0, 0, "%2.1ffps" %(fps), color=(0, 60, 255), scale=2.0) # 显示屏显示FPS
    lcd.display(img)

# 创建的kpu对象去初始化,释放模型内存
kpu.deinit()
lm68_kpu.deinit()

  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值