目录

OpenCV 表情识别

一、OpenCV表情识别介绍

OpenCV(Open Source Computer Vision Library)是一个广泛应用于计算机视觉任务的开源库,提供了丰富的图像处理和机器学习工具。表情识别则是计算机视觉领域的重要分支,旨在通过分析图像或视频中的人脸特征,判断出人物所表达的情感状态,如高兴、悲伤、愤怒、惊讶等。结合 OpenCV 进行表情识别,能借助其强大功能实现高效且准确的表情判断。

二、表情识别的基本原理

表情识别主要基于图像处理和机器学习技术。其基本流程可以分为以下几个步骤:

人脸检测:在图像或视频帧中定位出人脸的位置和大小。这是表情识别的基础,只有准确地检测到人脸,才能进行后续的表情分析。

特征提取:从检测到的人脸区域中提取出能够反映表情特征的信息,如眼睛、嘴巴等部位的形状和位置变化。常用的特征提取方法包括几何特征提取、纹理特征提取等。

表情分类:将提取到的特征输入到分类器中,根据预先训练好的模型判断人脸的表情类别,如高兴、悲伤、愤怒等。

三、代码实现

  1. 导入必要的库
python 复制代码
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont

numpy:用于处理数值计算和数组操作。

dlib:一个强大的机器学习库,用于人脸检测和关键点定位。

cv2:OpenCV 库,用于计算机视觉任务,如读取视频帧、绘制图形等。

euclidean_distances:用于计算两点之间的欧几里得距离。

PIL(Python Imaging Library):用于处理图像,特别是在图像上添加中文文本。

  1. 定义函数计算嘴部纵横比(MAR)
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

shape 是一个包含 68 个人脸关键点坐标的数组。

A、B、C 分别计算了嘴部垂直方向上三对关键点之间的欧几里得距离。

D 计算了嘴部水平方向上两个关键点之间的欧几里得距离。

最终返回的 MAR 值是垂直方向平均距离与水平方向距离的比值。

  1. 定义函数计算嘴宽与脸颊宽的比例(MJR)
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
  1. 定义函数在图像上添加中文文本
python 复制代码
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("simhei.ttf", textSize, encoding="utf-8")
    draw.text(position, text, textcolor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

由于 OpenCV 本身不支持直接添加中文文本,因此使用 PIL 库来实现。

首先将 OpenCV 的 numpy 数组图像转换为 PIL 图像。

使用 ImageDraw 在图像上绘制文本,使用 ImageFont 指定字体和字号。

最后将 PIL 图像转换回 numpy 数组图像。

  1. 初始化人脸检测器和关键点预测器
python 复制代码
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

detector 用于检测图像中的人脸。

predictor 用于预测人脸的 68 个关键点坐标,需要提供预训练的模型文件 shape_predictor_68_face_landmarks.dat。

  1. 打开摄像头并开始循环处理视频帧
python 复制代码
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    faces = detector(frame, 0)  # 获取图片中全部人脸位置
    for face in faces:
        shape = predictor(frame, face)  # 获取关键点
        # 将关键点转换为坐标(x,y)的形式
        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

cap = cv2.VideoCapture(0) 打开默认摄像头。

在循环中,使用 cap.read() 读取一帧视频。

detector(frame, 0) 检测当前帧中的人脸。

对于每个检测到的人脸,使用 predictor 预测其 68 个关键点坐标,并将其转换为 numpy 数组。

调用 MAR 和 MJR 函数计算嘴部的纵横比和嘴宽与脸颊宽的比例。

根据 MAR 和 MJR 的值判断表情状态(正常、大笑、微笑)。

cv2.convexHull(shape[48:61]) 构造嘴部关键点的凸包。

使用 cv2AddchineseText 函数在图像上添加表情结果文本。

使用 cv2.drawContours 函数在图像上绘制嘴部的凸包。

使用 cv2.imshow 显示处理后的帧。

如果按下 Esc 键(键码为 27),则退出循环。

  1. 释放资源
python 复制代码
cv2.destroyAllWindows()
cap.release()

cv2.destroyAllWindows() 关闭所有 OpenCV 窗口。

cap.release() 释放摄像头资源。

完整代码:

python 复制代码
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image,ImageDraw, ImageFont
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 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("simhei.ttf", textSize, encoding="utf-8")
    draw.text(position, text, textcolor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
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()
    faces = detector(frame,0)  # 获取图片中全部人验位置
    for face in faces:
        shape = predictor(frame,face)  # 获取关键点
        # 将关键点转换为坐标(x,y)的形式
        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()

四、表情识别的应用案例

人机交互

在人机交互中,表情识别可以让计算机更好地理解用户的情感状态,从而提供更加个性化的服务。例如,智能客服系统可以根据用户的表情判断用户的情绪,提供更加贴心的服务。

安防监控

在安防监控中,表情识别可以用于检测人员的异常表情,如愤怒、恐惧等,及时发现潜在的安全隐患。

市场调研

在市场调研中,表情识别可以用于分析消费者对产品或广告的反应,了解消费者的喜好和需求。

五、总结与展望

本文介绍了使用 OpenCV 进行表情识别的基本原理和具体实现方法,包括人脸检测、特征提取和表情分类。通过 OpenCV 提供的丰富工具和函数,我们可以方便地实现一个简单的表情识别系统。然而,表情识别仍然面临着一些挑战,如光照变化、表情多样性等。未来,随着计算机视觉技术的不断发展,表情识别的准确率和鲁棒性将会不断提高,其应用领域也将会更加广泛。

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
每天都要写算法(努力版)几秒前
【神经网络与深度学习】两种加载 pickle 文件方式(joblib、pickle)的差异
人工智能·深度学习·神经网络
制冷男孩3 分钟前
机器学习算法-支持向量机SVM
人工智能·算法·机器学习·支持向量机
结冰架构9 分钟前
人工智能大语言模型与AI芯片新进展:技术演进与商业化路径
人工智能·ai·语言模型·自然语言处理·技术
小研学术28 分钟前
如何开展有组织的AI素养教育?
大数据·人工智能·ai·大模型·deepseek·ai素养
中杯可乐多加冰30 分钟前
CloudFront VPC Origins 实践流程深入解析 —— 安全高效架构的实战之道
人工智能·掘金·金石计划
Francek Chen35 分钟前
【现代深度学习技术】循环神经网络07:通过时间反向传播
人工智能·pytorch·rnn·深度学习·神经网络·bptt
ai问道武曲36 分钟前
ai环境conda带torch整体迁移。
人工智能·pytorch·ai·conda
点PY1 小时前
对VTK中的Volume Data体数据进行二维图像处理
图像处理·人工智能
小草cys1 小时前
AI工作流自动化与智能应用开发平台
运维·人工智能·自动化·dify
小可爱的大笨蛋1 小时前
Spring AI Alibaba - MCP连接 MySQL
人工智能·mysql·spring·mcp