【进阶OpenCV】 (19)-- Dlib库 --人脸表情识别

文章目录

  • 表情识别
    • 一、原理
    • 二、代码实现
      • 1. 摄像头前预处理
      • 2. 计算嘴唇变化
      • 3. 绘制嘴唇轮廓
      • 4. 显示结果
      • 5. 完整代码展示
  • 总结

表情识别

目标:识别人物的喜悦状态。

一、原理

我们在对一张人脸图片进行关键点定位后,得到每个关键点的位置:

在这里插入图片描述

比如嘴唇,想象一下当一个人大笑的时候,嘴的大小是不是会发生变化呢,上嘴唇关键点与下嘴唇关键点的距离是不是会变化呐?

这样我们就可以通过变化程度来简单的判断人物体现的心情。

唇部关键点

在这里插入图片描述

人在微笑时,嘴角会上扬,嘴的宽度和与整个脸颊(下颌)的宽度之比变大。

二、代码实现

1. 摄像头前预处理

  1. 构造脸部位置检测器HOG ----> 检测人脸
  2. dlib.shape_predictor载入模型(加载预测器)---- > 获取关键点
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()  # 如果正确读取,ret为True
    if not ret:
        print("不能读取摄像头")
        break
    faces = detector(frame, 0)  # 检测人脸

2. 计算嘴唇变化

  • 计算嘴的宽高比

使用euclidean_distances()函数方法,计算两个数据点之间的欧几里得距离,即两点之间的直线距离。

from sklearn.metrics.pairwise import euclidean_distances
def MAR(shape): # 计算嘴的宽高比
    x = shape[50]
    y = shape[50].reshape(1,2)

    A = euclidean_distances(shape[50].reshape(1,2),shape[58].reshape(1,2))
    B = euclidean_distances(shape[51].reshape(1, 2), shape[57].reshape(1, 2))
    C = euclidean_distances(shape[52].reshape(1, 2), shape[56].reshape(1, 2))
    D = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2))
    return ((A+B+C)/3)/D
  • 计算嘴宽度、脸颊宽度的比值
def MJR(shape): # 计算嘴宽度、脸颊宽度的比值
    M = euclidean_distances(shape[48].reshape(1,2),shape[54].reshape(1,2)) # 嘴宽度
    J = euclidean_distances(shape[3].reshape(1, 2), shape[13].reshape(1, 2)) # 下颌的宽度
    return M/J
  • 代码
for face in faces:
    shape = predictor(frame,face)
    shape = np.array([[p.x,p.y] for p in shape.parts()])
    mar = MAR(shape) # 绘制右眼凸包
    mjr = MJR(shape) # 绘制左眼凸包
    result = "正常"
    print("mar",mar,"\tmjr",mjr)
    if mar > 0.5:
        result = "大笑"
    elif mjr > 0.45:
        result = "微笑"

3. 绘制嘴唇轮廓

绘制嘴唇轮廓,并将表情检测结果显示在图像上:

def cv2ADDChineseText(img,text,position,textColor=(0,255,0),textSize=30):
    """向图片中添加中文"""
    if (isinstance(img,np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)

    fontStyle = ImageFont.truetype("simfang.ttf",textSize,encoding="Utf-8")
    draw.text(position,text,textColor,font=fontStyle)
    return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB)
mouthHull = cv2.convexHull(shape[48:61]) # 计算凸包
frame = cv2ADDChineseText(frame, result, mouthHull[0, 0])  # 多人脸
cv2.drawContours(frame,[mouthHull],-1,(0,255,0),1)

4. 显示结果

    cv2.imshow("Frame",frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()

5. 完整代码展示

import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image,ImageDraw,ImageFont

def MAR(shape): # 计算嘴的宽高比
    x = shape[50]
    y = shape[50].reshape(1,2)

    A = euclidean_distances(shape[50].reshape(1,2),shape[58].reshape(1,2))
    B = euclidean_distances(shape[51].reshape(1, 2), shape[57].reshape(1, 2))
    C = euclidean_distances(shape[52].reshape(1, 2), shape[56].reshape(1, 2))
    D = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2))
    return ((A+B+C)/3)/D

def MJR(shape): # 计算嘴宽度、脸颊宽度的比值
    M = euclidean_distances(shape[48].reshape(1,2),shape[54].reshape(1,2)) # 嘴宽度
    J = euclidean_distances(shape[3].reshape(1, 2), shape[13].reshape(1, 2)) # 下颌的宽度
    return M/J

