我想把两人脸检测演示改为一个模型任务,就是先做人脸识别,再做人脸姿势识别,结果一起输出

Viewed 222

我想把两人脸检测演示改为一个多模型任务,就是先做人脸识别,再做人脸姿势识别,结果一起输出,就是人脸姿势输出上叠加人脸识别结果,先没做多模型任务,只是简单做两次人脸识别,得到结果,一起绘制输出,画面一个人脸是没问题,多人脸是报错,因为是独立的两次人脸识别,结果数量可以不一样,所以我想改为多模型任务,共用一个人脸检测,然后做人脸识别人脸姿势识别,最后绘制输出,在FaceDetApp类定义上有些疑问,疑问如下

大部分人脸检测演示程序定义人脸检测类时,后处理如下
import aidemo
class FaceDetApp(AIBase):
# 自定义后处理,results是模型输出的array列表,这里使用了aidemo库的face_det_post_process接口
def postprocess(self,results):
with ScopedTiming("postprocess",self.debug_mode > 0):
res = aidemo.face_det_post_process(self.confidence_threshold,self.nms_threshold,self.model_input_size[0],self.anchors,self.rgb888p_size,results)
if len(res)==0:
return res
else:
return res[0]

只有人脸识别和注册稍有不同,是这样
import aidemo
class FaceDetApp(AIBase):
# 自定义后处理,results是模型输出的array列表,这里使用了aidemo库的face_det_post_process接口
def postprocess(self,results):
with ScopedTiming("postprocess",self.debug_mode > 0):
res = aidemo.face_det_post_process(self.confidence_threshold,self.nms_threshold,self.model_input_size[0],self.anchors,self.rgb888p_size,results)
if len(res)==0:
return res,res
else:
return res[0],res[1]

就是这个人脸识别后处理res取了两个结果数据,我不知都这第二个数据是什么,用途是什么?
import aidemo res = aidemo.face_det_post_process()这个API接口在哪里定义的,我找不到文档或源码,麻烦提示一下

搞定了
main.py

from libs.PipeLine import PipeLine, ScopedTiming
from libs.AIBase import AIBase
from libs.AI2D import Ai2d
import os
import ujson
from media.media import *
import time
import nncase_runtime as nn
import ulab.numpy as np
import image
import aidemo
import random
import gc
import sys
import math

from face_recognition import FaceDetApp
from face_recognition import FaceRecognition
from face_pose import FacePose

if name == "main":

# 注意:执行人脸识别任务之前,需要先执行人脸注册任务进行人脸身份注册生成feature数据库
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd",用于指定最终图像结果展示的输出模式
display_mode = "lcd"
# k230保持不变,k230d可调整为[640,360],这里设置传给AI的图像分辨率,通常代表图像的宽和高
rgb888p_size = [1920, 1080]

# 根据选择的显示模式来确定显示的分辨率,hdmi模式下通常采用较高分辨率,lcd模式下采用相对较低分辨率
if display_mode == "hdmi":
    display_size = [1920, 1080]
else:
    display_size = [800, 480]

# 人脸检测模型路径,指定了加载人脸检测模型文件的具体位置,模型用于检测图像中的人脸位置等信息
face_det_kmodel_path = "/sdcard/examples/kmodel/face_detection_320.kmodel"
# 人脸识别模型路径,用于加载人脸识别模型文件的位置,该模型基于检测到的人脸进一步识别具体身份
face_reg_kmodel_path = "/sdcard/examples/kmodel/face_recognition.kmodel"
# 人脸姿态模型路径
face_pose_kmodel_path = "/sdcard/examples/kmodel/face_pose.kmodel"

