基于深度学习的面部表情分类识别系统

 温馨提示:文末有 CSDN 平台官方提供的师姐 QQ 名片 :) 

1. 项目简介

        面部表情识别是计算机视觉领域的一个重要研究方向, 它在人机交互、心理健康评估、安全监控等领域具有广泛的应用。近年来,随着深度学习技术的快速发展, 面部表情识别的准确性和实时性得到了显著提升。本项目以 MobileNetV2 为基础模型构建面向面部表情识别的卷积神经网络, 完成模型的训练、验证和测试,面部表情识别准确率达到 85%以上。并利用 Flask + Bootstrap 框架搭建交互式分析平台,方便用户进行表情的识别。

基于深度学习的面部表情分类识别系统

2. 面部表情数据集读取与预处理

        利用 opencv 读取面部表情图像数据,并转换为 numpy 数组,图片为灰度图:

def prepare_data(ori_data):
    """
    像素数组转成 numpy array
    """
    image_array = np.zeros(shape=(ori_data.shape[0], img_size, img_size))
    image_label = np.array(list(map(int, ori_data['emotion'])))

    for i, row in ori_data.iterrows():
        image = np.fromstring(row['pixels'], dtype=int, sep=' ')
        image = np.reshape(image, (img_size, img_size))
        image_array[i] = image
        
    return image_array, image_label

         读取的数据集,可视化部分样例数据:

3. 数据集制作与样本均衡处理

        数据集共包含:生气(Angry)、厌恶(Disgust)、恐惧(Fear)、开心(Happy)、悲伤(Sad)、惊讶(Surprise)和中性(Neutral)七种类型,其样本数量分布如下:

        可以看出,样本类别极具不均衡,如不处理样本均衡问题,将影响模型的训练,样本少的类别会得不到充分的学习。

         通过对样本进行采样,并切分出训练集、验证集和测试集:

class_data = [data[data['emotion'] == i] for i in range(7)]

# 对每个类别进行过采样,以匹配平均类别数量
oversampled_data = [resample(class_df, replace=True, n_samples=int(average_class_count), random_state=42) for class_df in class_data]
# 将过采样后的数据合并为一个平衡的数据集
balanced_data = pd.concat(oversampled_data)
# 重置索引并直接在原数据框上进行修改
balanced_data.reset_index(drop=True, inplace=True)

# 准备数据,将特征和标签分离
all_x, all_y = prepare_data(balanced_data)
# 重塑特征数据,以匹配输入形状
all_x = all_x.reshape((all_x.shape[0], img_size, img_size, 1))
# 将标签转换为独热编码格式
all_y = to_categorical(all_y)

# 将数据分为训练集和临时集,其中20%用于测试
x_train, x_temp, y_train, y_temp = train_test_split(all_x, all_y, test_size=0.2)
# 将临时集进一步分为验证集和测试集,各占50%
x_val, x_test, y_val, y_test = train_test_split(x_temp, y_temp, test_size=0.5)

print('训练集:{},验证集:{},测试集:{}'.format(x_train.shape[0], x_val.shape[0], x_test.shape[0]))

        可以看出,七种类型的样本数量已基本均衡,有利于神经网络的训练。

4. 面部表情识别卷积神经网络构建

4.1 MobileNetV2 基础模型

        MobileNetV2 是一种轻量级的深度神经网络模型,由Google在2018年发布,旨在用于移动和边缘设备上的高效图像识别任务。它是MobileNetV1的改进版,继承了其轻量级和高效的特点,并在多个方面进行了优化。以下是MobileNetV2模型的主要特点和结构:

        主要特点:

  1. 深度可分离卷积(Depthwise Separable Convolution): MobileNetV2依然采用了深度可分离卷积来减少模型参数和计算量。这种卷积将标准的卷积分解为两个步骤:深度卷积(depthwise convolution)和逐点卷积(pointwise convolution)。

  2. 线性瓶颈(Linear Bottlenecks): 在MobileNetV2中,作者引入了线性瓶颈的概念,即在网络的最后几层使用了线性激活函数(ReLU6)而不是传统的ReLU,这有助于减少信息的损失。

  3. 倒残差结构(Inverted Residuals): MobileNetV2采用了倒残差结构,即先通过一个逐点卷积扩展维度,然后进行深度卷积,最后再用逐点卷积减少维度。这种结构有助于提高网络的表达能力。

  4. 轻量级: 由于采用了上述结构,MobileNetV2在保持精度的同时大大减少了模型的参数数量和计算量,使其非常适合在资源受限的设备上运行。

4.2 基于迁移学习的卷积神经网络构建

        以 MobileNetV2 为 base 模型,加载利用 ImageNet 大规模数据集预训练的 MobileNetV2 模型权重,构建

base_model = tf.keras.applications.MobileNetV2(
    weights='./pretrained_models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_1.0_96_no_top.h5', 
    include_top=False,
    input_shape=(96,96,3)
)

