CASME2数据集入门指南:从数据预处理到微表情识别实战

1次阅读
没有评论

共计 2618 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

微表情识别与 CASME2 数据集简介

微表情是人类在试图隐藏真实情感时,面部肌肉短暂、不自主的微小动作,持续时间通常只有 1 /25 到 1 / 5 秒。这种非语言行为在心理治疗、安全审讯等领域具有重要价值。CASME2 是目前最权威的微表情数据集之一,包含 26 名受试者的 247 个样本,具有以下特点:

CASME2 数据集入门指南:从数据预处理到微表情识别实战

  • 高分辨率:所有视频帧均为 100×100 像素,聚焦面部区域
  • 精细标注:包含 AUs(面部动作单元)编码、起始帧、情绪类别等
  • 多模态数据:同时提供面部温度变化信息(需红外摄像头)

数据准备中的三大挑战

在实际使用 CASME2 时,初学者常会遇到这些难题:

  1. 视频帧提取复杂:原始 AVI 视频需要逐帧处理,且不同样本的时长差异大
  2. 标签解析困难:标注信息分散在 Excel 文件和视频文件名中
  3. 类别不均衡:”happiness” 类样本量是 ”disgust” 的 3 倍以上

实战准备工作

环境配置建议

推荐使用 Python 3.8+ 和以下库版本:

opencv-python==4.5.5.64
torch==1.11.0
pandas==1.4.2

数据预处理全流程

视频帧抽取与面部 ROI 裁剪

使用 OpenCV 进行关键帧提取时,要注意微表情的持续时间特征:

import cv2

def extract_frames(video_path, output_dir, fps=25):
    cap = cv2.VideoCapture(video_path)
    frame_count = 0

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        # 转换为灰度图并保存
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imwrite(f"{output_dir}/frame_{frame_count:04d}.jpg", gray)
        frame_count += 1

    cap.release()

标注文件解析技巧

AU_LOGGING.xlsx文件中包含关键的时间标注信息,建议这样处理:

import pandas as pd

def parse_annotations(excel_path):
    df = pd.read_excel(excel_path)
    # 提取微表情起止帧
    annotations = df[['Subject', 'OnsetFrame', 'ApexFrame']].copy()
    return annotations

解决类别不平衡问题

PyTorch 的 WeightedRandomSampler 能有效缓解样本不均衡:

from torch.utils.data import WeightedRandomSampler

# 计算每个类别的样本权重
class_counts = torch.bincount(labels)
class_weights = 1. / class_counts
sample_weights = class_weights[labels]

sampler = WeightedRandomSampler(
    weights=sample_weights,
    num_samples=len(sample_weights),
    replacement=True
)

3D-CNN 模型构建

相比传统 2D-CNN,3D 卷积能同时捕捉空间和时间特征。这里给出 P3D-ResNet 的简化实现:

import torch.nn as nn

class P3DBlock(nn.Module):
    def __init__(self, in_channels):
        super().__init__()
        # 空间卷积分支
        self.spatial = nn.Sequential(nn.Conv3d(in_channels, in_channels, kernel_size=(1,3,3), padding=(0,1,1)),
            nn.BatchNorm3d(in_channels),
            nn.ReLU())
        # 时间卷积分支
        self.temporal = nn.Sequential(nn.Conv3d(in_channels, in_channels, kernel_size=(3,1,1), padding=(1,0,0)),
            nn.BatchNorm3d(in_channels),
            nn.ReLU())

    def forward(self, x):
        return self.temporal(self.spatial(x))

训练过程中的关键技巧

  1. 梯度累积:当 GPU 显存不足时,可以通过多次前向传播累积梯度
optimizer.zero_grad()
for i, (inputs, labels) in enumerate(train_loader):
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    loss = loss / accumulation_steps  # 梯度累积
    loss.backward()

    if (i+1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()
  1. EarlyStopping 配置
from pytorchtools import EarlyStopping

es = EarlyStopping(patience=10, verbose=True)

for epoch in range(epochs):
    val_loss = validate()
    es(val_loss, model)
    if es.early_stop:
        break

效果评估与优化

在验证集上达到 0.65+ 的加权 F1-score 需注意:

  • 使用 sklearn.metrics.classification_report 计算各类别指标
  • 重点关注少数类别的召回率
  • 混淆矩阵能直观显示模型对相似表情(如 ”surprise” 和 ”fear”)的区分能力

常见问题解决方案

  1. 面部对齐问题
  2. 使用 dlib 或 MTCNN 进行人脸关键点检测
  3. 应用相似变换统一面部位置

  4. 过拟合应对

  5. 添加 SpatialDropout3D 层
  6. 使用 Label Smoothing 技术

开放性问题探讨

对于极低强度微表情的检测,可以考虑:
– 引入光流特征作为辅助输入
– 尝试 Transformer 架构捕捉长时序依赖
– 使用放大神经网络 (MicroExpNet) 增强微小运动

通过本教程,读者应该能够建立起完整的微表情识别流程。虽然 CASME2 数据集存在挑战,但通过合理的数据处理和模型设计,完全可以达到科研级的表现要求。

正文完
 0
评论(没有评论)