【进阶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为Trueif not ret:print("不能读取摄像头")breakfaces = 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,ImageFontdef 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)/Ddef 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/Jdef 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为Trueif not ret:print("不能读取摄像头")breakfaces = 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()

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

疯狂变现!5分钟教你如何高效率制作AI商业海报!

在这个快节奏的时代,效率就是生命力。无论你是创业者、还是设计师,制作吸引人的详情海报都是日常工作中不可或缺的一环。传统的设计从构思到定稿,往往需要数小时甚至数天的时间。但现在,有了AI技术的加持——仅5分钟,你…

红帽Linux认证与其他认证相比优势在哪?

在各种各样的 IT 认证里头,红帽 Linux 认证凭借自身独特的地方和长处崭露头角。那红帽 Linux 认证跟其他认证相比,长处到底在啥地方呢? 接下来就给大伙简单说道说道。 首先,红帽 Linux 认证特别注重实践。它主要考查考生实际操作…

AI智能监测系统:全面赋能燃气安全管理的智能化转型方案

燃气安全智能化的需求: 随着燃气供应系统的广泛应用,燃气安全成为城市管理和企业运营中的重要环节。由于燃气泄漏、操作不规范等事故会造成巨大的人员伤亡和财产损失,传统的安全管理方法往往效率低下,依赖人工巡检,无…

JavaEE----多线程(二)

文章目录 1.进程的状态2.线程的安全引入3.线程安全的问题产生原因4.synchronized关键字的引入4.1修饰代码块4.2修饰实例方法4.3修饰静态方法4.4对象头介绍4.5死锁-可重入的特性 5.关于死锁的分析总结5.1死锁的分析5.2死锁成因的必要条件5.3死锁的解决方案 1.进程的状态 public…

深入了解 kotlinx-datetime:配置与使用指南

深入了解 kotlinx-datetime:配置与使用指南 在Kotlin多平台开发中,处理日期和时间是常见的需求。kotlinx-datetime库提供了强大且简洁的API来帮助开发者应对这一挑战。本文将详细介绍如何配置kotlinx-datetime库,并通过生动的示例演示其核心…

java中Set,Map,List集合的比较(不包含增删改查函数方法)

目录 1. 集合的简介2. List3. Set4. Map5. 比较5.1 结构特点5.2 实现类5.3 区别 6. 其他问题6.1 集合与数组的区别6.2 哪些集合类是线程安全的 7. 参考链接 1. 集合的简介 所有的集合类和集合接口都在java.util包下。 在内存中申请一块空间用来存储数据,在Java中集…

[网络协议篇] UDP协议

文章目录 1. 简介2. 特点3. UDP数据报结构4. 基于UDP的应用层协议5. UDP安全性问题6. 使用udp传输数据的系统就一定不可靠吗?7. 基于UDP的主机探活 python实现 1. 简介 User Datagram Protocol,用户数据报协议,基于IP协议提供面向无连接的网…

毕业设计—基于 Inception-ResNet模型的皮肤癌分类系统实现

1.摘要 皮肤癌是人类最常见的恶性肿瘤,主要通过视觉诊断进行初步临床筛查。但是由于皮肤病变外观的细微变化性,使用图像自动分类皮肤病变是一项具有挑战性的任务。本文为了提高深度学习算法在皮肤病检测上的准确率,本文提出了基于Inception和…

VoLTE 微案例:VoLTE 注册失败,I-CSCF 返回 403,HSS(UAR) 返回 5001

目录 1. 问题描述 2. 故障注册流程与正常流程对照 3. 结论 博主wx:yuanlai45_csdn 博主qq:2777137742 想要 深入学习 5GC IMS 等通信知识(加入 51学通信),或者想要 cpp 方向修改简历,模拟面试,学习指导都可以添加博主低价指导哈。 1. 问题描述

Geranium天竺葵:位置修改、守护进程管理器、清理器、屏幕时间删除器和 TrollStore 监督器

