MMI人脸表情数据库深度解析:FACS动作单元与动态时序标注实战
2026/9/9 12:38:12 网站建设 项目流程

简介:面向表情识别、模式识别与人机交互研究者的 MMI 面部表情数据库压缩资源,适用于训练 AU(动作单元)检测模型、表情分类算法以及研究表情动态演变过程。该数据集源自 MMI 数据库,包含大量标注视频对应的高清静态帧与动作单元标签,可服务于表情识别入门教学和科研实验。

本资源压缩包共 2000 个文件,内存放 6157 个 XML 标注文件与 493 张 JPG 图片,包体大小约 96.17 MB。XML 文件详细记录每帧 AU 的中性、起始、顶点、偏移阶段,图片则提供对应表情样本,便于按需组织训练集与测试集。文件命名规范以受试者编号、表情序列及 AU 标签为特征。

截止目前已有 500 人学习下载。获取后可以快速获得带细粒度 AU 阶段标注的面部表情样本集,无需再自行爬取或清洗大量数据,特别适合作为表情识别课程设计、论文实验或算法验证的基准数据,同时也可用于扩展多模态情感计算研究。 开始写这篇博文之前,先说句题外话:很多刚接触表情识别(Facial Expression Recognition,简称FER)的朋友,第一站通常都是CK+或者JAFFE,拿到一个数据集就迫不及待地训练分类器。但真到了做动态表情识别、做人脸动作单元(AU)检测、或者跑时序模型的时候,才会发现手里缺一个“既能给类别标签、又能给帧级动态标签”的数据库。这时候就绕不开MMI Facial Expression Database。

MMI是英国帝国理工学院Maja Pantic团队发布的开源人脸表情数据库,主要面向学术研究,距今已经迭代了十几年,仍然被顶会论文反复使用。它最核心的价值不在于“大”,而在于它把表情当作一个动态过程来建模:每个样本都是一段完整的视频序列,包含表情从无到有、再到消退的整个过程,同时提供基本情绪标签和FACS动作单元(AU)标注。这篇博文我想从数据库结构、FACS标注原理、实际下载上手、训练避坑这几个维度,把我的使用经验完整讲一遍,尤其适合那些准备把MMI当实验数据跑模型的研究生和工程师。

1. MMI Facial Expression Database 到底是什么

1.1 一个“会动”的表情库,而不是静态照片集

先纠正一个常见误解。很多人以为MMI就是一个比JAFFE大一点的人脸图片库,其实它是以视频序列为核心的数据集。官方早期的版本大约包含1500段样本,受试者75人,年龄分布在19到62岁,其中有约10%的非欧裔受试者。后来项目组发布了增强版(通常称为Deluxe版本),样本量进一步扩展到2900段以上的视频和静态图像,采集角度也覆盖了正面和侧面视角。

和CK+这类从“中性脸”直接突变到“峰值表情”的库不同,MMI的每段视频都刻意记录了完整的表情演变过程:受试者从平静状态开始,逐渐做出某个表情,强度达到最高点,然后再缓慢恢复平静。这个特性在做时序模型时非常关键,因为动态模型需要看到表情的出生和消退,才能学到肌肉变化的轨迹,而不是只凭一张峰值图去猜表情类别。

1.2 版本与目录结构里的“隐藏资源”

MMI在官网上下载时,一般会看到两个主要大目录,一个是原始版本(Original),一个是后来的增强版本(Deluxe)。Deluxe版本并不是简单的“原版加了点视频”,而是在录制环境、受试者数量、样本标注上做了整体升级,所以如果你是新用户,直接下Deluxe版本就好,原始版本可以留作跨版本对比实验。

还有一个容易被忽略的资源:部分序列带有多模态信息,比如音频和侧面视角。做情感计算的同学,其实可以拿这些数据做音视频双模态的预训练,不一定非要去找另外的AV数据集。目录里还会出现以“S”开头的文件夹,比如S010、S023,这个S代表受试者编号(Subject ID),后面跟的具体数字是样本编号。用受试者编号做数据划分,是所有严谨实验的默认前提,这点后面细讲。

2. FACS、AU 和动态标签:MMI 比“表情分类”更吸引人的地方

2.1 FACS编码:把表情拆成肌肉动作的“解剖学语言”

说到MMI就不可能不提FACS(Facial Action Coding System)。FACS是上世纪70年代由Paul Ekman和Wallace Friesen提出的面部动作编码系统,它的基本单位叫做Action Unit(AU),也就是“动作单元”。简单理解,AU就是对面部肌肉活动的“原子化描述”,比如AU1是眉毛内侧上扬,AU4是眉毛皱起,AU6是脸颊提升,AU12是嘴角向斜上方拉动,AU26是下颌放松下降。

MMI的标注体系里,很多样本同时给了情绪类别标签(愤怒、厌恶、恐惧、快乐、悲伤、惊讶)和AU标签。这意味着同一个数据库既能用来训练“给我判断这个人在笑”的分类器,也能用来训练“请定位嘴角附近哪块肌肉在动”的AU检测模型。这对模型可解释性的提升特别大:你可以在网络中间层把AU特征抽取出来,再反推类别决策,相当于给黑盒模型装了一个显微镜。