# Inputlayer
input = tf.keras.layers.Input(name='0_Input',
                            shape=(img_size, img_size, 1))

# Preprocessing stage
x = tf.keras.layers.Resizing(name='1_Preprocessing_1',height = 96, width = 96)(input)
x = tf.keras.layers.Rescaling(name='1_Preprocessing_2',
                            scale = 1/127.0, offset=-1)(x)
x = tf.keras.layers.RandomRotation(name='1_Preprocessing_3',
                                 factor=0.20,
                                 seed=100)(x)
x = tf.keras.layers.RandomFlip(name='1_Preprocessing_4',
                             mode="horizontal",
                             seed=100)(x)

......

# Feature extracting stage
x = base_model(x)
x = tf.keras.layers.Flatten(name='3_Classification_1')(x)

# Classification stage
x = tf.keras.layers.Dense(name='3_Classification_2',
                        units=256,
                        kernel_regularizer=tf.keras.regularizers.l2(l2=regularization_rate),
                        kernel_initializer = 'he_uniform',
                        activation='relu')(x)

......

# Prediction stage
predictions = tf.keras.layers.Dense(name='4_Prediction',
                                  units = 7,
                                  kernel_initializer = 'zeros',
                                  activation=tf.nn.softmax)(x)

model = Model(inputs=input, outputs=predictions)

model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate),
            loss='categorical_crossentropy',
            metrics=['acc'])
model.summary()

5. 模型训练与验证

5.1 模型训练 

        利用切分的训练集进行模型的训练,验证集进行模型的验证评估,并保存 val_acc 最高的模型权重:

checkpoint = ModelCheckpoint('save_models/best_model.h5', monitor='val_acc', verbose=1, mode='max',save_best_only=True)
early = EarlyStopping(monitor="val_acc", mode="max",restore_best_weights=True, patience=5)
lrp_reducer = ReduceLROnPlateau(monitor='val_loss', factor=lrp_factor, patience=lrp_patience, verbose=1)

callbacks_list = [checkpoint, early, lrp_reducer]

history = model.fit(
    x_train, y_train, 
    batch_size=batch_size,
    epochs=epochs,
    steps_per_epoch=x_train.shape[0] // batch_size,
    verbose=1,
    callbacks=callbacks_list,
    validation_data=(x_val, y_val),
    validation_steps=x_val.shape[0]//batch_size
)

5.2 测试集预测结果的 AUC 得分与 ROC score 分布

        模型预测测试集的 AUC 得分,并绘制 ROC 曲线:

# 获取疾病标签名称列表
labels = list(emotions.values())

# 创建一个范围,表示 x 轴上每个标签的位置
x = np.arange(len(labels))
# 设置柱状图的宽度
width = 0.80
fig, ax = plt.subplots(figsize=(20, 8), dpi=120)
rects = ax.bar(x, cate_auc, width, color='#EEC900')
ax.set_ylabel('AUC Score', fontsize=20)
ax.set_xlabel('标签', fontsize=20)
ax.set_title('不同类别模型预测 AUC Score 分布', fontsize=30)
ax.set_xticks(x, labels, fontsize=20)
ax.bar_label(rects, padding=3, fontsize=16)
fig.tight_layout()
plt.show()

5.3 困惑矩阵 Confusionmatrix

from matplotlib.colors import LogNorm
import seaborn as sns

true_labels = np.argmax(y_test, axis=1)
predictions = np.argmax(pred_test, axis=1)
conf_matrix = confusion_matrix(true_labels, predictions)

plt.figure(figsize=(10, 8))
sns.heatmap(conf_matrix, annot=True, cmap='GnBu', fmt='g', xticklabels=[emotions[i] for i in range(len(conf_matrix))], yticklabels=[emotions[i] for i in range(len(conf_matrix))], norm=LogNorm())

plt.title('Confusion Matrix')
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.show()

6. 基于深度学习的面部表情分类识别系统

        利用 Flask + Bootstrap 框架搭建响应式布局的交互分析 web 系统,利用 keras load_model 加载训练好的性能最佳的模型,提供标准化 rest api,提供面部表情的在线识别功能。

6.1 系统首页

6.2 面部表情在线识别

        通过上传待测试面部表情图片,提交预测后,后端调用模型进行表情预测,预测结果返回给前端进行渲染可视化,展示预测的标签类别,及各类标签预测的概率分布。

7. 结论

        本项目以 MobileNetV2 为基础模型构建面向面部表情识别的卷积神经网络, 完成模型的训练、验证和测试,面部表情识别准确率达到 85%以上。并利用 Flask + Bootstrap 框架搭建交互式分析平台,方便用户进行表情的识别。

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。技术交流、源码获取认准下方 CSDN 官方提供的学长 QQ 名片 :)

精彩专栏推荐订阅:

1. Python数据挖掘精品实战案例

2. 计算机视觉 CV 精品实战案例

3. 自然语言处理 NLP 精品实战案例

  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python极客之家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值