当前位置: 首页 > article >正文

《计算机视觉》—— 表情识别

  • 根据计算眼睛、嘴巴的变化,判断是什么表情
  • 结合以下两篇文章来理解表情识别的实现方法
    • 基于 dilib 库的人脸检测
      • https://blog.csdn.net/weixin_73504499/article/details/142977202?spm=1001.2014.3001.5501
    • 基于 dlib 库的人脸关键点定位
      • https://blog.csdn.net/weixin_73504499/article/details/142990867?spm=1001.2014.3001.5501
  • 完整代码如下:
    import numpy as np
    import dlib
    import cv2
    from sklearn.metrics.pairwise import euclidean_distances
    from PIL import Image, ImageDraw, ImageFont
    
    # 计算眼睛的宽高比
    def eye_aspect_ratio(eye):
        A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))
        B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))
        C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))
        ear = ((A + B) / 2.0) / C
        return ear
    
    
    # 计算嘴的宽高比
    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)):  # 判断是否是OpenCV图片类型
            img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 实现 array 到 image 的转换
        draw = ImageDraw.Draw(img)  # 在img图片上创建一个绘图的对象
        # 字体的格式                       C 盘中的 Windows/Fonts 中,复制到此文件夹下可看到文件名
        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 格式
    
    
    # 构建脸部位置检测器
    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()
        frame = cv2.flip(frame, 1)
    
        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)
    
            rightEye = shape[36:42]  # 右眼,关键点索引从36到41(不包含42)
            leftEye = shape[42:48]  # 左眼,关键点索引从42到47(不包含48)
            rightEAR = eye_aspect_ratio(rightEye)  # 计算右眼纵横比
            leftEAR = eye_aspect_ratio(leftEye)  # 计算左眼纵横比
    
            ear = (rightEAR + leftEAR) / 2.0  # 均值处理
    
            result = "正常"  # 默认是正常表情
    
            # 打印出实际值,可以根据该值更改阈值
            print("mar", mar, "\tmjr", mjr, "\tear", ear)
    
            if mar > 0.5 and ear < 0.28:
                result = "大笑"
    
            elif mar > 0.5 and ear > 0.28:
                result = "愤怒"
    
            elif mjr > 0.45:
                result = "微笑"
            # 输出中文
            # frame = cv2AddChineseText(frame, result, (50, 100))
    
            # cv2.putText()#输出英文
    
            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.kler.cn/news/356768.html

相关文章:

  • IDEA运行Java程序时出错。提示:命令行过长。通过 JAR 清单或通过类路径文件缩短命令行,然后重新运行。
  • 鸿蒙NEXT开发-知乎评论小案例(基于最新api12稳定版)
  • vue 环境安装
  • Keepalived:构建高可用性的秘密武器
  • 预警!这些SCISSCI已被多家学校/单位拉黑,请谨慎投递!
  • CSS 选择器简单回顾
  • 第二十五:IP网络层的数据,IP数据报
  • 网络参考模型总结
  • Java中的StringBuilder类
  • 【Vue】Vue3.0 (十二)、watch对ref定义的基本类型、对象类型;reactive定义的对象类型的监视使用
  • 【整合包及教程】第二代GPT-SoVITS V2:革新声音克隆技术
  • Linux——K8S平台的权限规划
  • connect 的断线重连设计
  • .cwsp勒索病毒:了解最新变种,以及如何保护您的数据
  • ubuntu24.0离线安装Ollama和纯cpu版本以及对接Spring AI
  • Missing classes detected while running R8报错解决方案
  • 博客|基于springBoot的精简博客系统设计与实现(附项目源码+论文+数据库)
  • [机器视觉]basler相机使用SN编号打开相机和采集
  • Android中的MVP模式
  • 【LeetCode】每日一题 2024_10_16 最小元素和最大元素的最小平均值(排序、模拟)