深度学习实战训练营

深度学习实战训练营

关于深度实战社区

我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万+粉丝,拥有2篇国家级人工智能发明专利。

社区特色:深度实战算法创新

获取全部完整项目数据集、代码、视频教程,请进入官网:zzgcz.com。竞赛/论文/毕设项目辅导答疑,v:zzgcz_com


1. 项目简介

面部情绪识别是一项通过计算机视觉和深度学习技术自动分析和识别人类面部表情的任务。在社会交互、心理分析、情绪监测等多个领域中具有广泛的应用前景。本项目的目标是利用深度学习模型,设计一个能够识别不同面部情绪(如快乐、愤怒、悲伤、惊讶等)的系统,并实时检测视频或图像中的表情变化。项目使用了基于SSD(Single Shot Multibox Detector)的面部检测算法,并结合情感分类模型实现表情识别。SSD是一种常用于目标检测的深度学习模型,可以通过卷积神经网络(CNN)结构高效地在图片中定位和识别目标。本项目的检测部分采用SSD模型进行人脸定位,而情感分类部分则使用预训练模型进行微调,从而在复杂背景中实现高效、精确的情绪识别。整个流程包括了数据预处理、人脸检测、表情特征提取及分类预测。本项目可以应用于人机交互系统、智能家居监控、在线教育情绪分析以及汽车驾驶员情感监测等场景,从而提升用户体验和行为分析的智能化水平。

SSD融合FERPlus模型实现面部情绪识别-LMLPHP

2.技术创新点摘要

本项目的深度学习模型结合了目标检测和情感识别两个模块,在实现实时性和准确性方面具有技术创新性。首先,该模型使用了SSD(Single Shot MultiBox Detector)作为目标检测的基础模型,并对其进行了结构上的改进,使其在处理小目标(如面部表情)时更加精准。通过自定义的 generate_priors 函数生成多尺度锚框(priors),并引入不同大小的检测框架(min_boxes)来提高特征图中小目标的检测精度,这种策略可以有效地提升表情识别模型在不同分辨率图像中的表现。其次,模型使用了一种基于标准化的图像输入预处理方法(以image_meanimage_std进行归一化),从而减少了输入数据的噪声影响,保证了模型在各种光照条件下的鲁棒性。同时,项目还采用了非极大值抑制(NMS)策略,通过 hard_nms 函数来优化目标框的过滤和重叠检测。这一策略能够有效地去除冗余框,使得最终检测到的面部区域更加精准。此外,该项目引入了来自ONNX模型库的预训练情感识别模型(FERPlus),并进行了模型的迁移学习和优化,使得情感分类模型能够在保持轻量化的同时,实现较高的分类精度。在框架整合上,项目将目标检测和情感识别模块无缝连接,并利用多线程处理技术(通过OpenCV进行视频帧并行处理),提高了系统的实时响应速度。总体来看,该模型在小目标检测、多尺度特征提取和多任务联合学习方面具有显著的创新点,并适用于多种实际应用场景。

3. 数据集与预处理

本项目使用的主要数据集为FERPlus(Facial Expression Recognition Plus),该数据集基于微软原始的FER(Facial Expression Recognition)数据集进行了扩展,包含了来自各种表情的数万张人脸图像。FERPlus数据集的特点是对每张图像进行了多种情感标签的标注,包括快乐、悲伤、愤怒、惊讶、恐惧、厌恶、中性和蔑视,共八种情感类别,并且由多名标注者对每张图像的表情进行了重新评估和多标签分类,从而提高了数据集的情感识别准确性和标签一致性。

在数据预处理方面,首先将图像进行标准化处理(归一化),即使用固定的均值(image_mean)和标准差(image_std)对像素值进行调整,将输入图像归一化到均值为0、方差为1的范围内,以减少不同光照条件、面部颜色差异带来的影响。其次,对输入图像进行尺寸调整(Resize),以适应SSD目标检测网络所需的输入维度。此外,为了提高模型的泛化能力和鲁棒性,项目中采用了数据增强技术,例如随机裁剪、水平翻转、旋转等操作。这些数据增强方法能够使模型在训练过程中见到更多样化的表情特征,避免模型过拟合于特定的面部姿态或表情。

在特征工程部分,模型利用深度卷积神经网络(CNN)对每张图像的面部特征进行提取,并采用不同层级的特征图(feature maps)来构建多尺度的情感特征描述,这样既可以有效捕捉全局表情信息,又能细化面部细节特征,从而提高模型对微表情的识别效果。

4. 模型架构

1) 模型结构的逻辑

本项目采用了双模型结构:SSD(Single Shot MultiBox Detector)进行人脸检测,并结合FERPlus(Facial Emotion Recognition Plus)模型进行情绪分类识别。模型架构逻辑如下:

  • SSD模型: 该模型通过特征图提取(Feature Map)和多尺度检测(Multi-scale Detection)来实现面部检测。主要流程如下:

    • 特征图生成: 输入图像首先通过一系列卷积层(Convolutional Layers)生成不同尺度的特征图。对于每一层特征图中的每个像素点,生成一系列候选框(priors),计算其在原图中的相对位置和大小。
    • 先验框(Anchor Boxes)生成: 使用generate_priors函数为每个特征图生成先验框,计算每个候选框的中心点和宽高。公式如下:

