微表情——直抵内心深处最真实的情感

P粉084495128
发布: 2025-07-30 10:11:08
原创
1017人浏览过
该项目利用ResNet50卷积神经网络实现微表情分类并部署至手机端。数据集源自CASMEII,含7类微表情,按6:2:2划分为训练(2464张)、验证(822张)、测试(826张)集。基于Paddle框架训练,用Momentum优化器,验证集top1准确率达98.91%。通过Paddle-Lite部署到安卓手机,支持本地图片和摄像头预测,适用于情感识别等场景。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

微表情——直抵内心深处最真实的情感 - php中文网

0 项目简介

您是否有过以下困惑:

  1. 第一次约会中,内心小鹿乱撞,却摸不清他(她)对我的真实情感,是喜欢、犹豫还是......我应该怎么做,才能得到他(她)的真心呢?

  2. 青春期的孩子最为敏感,最为复杂,为人父母,管教过于温和怕起不到效果,过于激烈又会伤了孩子的自尊心,探寻他们内心深处的真实情感,才能对症下药。

现在,只需要fork本项目,安装一个微表情识别软件的手机,就能为你解决以上困惑,为你追求真爱,为你家庭和睦助上一臂之力。

  • 任务:本次实验是一个图像多分类问题,利用ResNet50卷积神经网络实现微表情分类,再部署至手机端。

  • 实践平台:百度AI实训平台-AI Studio、Python3.7+ Paddle2.2、Android Studio、华为手机。

该项目是本人为完成学校课程而创建的,数据集不能公开,在此深表歉意。

但模型文件(MicroExpression.nb)文件有,需要的朋友拿去手机端部署就ok,部署直接看第五版块。

针对此项目还存在的改进空间,以及这类场景在飞桨框架下的实现,希望大家多交流观点,fork优化,相互关注,共同学习进步个人主页。

1 数据集介绍

人类接触外界的过程通常伴随一系列复杂的心理活动,由此诱发情感,也称情绪。研究表明,情绪变化会在脸部产生表情,两者存在绝对的对应关系。
近年来,在人脸表情范畴下,新兴起一个细化的分支——微表情( Micro-Expression)。
登录后复制
       

猜猜左边这位大哥的微表情,看似一脸认真,其实他的标签是高兴哈哈哈哈哈

仔细观察右边这位小姐姐,眉头微微皱起,嘴角轻轻上扬,如此迷惑,其实她代表微表情的是压抑

微表情——直抵内心深处最真实的情感 - php中文网 微表情——直抵内心深处最真实的情感 - php中文网        

由此可见,未经正规训练过的人很难识别微表情所代表的真实情感。

 不同于传统的宏观表情,微表情具有如下特点:
登录后复制
       
  1.   真实的情绪,复杂心理活动
    登录后复制
               
  2.   非自主控制,不自觉流露
    登录后复制
               
  3.   持续时间短,强度弱,不易察觉
    登录后复制
                   

    其实,微表情研究在侦察讯问、安全司法、临床医学都有很好的应用前景,因此开发一套自动化设备,对微表情进行识别研究是很有必要的。

    微表情来源于中科院提供的CASMEII数据库,这些样本主要包括七类:高兴、惊讶、恐惧、悲伤、厌恶、压抑和其他。

由于样本量较少,因此训练集、验证集、测试集按照6:2:2划分。

训练样本量| 2,464张

验证样本量| 822张

测试样本量| 826张

加载使用方式|自定义数据集

1.1 数据标注

数据集分为train、valid、test三个文件夹,每个文件夹内包含7个分类文件夹,每个分类文件夹内是具体的样本图片。

In [ ]
!tree'''
├── classification2
│   ├── test
│   │   ├── disgust
│   │   │   ├── 1110013.jpg
│   │   │   ├── 1110016.jpg
│   │   │   ├── 111004.jpg

'''
登录后复制
   

config.py

