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

    齐芒行,川锋明!
  • 相关阅读:
    转:pthread_detach()函数
    转: pthread_create()
    转:exit()与_exit()的区别
    转:perror和strerror的区别
    转:socket通信简介
    82-基于Xilinx Virtex-5LXT FPGA的四路光纤PCIE卡(4路光纤卡)
    18-基于双TMS320C6678 DSP的3U VPX的信号处理平台
    ZYNQ系列
    372-基于XC7VX690T的高速模拟信号、万兆光纤综合计算平台
    V7双雄-基于Virtex7XC7VX690T的高性能计算板卡解决方案
  • 原文地址:https://www.cnblogs.com/qimang-311/p/15526636.html
Copyright © 2011-2022 走看看