Opencv之dilib库:表情识别

一、简介

在计算机视觉领域,表情识别是一个既有趣又具有挑战性的任务。它在人机交互、情感分析、安防监控等众多领域都有着广泛的应用前景。本文将详细介绍如何使用 Python 中的 OpenCV 库和 Dlib 库来实现一个简单的实时表情识别系统。

二、实现原理

表情识别系统主要基于面部关键点的检测与分析。Dlib 库提供了强大的面部关键点检测器,能够准确地定位出面部的 68 个关键点,这些关键点涵盖了眼睛、眉毛、鼻子、嘴巴等重要面部特征部位。通过计算这些关键点之间的距离比例,我们可以提取出能够表征不同表情的特征指标。

三、具体代码实现

python 复制代码
import cv2
import numpy as np
import dlib
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont

上述代码导入了实现表情识别所需的各种库。OpenCV 用于图像处理和视频捕获;Numpy 用于数值计算;Dlib 用于面部检测和关键点定位;scikit - learn 的 euclidean_distances 函数用于计算欧几里得距离,以帮助我们计算面部关键点之间的距离;Pillow 库则用于在图像上添加中文文本。

python 复制代码
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

在MAR函数中,通过选取嘴巴周围的关键点(如嘴角、嘴唇中部等),计算它们之间的欧几里得距离,然后根据特定的公式计算出嘴巴长宽比。这个比值越大,通常表示嘴巴张开得越大,越有可能是大笑表情。

python 复制代码
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

MJR函数则计算了嘴巴宽度与脸部宽度的比值。当这个比值超过一定阈值时,我们认为面部表情为微笑。这里通过比较嘴巴宽度和脸部特定宽度(两眼外角之间的宽度近似代表脸部宽度),来捕捉微笑时嘴巴相对脸部的变化特征。

python 复制代码
def cv2AddChineseText(img, text, position, textColor = (255, 0, 0), textSize =50):
    if (isinstance(img,np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(img)
        fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
        draw.text(position, text, textColor, font=fontStyle)
        return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

函数首先将 OpenCV 的 BGR 图像转换为 RGB 格式,然后使用 Pillow 库的 ImageDraw 和 ImageFont 在图像上指定位置绘制中文文本,最后再将图像转换回 BGR 格式,以便后续在 OpenCV 中使用。下面是主程序部分

python 复制代码
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
cap = cv2.VideoCapture(0)

这里使用 Dlib 的 get_frontal_face_detector 函数初始化面部检测器,加载预训练的 68 个面部关键点模型 shape_predictor_68_face_landmarks.dat 用于关键点预测,并通过 cv2.VideoCapture(0) 打开电脑默认摄像头。用

python 复制代码
while True:
    ret,frame = cap.read()
    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()

在循环中,每读取一帧视频图像,首先使用面部检测器检测图像中的所有面部。对于每个检测到的面部,通过关键点预测器获取面部关键点坐标,并将其转换为 Numpy 数组形式以便后续计算。接着计算 MAR 和 MJR 值,并根据预设的阈值判断表情类别,将识别结果存储在 result 变量中。为了可视化效果,我们使用 cv2.convexHull 函数计算嘴巴区域的凸包,并使用 cv2.drawContours 函数将其绘制在图像上。同时,调用 cv2AddChineseText 函数在嘴巴凸包的起始位置添加识别出的表情文本。最后,通过 cv2.imshow 函数显示处理后的图像。当用户按下 Esc 键(键值为 27)时,循环结束,关闭所有窗口并释放摄像头资源。

运行结果

四、总结

通过上述步骤,我们成功构建了一个简单的实时表情识别系统,能够识别出大笑和微笑两种表情。然而,当前系统还存在一些局限性。例如,仅通过两个简单的特征指标来判断表情,可能无法准确识别更复杂多样的表情,如愤怒、悲伤、惊讶等。并且,阈值的设定是基于经验,可能在不同环境和个体上表现不稳定。

相关推荐
带你去吃小豆花2 小时前
在亚马逊云科技上使用n8n快速构建个人AI NEWS助理
人工智能·科技·ai·云原生·aws
AI技术控3 小时前
计算机视觉算法实战——基于YOLOv8的自动驾驶障碍物实时感知系统
人工智能·yolo·自动驾驶
耘瞳科技6 小时前
喜讯 | 耘瞳科技视觉检测与测量装备荣膺“2024机器视觉创新产品TOP10”
人工智能·科技·视觉检测
__Benco9 小时前
OpenHarmony子系统开发 - DFX(一)
人工智能·harmonyos
小西几哦9 小时前
3D点云配准RPM-Net模型解读(附论文+源码)
人工智能·pytorch·3d
CareyWYR9 小时前
每周AI论文速递(250331-250404)
人工智能
码视野9 小时前
基于快速开发平台与智能手表的区域心电监测与AI预警系统(源码+论文+部署讲解等)
人工智能·智能手表·毕业论文·计算机论文·物联网论文
skywalk81639 小时前
OpenRouter开源的AI大模型路由工具,统一API调用
服务器·前端·人工智能·openrouter
ejinxian10 小时前
大模型应用初学指南
人工智能·大模型·向量数据库