LocSim,TrollStore 的守护进程经理、清洁工和主管 关于 LocSim、守护进程管理器、清理器、屏幕时间删除器和 TrollStore 监督器 安装 安装Geranium需要满足以下要求:使用TrollStore 1.3或更高版本,并在iOS 15或更高版本的设备上运行。您可以从…

LearnOpenGL之3D模型加载

前序 AndroidLearnOpenGL是本博主自己实现的LearnOpenGL练习集合: Github地址:https://github.com/wangyongyao1989/AndroidLearnOpenGL 系列文章: 1、LearnOpenGL之入门基础 2、LearnOpenGL之3D显示 3、LearnOpenGL之摄像机 4、LearnOpenGL…

#数据结构(二)--栈和队列

栈和队列 一栈 1.栈的顺序存储结构 特点:先进后出 栈是一种只能在一端进行插入或删除操作的线性表。 表中允许插入删除操作的一端为栈顶(top),表的另一端为栈底(bottom), 1 结构体的定义 …

深度学习:SGD的缺点

首先看下述函数: 最小值为x0,y0处 先了解下它的梯度特征。了理解其梯度特征,我们需要计算其梯度向量。 梯度向量 ∇f 是函数 f 在每个变量方向上的偏导数组成的向量。具体来说: ∇f(∂f/∂x,∂f∂/y) 首先,我们计算 f …

3D、VR、AR技术的应用,对家电品牌营销有哪些影响?

家电行业3D数字化营销正以其独特的优势引领着行业的变革。随着技术的不断进步和应用场景的不断拓展,我们有理由相信,未来家电行业的3D数字化营销将会更加精彩纷呈。 那么3D、VR、AR技术的应用,对家电品牌营销有哪些影响? 01、提升…

[CSP-J 2023] 一元二次方程(模拟)

变态的大模拟…… 洛谷题目传送门https://www.luogu.com.cn/problem/P9750 解题思路 主要还是模拟&#xff0c;题目让你求啥你就求啥&#xff0c;要注意细节。 然后化简根式的可以用质因数分解一下即可。 代码 #include<bits/stdc.h> using namespace std; #define …

vue写个表格,让它滚动起来,没有用datav,有的时候结合会出错,一种简单的方法,直接用animation

表格样式就先不说了哈&#xff0c;这些简单内容&#xff0c;如果粉丝朋友还有什么问题&#xff0c;可以私信 好啦&#xff0c;首先&#xff0c;第一步 1.在目录的这个地方创建文件夹css&#xff0c;里面放两个文件 . 第一个文件里面内容 第二个文件里面内容 .drawCur{ curs…

网站建设中需要注意哪些安全问题?----雷池社区版

服务器与应用安全指南 1. 服务器安全 1.1 操作系统安全 及时更新补丁&#xff1a;确保操作系统始终安装最新补丁&#xff0c;以防范系统漏洞。例如&#xff0c;Windows Server 定期推送安全更新&#xff0c;修复如远程代码执行等潜在威胁。优化系统服务配置&#xff1a;关闭不…

深度学习系列——RNN/LSTM/GRU,seq2seq/attention机制

1、RNN/LSTM/GRU可参考&#xff1a; https://zhuanlan.zhihu.com/p/636756912 &#xff08;1&#xff09;对于这里面RNN的表示中&#xff0c;使用了输入x和h的拼接描述&#xff0c;其他公式中也是如此 &#xff08;2&#xff09;各符号图含义如下 2、关于RNN细节&#xff0c;…

node.js学习Day1

1.全局安装express npm install -g express-generator2.创建项目 express node-demo 3.项目安装依赖,补充nodemon npm installnpm install -g nodemon 4.整理目录和初始代码&#xff0c;去掉view文件夹&#xff0c;添加dao和service文件夹&#xff0c;注意app.js文件夹引用…

qt QSaveFile详解

QSaveFile 是 Qt 提供的一个类&#xff0c;用于安全地保存文件。它的主要特点是在写入文件时确保数据完整性&#xff0c;以防止文件损坏。使用 QSaveFile&#xff0c;您可以创建一个临时文件&#xff0c;并在成功写入后将其重命名为目标文件&#xff0c;这样可以避免在写入过程…