x center = ( i + 0.5 ) scale w , y center = ( j + 0.5 ) scale h x_{\text{center}} = \frac{(i + 0.5)}{\text{scale}_w}, \quad y_{\text{center}} = \frac{(j + 0.5)}{\text{scale}_h} xcenter=scalew(i+0.5),ycenter=scaleh(j+0.5)

w = min_box image_size w , h = min_box image_size h w = \frac{\text{min\_box}}{\text{image\_size}_w}, \quad h = \frac{\text{min\_box}}{\text{image\_size}_h} w=image_sizewmin_box,h=image_sizehmin_box

  • 边界框预测: 使用SSD进行边界框预测,利用自定义NMS(非极大值抑制)算法(hard_nms)进行冗余候选框的去除,从而得到最优人脸检测框。
  • 情感分类模型: 该部分模型基于FERPlus的ONNX预训练模型,该模型使用了多个卷积层进行面部特征提取,并在最后通过Softmax层输出情感分类的概率值。情感分类过程如下:

Emotion_Score = e z i ∑ j = 1 C e z j \text{Emotion\_Score} = \frac{e^{z_{i}}}{\sum_{j=1}^{C} e^{z_{j}}} Emotion_Score=j=1Cezjezi

  • 其中,zi 为第 i 类别(如愤怒、快乐)的得分, C为所有情感类别的数量(共7种情感类型)。
2) 模型的整体训练流程
  • 数据预处理: 首先将输入图像进行归一化和尺寸调整(320×240像素),并根据不同的尺度生成多层特征图。

  • 人脸检测: 通过SSD模型进行多尺度人脸检测,并对检测框进行非极大值抑制,剔除冗余的检测框。最终输出每个检测框的坐标和对应的置信度分数。

  • 情感识别: 将检测到的面部区域提取后输入到FERPlus模型中,经过卷积层和全连接层,输出情感分类的概率分布。

  • 模型评估:

    • 准确率(Accuracy): 衡量模型预测情感标签的准确度。
    • 交并比(IoU): 衡量预测框和真实框的重叠程度,用于评估检测框的精度。

5. 核心代码详细讲解

在整个项目中,关键代码主要涉及人脸检测、先验框生成、情感分类等功能模块。以下为挑选出的核心功能代码及其详细讲解:

1. 先验框(Anchor Boxes)生成

该部分是项目的核心之一,负责根据不同的特征图尺度生成候选框,并应用到多尺度检测中。理解这些先验框的生成逻辑,对于检测模块的精度和多目标处理能力至关重要。

def generate_priors(feature_map_list, shrinkage_list, image_size, min_boxes):
    priors = []遍历每一层特征图for index in range(0, len(feature_map_list[0])):计算当前特征图的缩放比例(scale),即原图与特征图的宽高比例
        scale_w = image_size[0] / shrinkage_list[0][index]
        scale_h = image_size[1] / shrinkage_list[1][index]遍历特征图的每个位置点(像素点),生成候选框for j in range(0, feature_map_list[1][index]):for i in range(0, feature_map_list[0][index]):计算候选框中心点在原图中的位置
                x_center = (i + 0.5) / scale_w
                y_center = (j + 0.5) / scale_h
针对每个位置点生成不同大小的候选框for min_box in min_boxes[index]:
                    w = min_box / image_size[0]
                    h = min_box / image_size[1]将生成的候选框添加到先验框列表中
                    priors.append([
                        x_center,
                        y_center,
                        w,
                        h
                    ])print("priors nums:{}".format(len(priors)))return np.clip(priors, 0.0, 1.0)

详细解释:

  1. feature_map_list:表示每一层特征图的宽高,用于生成不同尺度的先验框。
  2. shrinkage_list:表示特征图相对于原始图像的缩放比例。
  3. image_size:输入图像的大小(如 [320, 240]),用于计算宽高比。
  4. min_boxes:定义每层特征图生成的候选框大小。例如,在小特征图上生成更大的框,而在大特征图上生成小框。

逐行解释:

  • 第 4 行 scale_w = image_size[0] / shrinkage_list[0][index] scale_h = image_size[1] / shrinkage_list[1][index] 计算每个特征图的宽高缩放比例,表示当前特征图与原图的对应关系。
  • 第 7 行 x_center = (i + 0.5) / scale_w y_center = (j + 0.5) / scale_h 计算候选框中心点在原图中的位置。ij 为特征图的像素点位置,经过缩放计算后,得到在原图中的坐标。
  • 第 11 行 w = min_box / image_size[0] h = min_box / image_size[1] 计算候选框的宽高,以原图尺寸为基准。
  • 第 14 行 priors.append([x_center, y_center, w, h]) 将生成的候选框加入到先验框列表中,形成完整的先验框集。
  • 最后返回 np.clip(priors, 0.0, 1.0) 确保生成的候选框坐标值在 [0,1] 的范围内,防止坐标越界。