__all__ = ['CONFIG', 'get']CONFIG = {    'model_save_dir': "./output/MicroExpression",    'num_classes': 7,    'total_images': 4112,    'epochs': 20,    'batch_size': 32,    'image_shape': [3, 224, 224],    'LEARNING_RATE': {        'params': {            'lr': 0.00375             
        }
    },    'OPTIMIZER': {        'params': {            'momentum': 0.9
        },        'regularizer': {            'function': 'L2',            'factor': 0.000001
        }
    },    'LABEL_MAP': [        "disgust",        "others",        "sadness",        "happiness",        "surprise",        "repression",        "fear"
    ]
}

def get(full_path):    for id, name in enumerate(full_path.split('.')):        if id == 0:            config = CONFIG        
        config = config[name]
    
    return config
登录后复制
   
In [2]
import ioimport osfrom PIL import Imagefrom config import get# 数据集根目录DATA_ROOT = 'classification2'# 标签ListLABEL_MAP = get('LABEL_MAP')# 标注生成函数def generate_annotation(mode):
    # 建立标注文件
    with open('{}/{}.txt'.format(DATA_ROOT, mode), 'w') as f:        # 对应每个用途的数据文件夹,train/valid/test
        train_dir = '{}/{}'.format(DATA_ROOT, mode)        # 遍历文件夹,获取里面的分类文件夹
        for path in os.listdir(train_dir):            # 标签对应的数字索引,实际标注的时候直接使用数字索引
            label_index = LABEL_MAP.index(path)            # 图像样本所在的路径
            image_path = '{}/{}'.format(train_dir, path)            # 遍历所有图像
            for image in os.listdir(image_path):                # 图像完整路径和名称
                image_file = '{}/{}'.format(image_path, image)                
                try:                    # 验证图片格式是否ok
                    with open(image_file, 'rb') as f_img:
                        image = Image.open(io.BytesIO(f_img.read()))
                        image.load()                        
                        if image.mode == 'RGB':
                            f.write('{}\t{}\n'.format(image_file, label_index))                except:                    continuegenerate_annotation('train')  # 生成训练集标注文件generate_annotation('valid')  # 生成验证集标注文件generate_annotation('test')   # 生成测试集标注文件
登录后复制
   

1.2 数据集定义

接下来我们使用标注好的文件进行数据集类的定义,方便后续模型训练使用。

1.2.1 导入数据集的定义实现

我们数据集的代码实现是在dataset.py中。

import paddleimport paddle.vision.transforms as Timport numpy as npfrom config import getfrom PIL import Image

__all__ = ['MicroExpression']# 定义图像的大小image_shape = get('image_shape')
IMAGE_SIZE = (image_shape[1], image_shape[2])class MicroExpression(paddle.io.Dataset):
    """
    微表情数据集类的定义
    """

    def __init__(self, mode='train'):
        """
        初始化函数
        """
        assert mode in ['train', 'test', 'valid'], 'mode is one of train, test, valid.'

        self.data = []        with open('classification2/{}.txt'.format(mode)) as f:            for line in f.readlines():
                info = line.strip().split('\t')                if len(info) > 0:
                    self.data.append([info[0].strip(), info[1].strip()])        if mode == 'train':
            self.transforms = T.Compose([
                T.RandomResizedCrop(IMAGE_SIZE),    # 随机裁剪大小
                T.RandomHorizontalFlip(0.5),        # 随机水平翻转
                T.ToTensor(),                       # 数据的格式转换和标准化 HWC => CHW  
                T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 图像归一化
            ])        else:
            self.transforms = T.Compose([
                T.Resize(256),                 # 图像大小修改
                T.RandomCrop(IMAGE_SIZE),      # 随机裁剪
                T.ToTensor(),                  # 数据的格式转换和标准化 HWC => CHW
                T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])   # 图像归一化
            ])        
    def __getitem__(self, index):
        """
        根据索引获取单个样本
        """
        image_file, label = self.data[index]
        image = Image.open(image_file)        if image.mode != 'RGB':
            image = image.convert('RGB')

        image = self.transforms(image)        return image, np.array(label, dtype='int64')    def __len__(self):
        """
        获取样本总数
        """
        return len(self.data)
