opencv学习:基于计算机视觉的表情识别系统

news2024/10/22 0:11:41

简介

        基于计算机视觉的表情识别系统,该系统能够从视频流中实时检测人脸,并识别出两种基本表情:大笑和微笑。实验通过分析人脸关键点来计算表情特征指标,从而判断表情类型。

原理

基于以下原理进行:

  1. 人脸检测:使用dlib库的get_frontal_face_detector函数检测视频中的人脸。
  2. 特征点预测:使用dlib库的shape_predictor函数预测人脸的68个关键点。
  3. 表情特征计算
    • 嘴巴张开程度(MAR):通过计算嘴巴周围特定点之间的欧几里得距离来衡量嘴巴的张开程度。
      • 计算上下嘴唇的距离
      • 计算嘴唇的长度
    • 嘴巴宽度与脸部宽度的比例(MJR):通过比较嘴巴宽度和脸部宽度的比例来识别微笑表情。
  4. 表情判断:根据计算出的特征指标,结合预设的阈值判断表情类型。

代码步骤:

1.导入必要的库:

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

2.定义MAR函数:

        函数计算嘴巴张开的程度(MAR),通过计算嘴巴周围特定点之间的距离。

def MAR(shape):
    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

3.定义MJR函数:

        函数计算嘴巴宽度与脸部宽度的比例(MJR),用于判断微笑的程度。

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

4.定义cv2addchinese函数:

        检查图像类型并转换:

def cv2addchinese(img, text, position, textColor=255, textSize=30):
    if isinstance(img, np.ndarray):
        if len(img.shape) == 2:  # 灰度图像
            img_pil = Image.fromarray(img)
        else:  # 彩色图像
            img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    else:
        raise ValueError("img must be a numpy array")

        创建了一个 ImageDraw 对象用于在PIL图像上绘制,加载了一个中文字体文件,在指定位置绘制文本。

    draw = ImageDraw.Draw(img_pil)
    fontstyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, font=fontstyle, fill=textColor)

        将PIL图像转换回OpenCV图像,如果原图像是灰度图,直接转换即可;如果是彩色图,则需要从RGB色彩空间转换回BGR色彩空间。

    if len(img.shape) == 2:  # 灰度图像
        img_cv2 = np.array(img_pil, dtype=np.uint8)
    else:  # 彩色图像
        img_cv2 = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
    return img_cv2

5.初始化人脸检测器和特征点预测器:

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
cap = cv2.VideoCapture('xiao.mp4')

6.读取视频帧并检测人脸:

while True:
    ret, image = cap.read()
    faces = detector(image, 0)
    for face in faces:
        #获取特征点
        shape = predictor(image, face)
        #将 predictor 返回的特征点横坐标与纵坐标转换为NumPy数组
        shape = np.array([[p.x, p.y] for p in shape.parts()])

7.计算表情指标并绘制结果:

        根据MAR和MJR的值来判断表情类型

        mar = MAR(shape)
        mjr = MJR(shape)
        result = '正常'
        print("mar", mar, "\tmjr", mjr)
        if mar > 0.5:
            result = "大笑"
        elif mjr > 0.45:
            result = "微笑"

        #计算嘴巴的凸包
        mouth = cv2.convexHull(shape[48:61])
        #在图像上添加表情文本
        image = cv2addchinese(image, result, mouth[0,0])
        #绘制嘴巴轮廓
        cv2.drawContours(image, [mouth], -1, (0, 255, 0), 1)
    cv2.imshow('frame', image)
    key = cv2.waitKey(60)
    if key == 27:
        break

运行结果

完整代码

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


def MAR(shape):
    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 cv2addchinese(img, text, position, textColor=255, textSize=30):
    if isinstance(img, np.ndarray):
        if len(img.shape) == 2:  # 灰度图像
            img_pil = Image.fromarray(img)
        else:  # 彩色图像
            img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    else:
        raise ValueError("img must be a numpy array")

    draw = ImageDraw.Draw(img_pil)
    fontstyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, font=fontstyle, fill=textColor)

    # 将PIL图像转换回OpenCV图像
    if len(img.shape) == 2:  # 灰度图像
        img_cv2 = np.array(img_pil, dtype=np.uint8)
    else:  # 彩色图像
        img_cv2 = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)

    return img_cv2


detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
cap = cv2.VideoCapture('xiao.mp4')

while True:
    ret, image = cap.read()
    faces = detector(image, 0)
    for face in faces:
        shape = predictor(image, 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 = "微笑"

        mouth = cv2.convexHull(shape[48:61])

        image = cv2addchinese(image, result, mouth[0,0])
        cv2.drawContours(image, [mouth], -1, (0, 255, 0), 1)
    cv2.imshow('frame', image)
    key = cv2.waitKey(60)
    if key == 27:
        break

改进方法:

  1. 提高特征点预测的稳定性:考虑使用更先进的特征点预测模型。
  2. 优化表情识别算法:使用深度学习模型来提高表情识别的准确性。
  3. 改进阈值设置:根据实际应用场景调整MAR和MJR的阈值,以提高识别准确率。
  4. 增强系统的鲁棒性:通过算法优化,提高系统在不同光照和表情变化下的鲁棒性。

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

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

相关文章

缓存常见问题:缓存穿透、雪崩、击穿及解决方案分析

1. 什么是缓存穿透,怎么解决? 缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍。如果有恶意攻击者不断请求系统中不存在的数据,会导致短时…

使用RabbitMQ实现延迟消息的完整指南

在分布式系统中,消息队列通常用于解耦服务,RabbitMQ是一个广泛使用的消息队列服务。延迟消息(也称为延时队列或TTL消息)是一种常见的场景应用,特别适合处理某些任务在一段时间后执行的需求,如订单超时处理、…

CISP/NISP二级练习题-第一卷

目录 另外免费为大家准备了刷题小程序和docx文档,有需要的可以私信获取 1.不同的信息安全风险评估方法可能得到不同的风险评估结果,所以组织 机构应当根据各自的实际情况选择适当的风险评估方法。下面的描述中错误的是 (&#…

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质)

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质) 核心代码完整代码在线示例Cesium 给实体对象(Entity)提供了很多实用的样式,基本满足普通项目需求; 但是作为 WebGL 引擎,肯定不够丰富,尤其是动态效果样式。 对于实体对象(Entity),可以通过自定义材质,实现各种…