# 其它参数
# anchors文件路径,anchors通常用于目标检测(这里是人脸检测)中预设的先验框相关数据,辅助确定人脸位置等
anchors_path = "/sdcard/examples/utils/prior_data_320.bin"
# 数据库目录,存放了已注册人脸的特征数据文件,用于在识别过程中与人脸特征进行比对
database_dir = "/sdcard/examples/utils/db/"
# 人脸检测模型输入分辨率,明确人脸检测模型期望输入图像的尺寸大小,以适配模型处理要求
face_det_input_size = [320, 320]
# 人脸识别模型输入分辨率,指定人脸识别模型所需输入图像的尺寸,保证模型能正确处理人脸图像
face_reg_input_size = [112, 112]
# 置信度阈值,用于在人脸检测结果中筛选出可信度较高的人脸框,低于此阈值的检测结果将被忽略
confidence_threshold = 0.5
# nms(非极大值抑制)阈值,用于去除重叠度过高的人脸框,保证最终检测到的人脸结果较为准确且不冗余
nms_threshold = 0.2
# anchor的长度,用于从文件中读取anchors数据时确定数据的维度等相关信息
anchor_len = 4200
# 检测维度,可能表示每个anchor相关的数据维度,比如坐标等信息的维度数量
det_dim = 4
# 从指定的文件路径读取anchors数据,将其转换为numpy数组,并按照指定的形状进行重塑,以符合后续处理要求
anchors = np.fromfile(anchors_path, dtype=np.float)
anchors = anchors.reshape((anchor_len, det_dim))
# 人脸识别阈值,用于判断识别出的人脸与数据库中已注册人脸是否匹配,高于此阈值认为识别成功
face_recognition_threshold = 0.75

face_pose_input_size = [120, 120]

# 初始化PipeLine,只关注传给AI的图像分辨率和显示的分辨率,PipeLine类可能负责图像数据的流转、处理等相关流程
pipeLine = PipeLine(rgb888p_size=rgb888p_size, display_size=display_size, display_mode=display_mode)
# 根据显示模式创建相应的管道设置,例如是否进行水平镜像、垂直翻转等操作,不同显示模式下可能有不同的初始化需求
if display_mode == "hdmi":
    # 在hdmi显示模式下,创建管道,设置不进行水平镜像和垂直翻转操作
    pipeLine.create(sensor=None, hmirror=False, vflip=False)
else:
    # 在lcd显示模式下,创建管道,设置不进行水平镜像但进行垂直翻转操作
    pipeLine.create(sensor=None, hmirror=False, vflip=True)

# 创建人脸检测FaceDetApp类的实例,传入各种相关参数,该实例将用于后续的人脸检测
face_det=FaceDetApp( face_det_kmodel_path, face_det_input_size, anchors, confidence_threshold , nms_threshold , rgb888p_size, display_size, debug_mode=0 )

# 创建FaceRecognition类的实例,传入各种相关参数,该实例将用于后续的人脸识别等操作
faceRecognition = FaceRecognition(face_det_kmodel_path, face_reg_kmodel_path, det_input_size=face_det_input_size,
                     reg_input_size=face_reg_input_size, database_dir=database_dir, anchors=anchors,
                     confidence_threshold=confidence_threshold, nms_threshold=nms_threshold,
                     face_recognition_threshold=face_recognition_threshold,
                     rgb888p_size=rgb888p_size, display_size=display_size)

# 创建FacePose类的实例,传入各种相关参数,该实例将用于后续的人脸姿态等操作
facePose = FacePose(face_det_kmodel_path, face_pose_kmodel_path, det_input_size=face_det_input_size,
              pose_input_size=face_pose_input_size, anchors=anchors, confidence_threshold=confidence_threshold,
              nms_threshold=nms_threshold, rgb888p_size=rgb888p_size, display_size=display_size)

face_det.config_preprocess()