登录后复制
   
In [1]
import paddleimport numpy as npfrom config import get

paddle.__version__
登录后复制
       
'2.2.2'
登录后复制
               
In [8]
from dataset import MicroExpression
登录后复制
   

1.2.2 实例化数据集类

根据所使用的数据集需求实例化数据集类,并查看总样本量。

In [9]
train_dataset = MicroExpression(mode='train')
valid_dataset = MicroExpression(mode='valid')print('训练数据集:{}张;验证数据集:{}张'.format(len(train_dataset), len(valid_dataset)))
登录后复制
       
训练数据集:2464张;验证数据集:822张
登录后复制
       

2 模型选择和开发

本次我们使用ResNet50网络来完成我们的案例实践。

来画数字人直播
来画数字人直播

来画数字人自动化直播,无需请真人主播,即可实现24小时直播,无缝衔接各大直播平台。

来画数字人直播 0
查看详情 来画数字人直播

2.1 模型介绍

以下项目对于ResNet50结构、功能有详细介绍,故在此不赘述,感兴趣的读者可以点击链接详细了解。

https://aistudio.baidu.com/aistudio/projectdetail/3405244?contributionType=1

In [ ]
# 模型选择和开发network = paddle.vision.models.resnet50(num_classes=get('num_classes'), pretrained=True)
登录后复制
   
In [ ]
model = paddle.Model(network)
model.summary((-1, ) + tuple(get('image_shape')))''''
-------------------------------------------------------------------------------
   Layer (type)         Input Shape          Output Shape         Param #    
===============================================================================
     Conv2D-1        [[1, 3, 224, 224]]   [1, 64, 112, 112]        9,408     
   BatchNorm2D-1    [[1, 64, 112, 112]]   [1, 64, 112, 112]         256      
      ReLU-1        [[1, 64, 112, 112]]   [1, 64, 112, 112]          0       
    MaxPool2D-1     [[1, 64, 112, 112]]    [1, 64, 56, 56]           0  
''''
登录后复制
   

3 模型训练和优化

其中关键API介绍如下:

CosineAnnealingDecay:

https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/lr/CosineAnnealingDecay_cn.html#cosineannealingdecay

Momentum:

https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/Momentum_cn.html#momentum

In [ ]
EPOCHS = get('epochs')
BATCH_SIZE = get('batch_size')def create_optim(parameters):
    step_each_epoch = get('total_images') // get('batch_size')
    lr = paddle.optimizer.lr.CosineAnnealingDecay(learning_rate=get('LEARNING_RATE.params.lr'),
                                                  T_max=step_each_epoch * EPOCHS)    return paddle.optimizer.Momentum(learning_rate=lr,
                                     parameters=parameters,
                                     weight_decay=paddle.regularizer.L2Decay(get('OPTIMIZER.regularizer.factor'))) #正则化来提升精度# 模型训练配置model.prepare(create_optim(network.parameters()),  # 优化器
              paddle.nn.CrossEntropyLoss(),        # 损失函数
              paddle.metric.Accuracy(topk=(1, 5))) # 评估指标# 训练可视化VisualDL工具的回调函数visualdl = paddle.callbacks.VisualDL(log_dir='visualdl_log')# 启动模型全流程训练model.fit(train_dataset,            # 训练数据集
          valid_dataset,            # 评估数据集
          epochs=EPOCHS,            # 总的训练轮次
          batch_size=BATCH_SIZE,    # 批次计算的样本量大小
          shuffle=True,             # 是否打乱样本集
          verbose=1,                # 日志展示格式
          save_dir='./chk_points/', # 分阶段的训练模型存储路径
          callbacks=[visualdl])     # 回调函数使用'''
