基于Retina+PFLD+CNN人脸关键点及表情识别

news2024/9/24 1:26:28

对图片/视频中的人脸进行检测,并绘制人脸框。然后对检测到的人脸进行关键点识别,并进行绘制。最后根据人脸关键点,裁剪出人脸,判断该人脸的表情。

基于此,分别使用retina进行人脸检测,PFLD进行人脸关键点识别,emotion-ferplus-8进行人脸表情的分类,它是基于微软的 FER+ 数据集训练的CNN分类网络,准确率约62%。

模型地址在文末...

代码如下,有详细的注释,注意修改一下自己的模型地址。

import sys
import os
import cv2
import numpy as np
import argparse
import logging.config
from torchvision import transforms


# 添加路径一次即可
sys.path.append('/data/ai/FaceSDK')

from core.image_cropper.arcface_cropper.FaceRecImageCropper import FaceRecImageCropper
from models.model_pipline import ModelLoader

# 配置日志
mpl_logger = logging.getLogger('matplotlib')
mpl_logger.setLevel(logging.WARNING)
logging.config.fileConfig("/data/ai/FaceSDK/config/logging.conf")
logger = logging.getLogger('api')

# 初始化模型加载器,加载模型
model_path = '/data/ai/FaceSDK/models'
model_loader = ModelLoader(model_path)

# 获取需要的模型处理器
faceDetModelHandler = model_loader.get_face_det_model_handler()  # 人脸检测
faceAlignModelHandler = model_loader.get_face_align_model_handler()  # 人脸对齐
face_cropper = FaceRecImageCropper()  # 人脸裁剪

emo_model = cv2.dnn.readNetFromONNX('/data/ai/FaceSDK/models/emotion-ferplus-8.onnx')  # 加载onnx人脸表情模型
logger.info(f"人脸表情识别模型加载成功....")

# 定义情感字典
emotion_dict = {
    0: 'neutral',
    1: 'happiness',
    2: 'surprise',
    3: 'sadness',
    4: 'anger',
    5: 'disgust',
    6: 'fear'
}


def emotion_process(image_name, image):
    dets = faceDetModelHandler.inference_on_image(image)  # 人脸检测
    face_nums = dets.shape[0]

    bboxs = dets
    for i in range(face_nums):
        box = list(map(int, bboxs[i]))
        cv2.rectangle(image, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 2)  # 绘制人脸检测框

        landmarks = faceAlignModelHandler.inference_on_image(image, bboxs[i])
        for (x, y) in landmarks.astype(np.int32):
            cv2.circle(image, (x, y), 2, (255, 0, 0), -1)  # 绘制人脸关键点

        landmarks_list = []
        for (x, y) in landmarks.astype(np.int32):
            landmarks_list.extend((x, y))
        cropped_image = face_cropper.crop_image_by_mat(image, landmarks_list)  # 裁剪人脸

        # 调整尺寸并转换为单通道灰度图像
        cropped_image = cv2.resize(cropped_image, (64, 64))
        cropped_image = cv2.cvtColor(cropped_image, cv2.COLOR_RGB2GRAY)  # 转换为灰度图像
        blob = cv2.dnn.blobFromImage(cropped_image, scalefactor=1.0, size=(64, 64), mean=(0, 0, 0), swapRB=False,
                                     crop=False)

        # 确保输入张量的形状正确
        if blob.shape[1:] != (1, 64, 64):
            logger.error(f"Incorrect blob shape: {blob.shape[1:]}. Expected (1, 64, 64).")
            continue

        emo_model.setInput(blob)
        try:
            output = emo_model.forward()
        except Exception as e:
            logger.error(f"Error during model inference: {e}")
            continue
        pred = emotion_dict[list(output[0]).index(max(output[0]))]  # 推理人脸表情

        # 绘制情感标签
        cv2.putText(
            image,
            pred,
            (box[0], box[1] - 10),
            cv2.FONT_HERSHEY_SIMPLEX,
            0.8,
            (215, 5, 247),
            2,
            lineType=cv2.LINE_AA
        )

    return image


def process_image(image_path, result_folder):
    image_name = os.path.basename(image_path)
    try:
        image = cv2.imread(image_path, cv2.IMREAD_COLOR)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        processed_image = emotion_process(image_name, image)
        result_path = os.path.join(result_folder, image_name)
        cv2.imwrite(result_path, cv2.cvtColor(processed_image, cv2.COLOR_RGB2BGR))
        logger.info(f"Result saved for image: {image_name}")
    except Exception as e:
        logger.error(f"Error processing image {image_path}: {e}")


