分享一套【优质Python源码】基于Python的深度学习人脸表情识别系统(Keras卷积神经网络+OpenCV+PyQt)

24 阅读5分钟

大家好,我是python222_小锋老师,分享一套优质的基于Python的深度学习人脸表情识别系统(Keras卷积神经网络+OpenCV+PyQt)  。  

1.jpg

项目简介

人工智能与机器视觉技术的迅速发展,掀起了图像处理领域发展的浪潮,深度学习算法也逐渐步入人们的视线。人脸面部表情识别作为人机交互的一个重要组成部分,利用深度学习算法实现对人脸面部表情的识别和分类成为了各界学者研究的热点问题。

论文主要是对人脸面部表情进行识别分类。首先运用 Adaboos 算法对人 脸面部表情图像进行粗略的裁剪,再利用梯度积分投影和双阈值二值化对人脸面部表情图像中的人眼进行定位从而实现对人脸面部图像的精确裁剪;对于裁剪好的图像又对其进行了基于双线性插值的尺度归一化处理和基于均衡化算法的灰度归一化处理,得到最终的统一尺寸和统一灰度的人脸面部表情图像。

综合考虑的神经元的特征、学习规则和网络的拓扑结构三个方面构建了一个用于对人脸面部表情进行识别和分类的卷积神经网络构架。卷积层采用固定权值的 Gabor 小波直接构造,全连接层采用支持向量机算法进行构造,并运用匹配生长规则 对卷积神经网络的层次结构进行确定,利用反向传播算法对整个卷积神经网进行参 数训练。最终得到经过实验确定的适用于人脸面部表情识别与分类的卷积神经网络 结构。针对 Gabor 小波的位数灾难问题,运用 Fisher 线性判别法改进的主成分分析 法对其进行了降维处理,有效地解决了人脸面部图像维数过多和识别时间较长的问 题。 对改进的主成分分析法结合支持向量机算法与卷积神经网络算法分别进行了人 脸面部表情识别的实验,并与传统的人脸面部表情识别结构进行了比较,验证了卷 积神经网络在人脸面部表情识别的准确性和有效性;另外,对人脸面部表情识别分 类系统进行了设计,并设计了应用于人机交互的 GUI 图形用户界面

源码下载

链接: pan.baidu.com/s/1IGofFi7G…

提取码: 1234

相关截图

2.jpg

3.jpg

4.jpg

核心代码

# -*- coding: utf-8 -*-

import cv2
import imutils
import numpy as np
from PyQt5 import QtGui, QtWidgets
from keras.models import load_model
from keras.preprocessing.image import img_to_array
from load_and_process import preprocess_input


class Emotion_Rec:
    def __init__(self, model_path=None):

        # 载入数据和图片的参数
        detection_model_path = 'haarcascade_files/haarcascade_frontalface_default.xml'

        if model_path == None:  # 若未指定路径,则使用默认模型
            emotion_model_path = 'models/_mini_XCEPTION.102-0.66.hdf5'
        else:
            emotion_model_path = model_path

        # 载入人脸检测模型
        self.face_detection = cv2.CascadeClassifier(detection_model_path)  # 级联分类器

        # 载入人脸表情识别模型
        self.emotion_classifier = load_model(emotion_model_path, compile=False)
        # 表情类别
        self.EMOTIONS = ["angry", "disgust", "scared", "happy", "sad", "surprised",
                         "neutral"]

    def run(self, frame_in, canvas, label_face, label_result):
        # frame_in 摄像画面或图像
        # canvas 用于显示的背景图
        # label_face 用于人脸显示画面的label对象
        # label_result 用于显示结果的label对象

        # 调节画面大小
        frame = imutils.resize(frame_in, width=300)  # 缩放画面
        # frame = cv2.resize(frame, (300,300))  # 缩放画面
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 转为灰度图

        # 检测人脸
        faces = self.face_detection.detectMultiScale(gray, scaleFactor=1.1,
                                                     minNeighbors=5, minSize=(30, 30),
                                                     flags=cv2.CASCADE_SCALE_IMAGE)
        preds = []  # 预测的结果
        label = None  # 预测的标签
        (fX, fY, fW, fH) = None, None, None, None  # 人脸位置
        frameClone = frame.copy()  # 复制画面

        if len(faces) > 0:
            # 根据ROI大小将检测到的人脸排序
            faces = sorted(faces, reverse=False, key=lambda x: (x[2] - x[0]) * (x[3] - x[1]))  # 按面积从小到大排序

            for i in range(len(faces)):  # 遍历每张检测到的人脸,默认识别全部人脸
                # 如果只希望识别和显示最大的那张人脸,可取消注释此处if...else的代码段
                # if i == 0:
                #     i = -1
                # else:
                #     break

                (fX, fY, fW, fH) = faces[i]

                # 从灰度图中提取感兴趣区域(ROI),将其大小转换为与模型输入相同的尺寸,并为通过CNN的分类器准备ROI
                roi = gray[fY:fY + fH, fX:fX + fW]
                roi = cv2.resize(roi, self.emotion_classifier.input_shape[1:3])
                roi = preprocess_input(roi)
                roi = img_to_array(roi)
                roi = np.expand_dims(roi, axis=0)

                # 用模型预测各分类的概率
                preds = self.emotion_classifier.predict(roi)[0]
                # emotion_probability = np.max(preds)  # 最大的概率
                label = self.EMOTIONS[preds.argmax()]  # 选取最大概率的表情类

                # 圈出人脸区域并显示识别结果
                cv2.putText(frameClone, label, (fX, fY - 10),
                            cv2.FONT_HERSHEY_TRIPLEX, 0.4, (0, 255, 0), 1)
                cv2.rectangle(frameClone, (fX, fY), (fX + fW, fY + fH), (255, 255, 0), 1)

        # canvas = 255* np.ones((250, 300, 3), dtype="uint8")
        # canvas = cv2.imread('slice.png', flags=cv2.IMREAD_UNCHANGED)

        for (i, (emotion, prob)) in enumerate(zip(self.EMOTIONS, preds)):
            # 用于显示各类别概率
            text = "{}: {:.2f}%".format(emotion, prob * 100)

            # 绘制表情类和对应概率的条形图
            w = int(prob * 300) + 7
            cv2.rectangle(canvas, (7, (i * 35) + 5), (w, (i * 35) + 35), (224, 200, 130), -1)
            cv2.putText(canvas, text, (10, (i * 35) + 23), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 0, 0), 1)

        # 调整画面大小与界面相适应
        frameClone = cv2.resize(frameClone, (420, 280))

        # 在Qt界面中显示人脸
        show = cv2.cvtColor(frameClone, cv2.COLOR_BGR2RGB)
        showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)
        label_face.setPixmap(QtGui.QPixmap.fromImage(showImage))
        QtWidgets.QApplication.processEvents()

        # 在显示结果的label中显示结果
        show = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)
        showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)
        label_result.setPixmap(QtGui.QPixmap.fromImage(showImage))

        return (label)