2.2 Onset-Apex-Offset:真正的时间结构

MMI最让我欣赏的设计,是它在录制阶段就刻意强调时间结构。一段表情视频通常分为三个阶段:onset(表情刚出现)、apex(表情强度最大)、offset(表情回归中性)。很多论文里直接称这段结构为“表情三阶段”。

在实操中,这个结构对建模方式有直接影响。如果你用2D-CNN做静态识别,那只需要抽取apex帧就行;但如果你想做3D-CNN、视频Transformer、RNN这类动态模型,整段onset-apex-offset序列都是可用的训练信号。我在实际实验中对比过:把完整序列输入时序模型,比单纯用峰值帧堆叠出来的“伪序列”效果要好不少,尤其在细粒度情感区分上,动态信息能明显降低愤怒和厌恶之间的混淆。

2.3 情绪标签与AU标签的对应关系

MMI里的情绪标签不是简单“一个人给一个label”,它有专门的组织方式。部分是单一情绪(single),比如一段视频只表达快乐;部分则是双情绪(duo),比如“愤怒+厌恶”这种复合标签。这种复合标签对真实场景很有意义,因为人的表情极少是纯单一的,往往是混合状态。

不过要提醒一句:AU标签和情绪类别标签并不是每个样本都同时齐全。有的样本只有AU标注,有的样本只有离散情绪标签,有的样本两种都有。做多任务学习之前,一定要先统计你打算使用的子集到底有多少样本带完整双标注,不要盲信网上的二手描述,自己写一段脚本统计一下最保险。

3. 横向对比 CK+、JAFFE、FER2013,看看MMI更适合什么场景

为了把MMI的定位讲清楚,我拿几个高频使用的数据库放在一起比一下。

数据库样本类型规模标注类型是否动态典型应用场景
MMI视频序列/图像约1500~2900+(扩增版)6种基本情绪+双情绪、AU逐帧是,完整onset-apex-offset动态表情识别、AU检测、复合情绪建模
CK+视频序列593个序列,123人8种情绪标签、AU标签弱,从中性到峰值静态/峰值表情识别,FER基线
JAFFE静态图像213张,10人6种情绪+中性早期静态分类算法验证
FER2013静态图像约35887张7种情绪类别大规模静态分类、Kaggle竞赛
RAF-DB静态图像约3万张7种基本+12种复合真实场景、复合表情识别

从表格可以看得很明显:CK+样本数不多,且它的视频大多在中性到峰值就结束了,看不到表情消退过程;JAFFE适合跑通baseline,但数据量和多样性都不适合现代深度模型大规模训练;FER2013虽然是静态库里的大规模选择,但标签噪声也是出了名的高。

MMI在这个矩阵里的不可替代性,恰恰是它同时具备“动态过程视频”和“精细AU标注”两个特性。如果你要做情感计算的时序模型、做面部肌肉运动轨迹的生成、或者在自监督预训练里找一个带帧级标注的数据集,MMI几乎是绕不开的。它未必是最适合刷分的,但一定是最适合研究“表情为什么产生、怎么变化”的数据库。

4. 实操:申请下载、目录解析与第一次上手

4.1 申请与下载注意点

MMI可不是在官网点一个Download按钮就能拿到的。官方地址是mmifacedb.eu,进去之后需要填写一份学术用途申请表,说明你的机构、研究方向和预期用途。审核周期通常几天,通过之后会收到下载链接或者FTP信息。填表时写清楚“用于学术研究”基本都没问题,如果你是商业用途,那大概率会被拒绝,这个数据库的授权协议本身就偏向非商业研究。

有朋友喜欢在第三方网盘上找现成的压缩包,我不推荐这么干。原因很简单:网络上流传的版本很可能是不完整的,或者目录结构被人改过,帧序混乱,标签文件和视频对不上,最后浪费的时间比自己申请多得多。正规渠道下来以后压缩包通常有几个GB,Deluxe版本会更大,提前清理好磁盘空间。

4.2 目录命名与帧序列读取

解压后你会看到类似这样的路径结构:

MMI_Deluxe/S010-001/ face_1.bmp face_2.bmp ... face_88.bmp

这里的S010-001表示“第010号受试者的第001号样本”。文件夹里通常是一串按顺序编号的帧图片,而不是一个打包好的MP4。原因在于数据集发布的年头比较早,帧序列格式对研究者更友好,方便你自由决定怎么抽帧。

读取时直接用OpenCV循环读图就行,但要注意文件名的排序问题,下面这段代码是我常用的小工具,能按文件名里的数字序号正确排序并按顺序拼成列表:

import os import cv2 def load_frames_from_dir(frame_dir): files = [f for f in os.listdir(frame_dir) if f.lower().endswith(('.bmp', '.jpg', '.png', '.jpeg'))] files.sort(key=lambda x: int(''.join(filter(str.isdigit, x)) or 0)) frames = [] for fname in files: path = os.path.join(frame_dir, fname) img = cv2.imread(path) if img is not None: frames.append(img) return frames

4.3 标签文件与AU区间解析