Epoch 20/20
step 77/77 [==============================] - loss: 0.3286 - acc_top1: 0.9257 - acc_top5: 0.9984 - 139ms/step          
save checkpoint at /home/aistudio/chk_points/19
Eval begin...
step 26/26 [==============================] - loss: 0.0287 - acc_top1: 0.9891 - acc_top5: 1.0000 - 86ms/step          
Eval samples: 822
save checkpoint at /home/aistudio/chk_points/final

'''
登录后复制
   

top1 表示预测的第一个答案就是正确答案的准确率

top5 表示预测里面前五个包含正确答案的准确率

预测可视化:

微表情——直抵内心深处最真实的情感 - php中文网 微表情——直抵内心深处最真实的情感 - php中文网        
微表情——直抵内心深处最真实的情感 - php中文网 微表情——直抵内心深处最真实的情感 - php中文网        
微表情——直抵内心深处最真实的情感 - php中文网 微表情——直抵内心深处最真实的情感 - php中文网        
In [11]
# 将我们训练得到的模型进行保存,以便后续评估和测试使用。model.save(get('model_save_dir'))
登录后复制
   

4 模型评估和测试

4.1 测试数据集

In [12]
# 模型评估和测试predict_dataset = MicroExpression(mode='test')print('测试数据集样本量:{}'.format(len(predict_dataset)))
登录后复制
       
测试数据集样本量:826
登录后复制
       

4.2 执行预测

In [14]
from paddle.static import InputSpec# 网络结构示例化network = paddle.vision.models.resnet50(num_classes=get('num_classes'))# 模型封装model_2 = paddle.Model(network, inputs=[InputSpec(shape=[-1] + get('image_shape'), dtype='float32', name='image')])# 训练好的模型加载model_2.load(get('model_save_dir'))# 模型配置model_2.prepare()# 执行预测result = model_2.predict(predict_dataset)
登录后复制
       
Predict begin...
step 826/826 [==============================] - 17ms/step          
Predict samples: 826
登录后复制
       
In [ ]
from PIL import Imageimport matplotlib.pyplot as plt# 样本映射LABEL_MAP = get('LABEL_MAP')def show_img(img, predict):
    plt.figure()
    plt.title('predict: {}'.format(LABEL_MAP[predict_label]))
    image_file, label = predict_dataset.data[idx]
    image = Image.open(image_file)
    plt.imshow(image)
    plt.show()# 随机取样本展示indexs = [50,150 , 250, 350]for idx in indexs:
    predict_label = np.argmax(result[0][idx])
    real_label = predict_dataset[idx][1]
    show_img(real_label,predict_label )    print('样本ID:{}, 真实标签:{}, 预测值:{}'.format(idx, LABEL_MAP[real_label], LABEL_MAP[predict_label]))'''
<Figure size 432x288 with 1 Axes>
样本ID:50, 真实标签:happiness, 预测值:happiness
<Figure size 432x288 with 1 Axes>
样本ID:150, 真实标签:disgust, 预测值:disgust