def process_video(video_path, result_folder):
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        logger.error(f"Error opening video file {video_path}")
        return

    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    size = (frame_width, frame_height)
    result_path = os.path.join(result_folder, 'result_video.avi')
    result = cv2.VideoWriter(result_path, cv2.VideoWriter_fourcc(*'MJPG'), 10, size)

    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break

        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        processed_frame = emotion_process('frame', frame_rgb)
        result.write(cv2.cvtColor(processed_frame, cv2.COLOR_RGB2BGR))

    cap.release()
    result.release()
    logger.info(f"Result video saved to {result_path}")


def process_folder(folder_path, result_folder):
    for image_name in os.listdir(folder_path):
        image_path = os.path.join(folder_path, image_name)
        process_image(image_path, result_folder)


def main(args):
    # 检查并创建结果文件夹
    if not os.path.exists(args.result_folder):
        os.makedirs(args.result_folder)

    if os.path.isdir(args.src):
        process_folder(args.src, args.result_folder)
    elif args.src.lower().endswith(('.mp4', '.avi', '.mov')):
        process_video(args.src, args.result_folder)
    else:
        process_image(args.src, args.result_folder)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Detect Face Emotion")
    parser.add_argument('--src', type=str, required=True, help='path to detect data (image, video, or folder)')
    parser.add_argument('--result_folder', type=str, required=True, help='path to save results')
    args = parser.parse_args()
    main(args)

运行脚本

python emotion_pipline.py --src /data/ai/FaceSDK/emotion/test\
                --result_folder /data/ai/FaceSDK/emotion/result

仓库地址:GitHub - JDAI-CV/FaceX-Zoo: A PyTorch Toolbox for Face Recognition

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993562.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软硬链接详解

目录 一、软硬链接命令 二、特征 三、相关知识 一、软硬链接命令 ln -s target link_name-s:选项表示创建一个符号链接(软链接),如果没有-s就是硬链接target:是要指向的目标文件或目录的路径。link_name&#xff1…

「HarmonyNextOS」页面路由跳转Router更换为Navigation

前言 前段时间,鸿蒙发布了HarmonyNextOS系统,API直接升级到了12,许多API都发生了改变,页面跳转页从当初推荐的Router变换成Navigation,并且从API Version 10之后,都推荐使用NavPathStack来实现页面路由&am…

Go语言项目实战班04 Go语言课程管理系统项目实战 20240807 课程笔记和上课代码

预览 课程特色 本教程录制于2024年8月8日,使用Go1.22版本,基于Goland2024进行开发,采用的技术栈比较新。 每节课控制在十分钟以内,课时精简,每节课都是一个独立的知识点,如果有遗忘,完全可以当…

【JavaEE】synchronized原理

目录 前言 synchronized特性 synchronized特点 synchronize的加锁过程 1.无锁-->偏向锁 2.偏向锁->轻量级锁 3.轻量级锁->重量级锁 锁的优化操作 1.锁消除 2.锁粗化 3.自适应自旋锁 相关面试题 1.什么是偏向锁? 2.synchronized的实现原理是什…

LVS原理及实例

目录 LVS原理 LVS概念 lvs集群的类型 lvs-nat 解释 传输过程 lvs-dr 解释 传输过程 特点 lvs-tun LVS(Linux Virtual Server)常见的调度算法 防火墙标记(Firewall Marking)结合轮询调度 实战案例 lvs的nat模式配置 …

代码随想录算法刷题训练营day49:LeetCode(42)接雨水、LeetCode(84)柱状图中最大的矩形

代码随想录算法刷题训练营day49&#xff1a;LeetCode(42)接雨水、LeetCode(84)柱状图中最大的矩形 LeetCode(42)接雨水 题目 代码 import java.util.Stack;class Solution {public int trap(int[] height) {//用单调栈进行操作int sum0;Stack<Integer> stacknew Stac…

计算机的错误计算(五十六)

摘要 展示大数的正切函数值的错误计算。 由计算机的错误计算&#xff08;五十五&#xff09;知&#xff0c;国际IEEE 754 标准给出的正切函数的定义域是整个实数域范围。那么&#xff0c;在该范围内&#xff0c;软件的计算效果如何呢&#xff1f; 例1. 计算 . 在 Python下计…

字体识别验证码的介绍!

字体识别验证码 ​是一种安全机制&#xff0c;‌通过要求用户识别特定字体来验证用户的身份或防止自动化攻击。‌这种验证码通常包含一些经过特殊设计的字符&#xff0c;‌需要用户根据这些字符的特定样式&#xff08;‌如字体、‌字形等&#xff09;‌来进行识别和输入。‌字…

