zoukankan      html  css  js  c++  java
  • dlib表情分析(专注力分数尚在开发)

    Dlib 人脸表情识别

    dlib作为一个一个c++的开源工具包,应用非常广泛,目前常用于人脸识别以及特征点标定。

    1.安装dlib库

    安装dlib,dlib依赖于Boost以及cmake

    以上两个库都只需要pip install Boost以及pip install cmake即可

    但是由于dlib内部集成的是c++环境,所以我们需要安装一个高版本的visual studio,安装时最基本的勾选c++桌面开发,安装完成就可以开始安装dlib

    然后直接pip install dlib,下载解压过程可能稍慢,耐心等候。

    2. 下载68点标注模型

    采用dlib官网给出的训练好的68点标注模型,http://dlib.net/files/

    下载解压到你的当前路径,方便引用

    3.实现原理

    微表情的识别实际简单按照一些动作角度计算并不能做到很精确,人物内心的因素也无法计算在内。

    所以这里只是简单的按照一些动作来进行表情识别。

    如果当前嘴部上扬的角度过大,可能是惊讶或者高兴,进一步通过眼睛的睁开程度区分

    如果当前嘴部张开角度小或者没张开,我们可以暂时认定为自然状态或者愤怒状态,根据眉毛弯曲角度进行进一步的区分。

    理论说明,实践开始

    import cv2
    import dlib
    import time
    import numpy as np
    import mediapipe as mp
    class Face():
        def __init__(self):
            /// 加载检测模型
            self. dector = dlib.get_frontal_face_detector()
            /// 加载68点标注模型
            self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
        def get_face(self,img):
            """
               获取面部数据
               返回值两个
               一个用于返回表情 一个用于返回68点的坐标
               最后一个来确定是否存在人脸图像
            """
            self.s = {}
            res = self.dector(img)
            # 眉毛直线拟合数据缓冲
            line_brow_x = []
            line_brow_y = []
            # 68点坐标
            dp = [[0 for k in range(2) ]for j in range(68)]
            /// 储存68点数据信息
            if (len(res) != 0):
                for i in range(0,len(res)):
                    for id,lm in enumerate(res):
                        self.face_width = lm.right() - lm.left()
                        self.face_higth = lm.top() - lm.bottom()
                        # 计算人脸长度
                        # 使用预测器得到68点数据的坐标
                        shape = self.predictor(img, lm)
                        # 分析点的位置关系来作为表情识别的依据
                        mouth_width = (shape.part(54).x - shape.part(48).x) / self.face_width  # 嘴巴咧开程度
                        mouth_higth = (shape.part(66).y - shape.part(62).y) / self.face_width  # 嘴巴张开程度
    
                        # 通过两个眉毛上的10个特征点,分析挑眉程度和皱眉程度
                        brow_sum = 0  # 高度之和
                        frown_sum = 0  # 两边眉毛距离之和
                        for j in range(17, 21):
                            brow_sum += (shape.part(j).y - lm.top()) + (shape.part(j + 5).y - lm.top())
                            frown_sum += shape.part(j + 5).x - shape.part(j).x
                            line_brow_x.append(shape.part(j).x)
                            line_brow_y.append(shape.part(j).y)
    
                        tempx = np.array(line_brow_x)
                        tempy = np.array(line_brow_y)
    
                        # np.ployfit(x,a,n)拟合点集a得到n级多项式,其中x为横轴长度
                        z1 = np.polyfit(tempx, tempy, 1)  # 拟合成一次直线
                        self.brow_k = -round(z1[0], 3)  # 拟合出曲线的斜率和实际眉毛的倾斜方向是相反的
    
                        eye_sum = (shape.part(41).y - shape.part(37).y + shape.part(40).y - shape.part(38).y +
                                   shape.part(47).y - shape.part(43).y + shape.part(46).y - shape.part(44).y)
                        eye_hight = (eye_sum / 4) / self.face_width
    
                       /// 张嘴表情较大,可能是惊讶或者高兴
                        if round(mouth_higth >= 0.03):
                            if eye_hight >= 0.056:
                                self.s = dict(emotion = 'amazing')
                            else:
                                self.s = dict(emotion = 'happy')
    
                        # 没有张嘴,可能是生气或者自然表情
                        else:
                            if self.brow_k <= -0.5:
                                self.s = dict(emotion = 'angry')
                            else:
                                self.s = dict(emotion = 'nature')
                        for i in range(68):
                            # self.s = ""
                            # self.s += "id: "+ str(i) +","
                            # self.s += "x: " + str(shape.part(i).x) + ","
                            # self.s += "y: " + str(shape.part(i).y)
                            dp[i][0] = shape.part(i).x
                            dp[i][1] = shape.part(i).y
                marks = np.array(dp)
                return self.s,marks,len(res)
            else :
            ///  没有人脸,返回空数据
                return self.s,np.array(dp),len(res)
    
       
    
    def main():
        # 初始化函数
        CTime = 0
        PTime = 0
        cap = cv2.VideoCapture(0)
        op = Face()
        # cap.set(3, 480)
        # 开启初始的摄像头图像为内置
        while True:
            success, img = cap.read()
            # 获取脸部数据
            emo,vis, len = op.get_face(img)
            # emo字典 返回当前表情   vis返回二维数组 68点的坐标 len代表是否存在人脸
            print(emo)
            print(vis)
            // 计算fps
            CTime = time.time()
            fps = 1 / (CTime - PTime)
            PTime = CTime
            // 显示fps
            cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
            # 范围 字体 比例 颜色 速度
            cv2.imshow("Image", img)
            cv2.waitKey(1)
    
    if __name__ == "__main__":
        main()
    

    参考

    https://blog.csdn.net/weixin_40277254/article/details/82350220

    齐芒行,川锋明!
  • 相关阅读:
    【Leetcode】【Easy】Remove Duplicates from Sorted List
    【Leetcode】【Easy】Pascal's Triangle II
    【Leetcode】【Easy】Pascal's Triangle
    【Leetcode】【Easy】Binary Tree Level Order Traversal II
    【Leetcode】【Easy】Binary Tree Level Order Traversal
    【Leetcode】【Easy】Maximum Depth of Binary Tree
    【Leetcode】【Easy】Minimum Depth of Binary Tree
    【Leetcode】【Easy】Balanced Binary Tree
    【Leetcode】【Easy】Symmetric Tree
    如何使用Action.Invoke()触发一个Storyboard
  • 原文地址:https://www.cnblogs.com/qimang-311/p/15526636.html
Copyright © 2011-2022 走看看