'''
登录后复制
   

5 基于Paddle-Lite进行安卓部署

5.1 PaddleLite简介

Paddle-Lite 是飞桨推出的一套功能完善、易用性强且性能卓越的轻量化推理引擎。 轻量化体现在使用较少比特数用于表示神经网络的权重和激活,能够大大降低模型的体积,解决终端设备存储空间有限的问题,推理性能也整体优于其他框架。本部分以本案例的微表情数据集的ResNet50模型为例,介绍怎样使用Paddle-Lite,在移动端(基于华为麒麟985npu的安卓开发平台)对进行模型速度评估。

华为麒麟NPU部署参考链接: https://paddlelite.paddlepaddle.org.cn/v2.10/demo_guides/huawei_kirin_npu.html

由下图可见,NPU上的运算速率是CPU的数倍:

微表情——直抵内心深处最真实的情感 - php中文网        

说明:PaddleLite v2.10不支持鸿蒙系统下使用npu,若有需要,可按照上述链接改为EMUI系统。

In [ ]
# 模型部署model_2.save('infer/MicroExpression', training=False)
登录后复制
   

5.2 准备工作

文件:infer文件夹中的 .pdmodel .pdiparams 和下载到本地的image_classification_demo文件,下载链接如下:

https://github.com/PaddlePaddle/Paddle-Lite-Demo

工具:Android Studio、华为手机(开启USB调试模式)、USB数据线

Android Studio安装: https://blog.csdn.net/qq_41976613/article/details/91432304

通过以下命令,将.pdmodel 和 .pdiparams两个模型文件生成Android Studio可执行的.nb文件。

In [ ]
# 准备PaddleLite依赖!pip install paddlelite==2.10
登录后复制
   
In [ ]
# 准备PaddleLite部署模型#--valid_targets中参数(arm)用于传统手机,(huawei_kirin_npu,arm )用于华为带有npu处理器的手机!paddle_lite_opt \
    --model_file=infer/MicroExpression.pdmodel \
    --param_file=infer/MicroExpression.pdiparams \
    --optimize_out=./infer/ResNet \
    --optimize_out_type=naive_buffer \
    --valid_targets=huawei_kirin_npu,arm
登录后复制
   

5.2.1 配置文件_电脑

  • 在下载的Paddle-Lite-Demo进入以下目录,按下列步骤配置文件

Paddle-Lite-Demo-master\Paddle-Lite-Demo-master\PaddleLite-android-demo\image_classification_demo\app\src\main\assets

微表情——直抵内心深处最真实的情感 - php中文网        
  • 将待预测的图片放入ages文件夹
微表情——直抵内心深处最真实的情感 - php中文网        
  • 将数据标签文件放入labels文件夹

制作标签文件见 classfication2/train.txt
序号和类别的对应关系千万不能弄错了!

微表情——直抵内心深处最真实的情感 - php中文网        
  • 在models文件夹中放入自己的模型

创建子文件夹resnet_for_npu,将上述步骤生成的.nb文件下载到本地,并改名为model.nb

微表情——直抵内心深处最真实的情感 - php中文网    

5.2.2 配置环境_手机端

  1. 连续点击“版本号”以进入开发者模式
  2. 开启USB调试按钮
  3. USB配置选为PTP图片传输
微表情——直抵内心深处最真实的情感 - php中文网 微表情——直抵内心深处最真实的情感 - php中文网 微表情——直抵内心深处最真实的情感 - php中文网        

5.3 完成部署

  • 导入demo文件:

位置:Paddle-Lite-Demo-master\Paddle-Lite-Demo-master\PaddleLite-android-demo\image_classification_demo

  • 在strings.xml文件中修改三行字符:在 models/ labels/ images/ 后修改为上文添加文件的名称。

微表情——直抵内心深处最真实的情感 - php中文网        

  • 在Predictor.java文件中修改三行代码,改为如下内容:

微表情——直抵内心深处最真实的情感 - php中文网        

  • 当Android Studio右上角设备信息为HUAWEI时,点击绿色三角形按钮下载至手机端:
微表情——直抵内心深处最真实的情感 - php中文网    

5.4 效果展示

手机会自动出现以下画面

微表情——直抵内心深处最真实的情感 - php中文网        
Open Gallery可在本地相册中添加图片预测, Take Photo可调用手机摄像头进行拍摄预测, Settings可进行硬件性能的相关设置。

说明:由于我没有再把鸿蒙系统改为EMUI系统,故默认使用CPU进行预测,从预测时间几百ms可以看出,符合上文中官方给出的推理时间。

以上就是微表情——直抵内心深处最真实的情感的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号