标签文件的格式在官网文档里会有详细说明。以某个样本为例,它可能包含一个文本文件,记录某个动作单元在哪些帧开始、哪些帧达到峰值、哪些帧结束。解析这类文件的核心逻辑是:把AU索引映射到时间区间,再生成帧级AU标签向量。

这里给出一个小函数思路,方便你把文本标签转成时序标签:

def parse_au_annotation(label_file, total_frames): au_sequence = [[0] * 68 for _ in range(total_frames)] # 预留AU数量 with open(label_file, 'r') as f: for line in f: parts = line.strip().split() if len(parts) < 4: continue au_id = int(parts[0]) onset = int(parts[1]) apex = int(parts[2]) offset = int(parts[3]) for t in range(max(0, onset), min(total_frames, offset + 1)): au_sequence[t][au_id] = 1 return au_sequence

注意不同样本的帧数不一样,解析前最好先读帧目录计算出总帧数,再对标签做裁剪或对齐。

4.4 中间产物:把“文件夹森林”转成结构化数据集

如果你准备好好做实验,我的建议是不要每次训练都去遍历原目录。提前写一个预处理脚本,把视频帧打包成压缩的numpy数组、把标签转成统一格式的CSV、把受试者ID单独存一列,会省下大量时间。最后保存成一个标准化的中间格式,无论是加载到PyTorch还是TensorFlow都会顺畅很多。

5. 用MMI做实验容易踩的五个坑

5.1 别把样本数直接当视频数,先做质量过滤

MMI里的序列虽然都是经过标注的,但实验时不是每个样本都能直接用。有些视频过短,表情刚起来就结束了;有些受试者戴眼镜、留胡子,或者头部转动幅度太大,容易干扰对齐。我通常会用一个人脸关键点检测器跑一遍,把关键点置信度过低的帧直接过滤掉,然后再看剩余帧数是否足够训练。这一步很费时,但能明显提升最终准确率。

5.2 划分训练集和测试集时,务必按受试者隔离

这是很多初学者最容易忽略的问题。如果只按样本随机划分,同一个人的多个表情片段会同时出现在训练集和测试集,模型相当于在“开卷考试”,最后跑出来的指标虚高一大截。正确做法是按Subject ID做留出法,比如留出20%的受试者作为测试集,或者做LOSO(Leave-One-Subject-Out)验证。你可以在预处理阶段就把subject_id单独保存,后续所有划分逻辑都基于这个字段。

5.3 帧率不统一,长度对不齐

MMI是不同时期采集的,帧率不完全一致,而且每个样本的序列长度也各有差异。在做时间序列模型时,你不能直接把变长序列塞进一个固定尺寸的batch里。常见解法有:

  • 设定一个标准长度(比如32帧或64帧),对长序列做均匀采样,对短序列做padding或者复制补齐。
  • 如果更关注apex附近的特征,直接以峰值帧为中心,截取前后固定窗口。

我在实验中发现,均匀采样到相同帧数再训练,比直接保留原始长度加mask的训练方式更稳定,至少在3D-CNN和Transformer类模型上是这样。

5.4 AU标签时间轴可能有误差,别把它当绝对真值

MMI的AU标注虽然已经很精细,但它是人工标注的,存在一定的模糊地带。尤其“onset”和“offset”这两个时间点,不同标注员的理解可能略有差异。如果你做逐帧AU分类,直接用这个时间轴当硬标签,模型会在边界帧上反复震荡。我的经验是采用“标签平滑”或者“弱监督窗口”策略:只在小范围内惩罚边界误判,或者把峰值附近窗口作为正样本,把远离峰值且接近中性的位置作为负样本,这样模型会稳定很多。

5.5 跨数据库对比时,协议口径必须统一

不少论文会同时报告MMI和CK+上的结果。问题是CK+的视频大多是“中性到峰值”就结束,MMI则有完整的offset阶段,两者的数据分布差异很大。如果你在CK+上取最后几帧做静态识别,在MMI上取峰值帧做静态识别,标准不统一,直接横向对比就不公平。建议跨库比较时都统一采用“峰值帧集合”或者在两个库上走同一套动态模型+同样的帧采样策略,否则你看到的高低之分很可能只是协议差异造成的。

6. 一点实际体会

我自己第一次用MMI的时候,其实挺崩溃的,因为它的标注文件和目录结构比FER2013这种“拿到就能训”的库要复杂得多。但后来把预处理脚本写顺之后,它反而成了我最喜欢的数据集之一。尤其是做动态表情生成实验时,MMI里那段逐渐放松的表情回归过程,给了我很多静态数据集永远无法提供的训练信号。如果你也打算在这上面跑实验,我建议先拿一个小子集把整条pipeline(读帧、对齐、标签解析、模型训练)跑通,再放大到全量数据,不要一上来就做全库,很容易被数据预处理的问题淹没。最后再分享一个小技巧:做跨域预训练的时候,可以用MMI的AU标签去构造一个自监督任务,比如随机遮盖某个时间步的AU序列,让模型去预测被遮住的部分,这样学到的时序特征在做表情分类微调时,往往比直接用表情类别标签从零训练效果更好。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询