def cv2ADDChineseText(img,text,position,textColor=(0,255,0),textSize=30):
    """向图片中添加中文"""
    if (isinstance(img,np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)

    fontStyle = ImageFont.truetype("simfang.ttf",textSize,encoding="Utf-8")
    draw.text(position,text,textColor,font=fontStyle)
    return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB)

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()  # 如果正确读取,ret为True
    if not ret:
        print("不能读取摄像头")
        break
    faces = detector(frame, 0)  # 检测人脸

    for face in faces:
        shape = predictor(frame,face)
        shape = np.array([[p.x,p.y] for p in shape.parts()])
        mar = MAR(shape) # 绘制右眼凸包
        mjr = MJR(shape) # 绘制左眼凸包
        result = "正常"
        print("mar",mar,"\tmjr",mjr)
        if mar > 0.5:
            result = "大笑"
        elif mjr > 0.45:
            result = "微笑"
        mouthHull = cv2.convexHull(shape[48:61])

        frame = cv2ADDChineseText(frame, result, mouthHull[0, 0])  # 多人脸
        cv2.drawContours(frame,[mouthHull],-1,(0,255,0),1)

    cv2.imshow("Frame",frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()

总结

本篇介绍了如何通过计算面部关键点的变化情况,来判断人脸的表情变化情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

go压缩的使用

基础:使用go创建一个zip func base(path string) {// 创建 zip 文件zipFile, err : os.Create("test.zip")if err ! nil {panic(err)}defer zipFile.Close()// 创建一个新的 *Writer 对象zipWriter : zip.NewWriter(zipFile)defer zipWriter.Close()// 创…

【Linux】————动静态库

作者主页: 作者主页 本篇博客专栏:Linux 创作时间 :2024年10月22日 一.库的定义 什么是库,在windows平台和linux平台下都大量存在着库。 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载…

渗透实战 JS文件怎么利用

1.前言 关于JS在渗透测试中的关键作用,想必不用过多强调,在互联网上也有许多从JS中找到敏感信息从而拿下关键系统的案例。大部分师傅喜欢使用findsomething之类的浏览器插件,也有使用诸如Unexpected.information以及APIFinder之类的Burp插件…

ES6 Promise的用法

学习链接:ES6 Promise的用法,ES7 async/await异步处理同步化,异步处理进化史_哔哩哔哩_bilibili 一、同步与异步区别 1.JavaScript代码是单线程的程序,即通过一行一行代码顺序执行,即同步概念。 2.若处理一些简短、…

算法魅力-双指针的实战

目录 1.双指针的介绍 1. 左右指针(对撞指针) 2. 快慢指针 2.题目练习讲解 2.1 移动零 算法思路 代码展示 画图效果效果 2.2 复写零 算法思路 代码展示 2.3 快乐数 算法思路 代码展示 2.4 盛最多水的容器 算法思路 代码展示 结束语 1.双指针的…

宝塔PHP8.1安装fileinfo拓展失败解决办法

在宝塔面板中安装PHP8.1后,安装fileinfo扩展一直安装不上,查看日志有报错,于是手动来安装也报错。 宝塔报错: 手动命令行编译安装同,也有报错 cd /www/server/php/81/src/ext/fileinfo/ make distclean ./configure …

【用74ls194实现1000-0100-0010-0001转换】2022-5-13

试用74194附加门电路设计1011011010序列发生器,并用示波器观察。要求:(1)写出设计过程;(2)画出电路图。 2、用multisim软件仿真实现上述序列信号发生器,CP频率为1KHz,用示…

【HarmonyOS】应用实现APP国际化多语言切换

【HarmonyOS】应用实现APP国际化多语言切换 前言 在鸿蒙中应用国际化处理,与Android和IOS基本一致,都是通过JSON配置不同的语言文本内容。在UI展示时,使用JSON配置的字段key进行调用,系统选择对应语言文本内容。 跟随系统多语言…

【scene_manager】与 MoveIt 机器人的规划场景进行交互

scene_manager Scene Manager包是由 Robotnik 创建的 ROS 包,旨在帮助构建和与 MoveIt 机器人的规划场景进行交互。 背景信息 MoveIt 规划场景 是一个用于存储机器人周围世界的表示(外部碰撞)以及机器人自身状态(内部碰撞和当…

rollup.js 插件实现原理与自定义

Rollup.js 是一个JavaScript模块打包器,它主要用于将小块代码编译成大块复杂的库或应用程序。相较于Webpack,Rollup更专注于代码的ES模块转换和优化,特别适合构建库或者那些对代码体积、执行效率有严格要求的应用。Rollup的核心特性之一就是它…

NETSH端口转发

NETSH介绍 netsh是windows系统自带命令行程序,攻击者无需上传第三方工具即可利用netsh程序可进行端口转 发操作,可将内网中其他服务器的端口转发至本地访问运行这个工具需要管理员的权限 实验场景 现在有如下的网络,电脑A是攻击机器&#x…

衡石分析平台系统分析人员手册-仪表盘控件概述

控件​ 控件是仪表盘的基本组成单位。控件种类很多,有展示分析数据的图表类类控件,有展示图片、文字的展示类控件,还有可导出数据、刷新数据、过滤数据等功能类控件。一个完整的仪表盘由多种不同功能的控件构成。 控件类型​ 根据控件是否展…

10月18日笔记(基于系统服务的权限提升)

系统内核漏洞提权 当目标系统存在该漏洞且没有更新安全补丁时,利用已知的系统内核漏洞进行提权,测试人员往往可以获得系统级别的访问权限。 查找系统潜在漏洞 手动寻找可用漏洞 在目标主机上执行以下命令,查看已安装的系统补丁。 system…

详解Java之Spring MVC篇一

目录 Spring MVC 官方介绍 MVC RequestMapping 传递参数 无参数 单个参数 针对String类型 针对Integer类型 针对int类型 针对自定义类型 多个参数 参数重命名 参数强制一致 参数不强制一致 传递数组 ​编辑传递List ​编辑 传递JSON ​编辑 从路径中获取参…

树上启发式合并(详解)

核心思想 借用了一个节点到根的路径上轻边个数不会超过logn条。 故重节点保留&#xff0c;轻节点删去&#xff0c;多重统计。 实际复杂度&#xff08;nlogn&#xff09; 例题 Lomsat gelral - 洛谷 AC 代码 #include<bits/stdc.h> #define int long long using na…

无需扩散,下一个token预测直达AGI!

目录 简单概括1 背景知识方法数据视觉 Tokenizer架构预训练 实验结果视频生成未来预测 简单概括 虽然&#xff0c;下一token预测已在大语言模型领域实现了ChatGPT等突破&#xff0c;但是在多模态模型中的适用性仍不明确&#xff0c;多模态任务仍然由扩散模型&#xff08;如Sta…

大规模创新类竞赛评审方案的建模与研究

随着科技的发展和教育制度的改革&#xff0c;近年来涌现出一批以“创新”为主题的竞赛项目。这类竞赛的运行模式为&#xff0c;参赛队伍提交文档、视频或幻灯片等文本形式的作品&#xff0c;专家对参赛队伍提交的作品评阅判分&#xff0c;一份作品将由多位专家独立进行评阅打分…

19.面试算法-树的深度优先遍历(一)

1. 深入理解前中后序遍历 深度优先遍历有前中后三种情况&#xff0c;大部分人看过之后就能写出来&#xff0c;很遗憾大部分只是背下来的&#xff0c;稍微变换一下就废了。 我们再从二叉树的角度看递归&#xff0c;每次遇到递归&#xff0c;都按照前面说的四步来写&#xff0c…

从壹开始解读Yolov11【源码研读系列】——cfg:模型配置加载功能

目录 一、模型配置操作&#xff1a;cfg.__init__.py 1.cfg.cfg2dict&#xff1a;yaml转字典 2.cfg.get_cfg&#xff1a;读取覆盖配置 3.cfg全局配置参数查询表 ①*基础参数配置&#xff1a; ②*训练参数配置&#xff1a; ③验证测试参数配置&#xff1a; ④*预测参数配置&…

element plus中menu菜单技巧

我在使用element plus的menu&#xff08;侧边栏&#xff09;组件的过程中遇到了一些问题&#xff0c;就是menu编写样式和路由跳转&#xff0c;下面给大家分享以下&#xff0c;我是怎么解决的。 1.页面效果 我要实现的网站布局是这样的&#xff1a; 侧边栏折叠以后的效果&#…