MoeCTF 2024 ---Misc方向WP

安全杂项 signin 题目描述: xdsec的小伙伴们和参赛者来上课,碰巧这一天签到系统坏了,作为老师的你,要帮他们 教师代签。 特殊提醒:luo同学今天好像在宿舍打游戏,不想来上课,这是严重的缺勤行为…

VideoCLIP-XL:推进视频CLIP模型对长描述的理解

摘要 对比语言-图像预训练(CLIP)已被广泛研究并应用于众多领域。然而,预训练过程中对简短摘要文本的重视阻碍了CLIP理解长描述的能力。在视频方面,这个问题尤为严重,因为视频通常包含大量详细内容。在本文中&#xff…

【JavaEE】——TCP应答报文机制,超时重传机制

阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 一:TCP协议(面试重点重点) 1:报头长度 2:…

Pytest参数详解 — 基于命令行模式!

1、--collect-only 查看在给定的配置下哪些测试用例会被执行 2、-k 使用表达式来指定希望运行的测试用例。如果测试名是唯一的或者多个测试名的前缀或者后缀相同,可以使用表达式来快速定位,例如: 命令行-k参数.png 3、-m 标记(…

鲸信私有化即时通信如何平衡安全性与易用性之间的关系?

即时通信已经成为我们生活中不可或缺的一部分。从日常沟通到工作协作,每一个信息的传递都承载着信任与效率。然而,随着网络安全威胁日益严峻,如何在享受即时通信便捷的同时,确保信息的私密性与安全性,成为了摆在我们面…

AGV电子地图之贝塞尔曲线

贝塞尔曲线在AGV系统的电子地图中的重要位置 AGV电子地图之贝塞尔曲线_哔哩哔哩_bilibili 点击关注不迷路,你的关注是我们最大的动力 在AGV(自动引导车)系统的电子地图中,贝塞尔曲线有着重要的作用,主要体现在以下几个…

如何保证Redis和数据库的数据一致性

文章目录 0. 前言1. 补充知识:CP和AP2. 什么情况下会出现Redis与数据库数据不一致3. 更新缓存还是删除缓存4. 先操作缓存还是先操作数据库4.1 先操作缓存4.1.1 数据不一致的问题是如何产生的4.1.2 解决方法(延迟双删)4.1.3 最终一致性和强一致…

【大数据算法】一文掌握大数据算法之:大数据算法分析技术。

大数据算法分析技术 1、引言2、 大数据分析技术2.1 时间/空间复杂度2.2 I/O 复杂度2.3 结果质量2.4 通信复杂度 3、总结 1、引言 小屌丝:鱼哥,最近更文有些不频繁了哈。 小鱼:这一个月不见,你这说话方式也变了。 小屌丝&#xff…

C++与C语言的排序算法对比(插入,希尔,归并)

1. 引言 排序算法是计算机科学中的基础概念,广泛应用于数据处理和算法设计中。本文将通过插入排序、希尔排序、归并排序和选择排序这四种常见的排序算法,分别用C和C语言实现,并对它们进行优劣对比,以帮助读者更好地理解这两种语言…

MATLAB支持的字体

listfonts 列出可用的系统字体 {Adobe Devanagari } {Agency FB } {Algerian } {AlienCaret } {AMS } {Arial } {Arial Black …

[LeetCode] 21. 合并两个有序链表

题目描述: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入:l1 [], l2 […

数据结构(8.3_1)——冒泡排序

交换排序: 冒泡排序和快速排序 冒泡排序: 示例: 从行往前将A[i-1]和A[i]比较若遇到A[i-1]>A[i]则将两个元素交换 注意: 代码实现: //交换 void swap(int& a, int& b) {int temp a;a b;b temp; } //冒…

入门!Linux 常见指令及权限管理全面指南

Linux 操作系统在现代计算机应用中扮演着重要的角色,广泛用于服务器、桌面系统、嵌入式设备及云计算平台等领域。理解和掌握 Linux 常见指令及权限管理机制,是每一位系统管理员和开发人员的基础技能。本文将详细介绍 Linux 系统的基本背景、常用指令、权…

设计模式概览

设计模式是一种解决常见编程问题的经验总结,提供了代码的可重用性、可扩展性和可维护性。常见的设计模式有23个,主要分为三大类:创建型模式、结构型模式和行为型模式。下面是这三类设计模式的详细分类和讲解: 一、创建型模式 创建…

进入 Searing-66 火焰星球:第一周游戏指南

Alpha 第四季已开启,穿越火焰星球 Searing-66,带你开启火热征程。准备好勇闯炙热的沙漠,那里有无情的高温和无情的挑战在等待着你。从高风险的烹饪对决到炙热的冒险,Searing-66 将把你的耐力推向极限。带上充足的水,天…

Fusion创建一个简单的api脚本文件

我的Fusion版本:Fusion 2.0.20476 x86_64 脚本模块在实用程序->附加模型->脚本和附加模块,快捷键为shifts 里面有一些演示脚本,可以直接使用 也可以自己创建一个新的脚本 创建的脚本在此处—— 选择脚本文件,点击编辑&a…