html+css网页制作 博云丝网5个页面 无js ui还原度100%

htmlcss网页制作 博云丝网5个页面 无js ui还原度100% 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取…

el-tree限制选中个数

el-tree限制选中个数 <el-treestyle"max-width: 600px":data"Treedata":check-strictly"true"show-checkboxnode-key"id":props"defaultProps":default-expanded-keys"[1, 2]"ref"treeRef"check&quo…

Java数组类型

目录 一维数组 一维数组的声明 动态数组初始化 静态数组的初始化 一维数组的访问 数组长度 数组的遍历操作 数组中的默认值 数组中的两个常见异常 越界访问异常ArrayIndexOutOfBoundsException 空指针异常NullPointerException Java中的内存划分 一维数组的内存分…

pdf怎么加密码怎么设置密码?pdf加密码的几种设置方法

在数字化时代&#xff0c;信息的保密性与安全性日益成为我们不可忽视的重要环节。尤其对于包含敏感信息或个人隐私的PDF文档而言&#xff0c;保护其免受未授权访问的侵扰显得尤为重要。通过为PDF文档设置密码保护&#xff0c;我们能够筑起一道坚实的防线&#xff0c;确保只有拥…

危化品安全生产风险监测预警系统的构建与实施

引言 1、背景与重要性 在现代工业生产中&#xff0c;危险化学品&#xff08;简称“危化品”&#xff09;的使用和管理日益广泛。它们在化工、制药、能源等多个领域中扮演着不可或缺的角色。然而&#xff0c;危化品因其固有的易燃、易爆、腐蚀、有毒等特性&#xff0c;一旦管理…

Git使用错误分析

一.fatal: Pathspec is in submodule 我做了这样的错误操作&#xff0c;在一个仓库下的一个子目录&#xff0c;执行了git init 创建了一个子仓库&#xff0c;然后想删掉这个子仓库&#xff0c;就只删除了该子目录下的.git文件夹&#xff0c;而没有删除缓存&#xff0c;执行如下…

java: Internal error in the mapping processor: java.lang.NullPointerExceptio

java: Internal error in the mapping processor: java.lang.NullPointerExceptio 解决办法&#xff1a;idea里面加参数-Djps.track.ap.dependenciesfalse即可

Java程序设计:Java 网络聊天室客户端

相关网络编程前两篇文章&#xff1a;Java程序设计&#xff1a;Java网络编程实验 服务端部分见上一篇文章&#xff1a;Java程序设计&#xff1a;Java网络聊天室服务端 目录 1 实验名称 2 实验目的 3 实验源代码 4 实验运行结果图 5 总结 1 实验名称 Java 网络聊天室客户端 …

纳米软件的电源模块测试系统有什么功能和优势?

纳米软件电源模块自动化测试系统主要实现针对单路进4路出和单路进2路出的非隔离DCDC电源模块进行测试。本次方案包含对以下15个测试项目的自动化测试&#xff0c;分别为输入电压范围VIN的最大值最小值、输出电压范围VOUT的最大值最小值、输出纹波VOPP、电压调整率SV、负载调整率…

基于SpringBoot+Vue的学院商铺管理系统(带1w+文档)

基于SpringBootVue的学院商铺管理系统(带1w文档) 基于SpringBootVue的学院商铺管理系统(带1w文档) 互联网概念的产生到如今的蓬勃发展&#xff0c;用了短短的几十年时间就风靡全球&#xff0c;使得全球各个行业都进行了互联网的改造升级&#xff0c;标志着互联网浪潮的来临。在…

[VBA]使用VBA在Excel中 操作 形状shape 对象

excel已关闭地图插件,对于想做 地图可视化 的,用形状来操作是一种办法,就是要自行找到合适的 地图形状,修改形状颜色等就可以用于 可视化展示不同省市销量、人口等数据。 引言 在Excel中,通过VBA(Visual Basic for Applications)可以极大地增强数据可视化和报告自动化…

Spring Cache在业务系统中最佳实践教程详解及实现原理

1.概述 接着之前总结的如何保证MySQL与Redis数据同步一致性一文中提到在业务代码中一般采用旁路缓存策略方式实现同步&#xff0c;Spring Cache 就是 Spring Framework 基于该策略方式提供的一种缓存抽象&#xff0c;可以帮助开发者简化缓存的使用过程。它支持多种缓存实现&am…