2. 非极大值抑制(NMS)处理

该模块用于过滤重叠的候选框,确保最终保留的检测框是最优的候选框。

def hard_nms(box_scores, iou_threshold, top_k=-1, candidate_size=200):
    scores = box_scores[:, -1]  提取每个候选框的置信度分数
    boxes = box_scores[:, :-1]  提取候选框的位置信息(不包括最后的分数)
    picked = []  存储保留下来的候选框索引
    indexes = np.argsort(scores)  根据分数进行排序,返回排序后的索引
    indexes = indexes[-candidate_size:]  保留前 candidate_size 个候选框while len(indexes) > 0:
        current = indexes[-1]  选取分数最高的候选框
        picked.append(current)  将当前候选框加入保留列表中if 0 < top_k == len(picked) or len(indexes) == 1:break  若达到指定保留数或候选框数为1,则停止
        current_box = boxes[current, :]  当前候选框的位置
        indexes = indexes[:-1]  从索引列表中移除已选框
        rest_boxes = boxes[indexes, :]  剩余候选框的位置
        iou = iou_of(rest_boxes, np.expand_dims(current_box, axis=0))  计算剩余候选框与当前候选框的IoU
        indexes = indexes[iou <= iou_threshold]  去除与当前候选框重叠度过高的框return box_scores[picked, :]

详细解释:

  1. scores = box_scores[:, -1]:提取每个候选框的置信度分数,最后一列表示置信度。
  2. boxes = box_scores[:, :-1]:去除置信度分数,只保留候选框的位置信息。
  3. indexes = np.argsort(scores):对所有候选框的分数进行升序排序,np.argsort返回排序后的索引值。
  4. indexes = indexes[-candidate_size:]:仅保留最高分数的前candidate_size个候选框。
  5. while len(indexes) > 0:循环遍历所有候选框,直到没有可用候选框为止。
  6. current = indexes[-1]:选取当前最高分数的候选框。
  7. iou = iou_of(rest_boxes, np.expand_dims(current_box, axis=0)):计算剩余候选框与当前候选框的交并比(IoU)。
  8. indexes = indexes[iou <= iou_threshold]:将IoU大于阈值的候选框从索引中移除(重叠过高的框)。

此模块有效减少了检测框的冗余性,提高了模型的检测精度和整体性能。

3. 情感识别分类
model = cv2.dnn.readNetFromONNX('emotion-ferplus-8.onnx')
output = model.forward()
pred = emotion_dict[list(output[0]).index(max(output[0]))]

详细解释:

  1. model = cv2.dnn.readNetFromONNX('emotion-ferplus-8.onnx'):使用OpenCV读取ONNX格式的FERPlus模型,用于情感分类任务。
  2. output = model.forward():前向传播,得到每种情感类别的预测概率值。
  3. pred = emotion_dict[list(output[0]).index(max(output[0]))]:取出最大概率对应的情感类别作为最终预测结果。

6. 模型优缺点评价

模型优点:
  1. 多尺度检测能力强: 本模型使用SSD(Single Shot MultiBox Detector)进行人脸检测,并生成不同尺寸的先验框(priors),能够在不同大小的特征图上检测小目标(如面部表情),从而提升人脸检测的准确度。
  2. 检测速度快: SSD模型由于其“单阶段”检测的特点,在保持较高检测精度的同时,具备更快的检测速度,能够满足实时视频流的情感识别需求。
  3. 情感分类模型优化: 采用FERPlus预训练模型进行迁移学习,使得情感识别模型能够在小样本情况下保持较好的情感分类性能。
  4. 模块化设计: 模型将检测和识别功能模块分离,便于进一步改进和优化各模块的性能。
模型缺点:
  1. 对复杂背景鲁棒性较差: 在复杂背景或光线条件变化较大的场景中,SSD模型的检测精度容易下降,导致情感分类的准确度受影响。
  2. 先验框数量设计繁琐: 在多层特征图上生成不同尺度的先验框需要手动调整和调试,尤其在处理高分辨率图像时可能导致计算量增加。
  3. 情感类别区分不够细致: 仅使用7种情感类别,模型在处理细微情感(如轻微的愤怒或中性情绪)时表现不佳,容易出现混淆。
可能的模型改进方向:
  1. 引入多任务学习: 将情感识别与其他任务(如年龄、性别预测)联合训练,从而提升模型对面部特征的整体理解能力。
  2. 优化模型结构: 使用更先进的检测模型(如RetinaNet或YOLOv5)替代SSD,以提升对复杂场景的检测能力。
  3. 超参数优化: 调整特征图层数、Anchor Box的大小、IoU阈值等参数,以提高检测与分类的精度。
  4. 增强数据集多样性: 通过更多的数据增强技术(如随机遮挡、光照变换等)来提升模型对复杂场景的鲁棒性和泛化能力。

↓↓↓更多热门推荐:
Detectron2和LSTM进行人体动作识别

全部项目数据集、代码、教程进入官网zzgcz.com

10-13 04:17