try:
    # 主循环,不断执行以下操作,实现实时的人脸识别和结果展示
    while True:
        # 处理操作系统相关的退出事件点,确保程序能正常响应外部的退出请求等情况,比如接收到系统的终止信号时能正确退出循环
        os.exitpoint()
        with ScopedTiming("total", 1):

            # 通过PipeLine获取当前帧图像,这帧图像将作为后续人脸检测和识别的输入数据
            img = pipeLine.get_frame()

            # 执行人脸检测
            det_boxes,landms = face_det.run(img)
 
            # 执行人脸识别,对获取到的图像进行推理,得到人脸框和识别结果信息
            recg_boxes, recg_res = faceRecognition.run(img,det_boxes,landms)
            # faceRecognition.draw_result(pipeLine, recg_boxes, recg_res)

            # 执行人脸姿态相关的推理,得到人脸姿态相关的结果信息(例如头部的角度等信息)
            pose_boxes, pose_res = facePose.run(img,det_boxes)

            # 调用FacePose实例的draw_result方法,将推理得到的人脸姿态结果绘制到图像上,以便直观展示人脸姿态情况
            facePose.draw_result(pipeLine, pose_boxes, pose_res, recg_res)
      
            # 通过PipeLine展示绘制好结果的图像,将处理后的图像输出显示到相应的设备上(如hdmi或lcd屏幕)
            pipeLine.show_image()

            # 执行垃圾回收操作,释放不再使用的内存资源,避免内存泄漏和性能问题,特别是在长时间运行过程中,及时回收内存很重要
            gc.collect()

except Exception as e:
    # 捕获并打印程序运行过程中出现的异常信息,方便排查问题和调试,将异常详细信息输出到标准输出,便于开发者查看错误原因
    sys.print_exception(e)

finally:
    # 对相关资源进行反初始化操作,释放相关资源,例如关闭相关模型文件、释放模型占用的内存等
    face_det.deinit()
    faceRecognition.face_reg.deinit()
    facePose.face_pose.deinit()
    pipeLine.destroy()
2 Answers
    # 执行人脸检测
    det_boxes,landms=self.face_det.run(input_np)
    recg_res = []
    for landm in landms:
        # 针对每个人脸五官点,推理得到人脸特征,并计算特征在数据库中相似度
        self.face_reg.config_preprocess(landm)
        feature=self.face_reg.run(input_np)
        res = self.database_search(feature)
        recg_res.append(res)
    return det_boxes,recg_res

第二个结果数据和五官点有关

还是想知道import aidemo res = aidemo.face_det_post_process()这个API接口定义或源码,麻烦提示一下

aidemo.face_det_post_process是封装的人脸检测后处理的接口,因为micropython并没有numpy库,矩阵处理能力比较差(功能不全+效率差),只有ulab.numpy提供了不完整的部分numpy功能,所以我们专门给例程提供了底层使用cpp实现的后处理接口给aidemo使用,不具备通用性,因此没有给出文档说明。
您可以通过添加打印查看res的输出值,人脸检测结果包含三部分内容:坐标位置,五官关键点和置信度分数。对于一般的人脸检测任务,我们只需要知道其位置坐标即可,因此返回的是res[0],也就是坐标框位置。但是对于人脸识别和人脸注册,我们需要使用五官关键点计算仿射变换矩阵,将人脸调整到正确的位置,保证人脸注册的一般性。比如检测到的人脸1和人脸2都要位于输入中心,并且人脸都是正向等前提,这样才能保证人脸注册的特征向量是一般性的。但是检测的人脸1和人脸2分别位于整张图片的不同位置,方向也不同,要分别将两个人脸按照要求进行仿射变换处理成识别模型需要的方式,在这个过程中需要使用五官关键点计算不同的仿射变换矩阵,因此在人脸识别和人脸注册中,不仅仅需要人脸检测框的位置,还需要五官关键点,所以这里的返回是res[0]和res[1]。
其他的aidemo接口一般也是如此,在底层用c定义接口,然后用cpp实现接口,
应用层和底层实现的接口逻辑见:https://github.com/canmv-k230/canmv/blob/canmv_k230/port/ai_demo/ai_demo.c
接口定义见:https://github.com/canmv-k230/canmv/blob/canmv_k230/port/include/ai_demo/aidemo_wrap.h
接口实现见:https://github.com/canmv-k230/canmv/tree/canmv_k230/port/ai_demo 下的多个cpp文件。

终于搞定了,检测人脸,人脸识别,人脸姿势,一块展示结果,名字显示到人脸姿势大头矩形上

可以的,很棒