PAYATHON 2026

如何为 deep learning 面部情绪识别项目设计 dfd 和 ER diagram?

技术老齐

建议将两种输入统一建模为“识别任务”。每个任务固定使用 upload 或 webcam,共用后续的人脸检测、预处理和情绪分类流程。DFD 描述数据如何流动,ER diagram 描述需要保存的数据及其关系。

“每次只能选择一种方式”应落实为任务约束。如果还要求同一用户不能同时运行两个任务,就需要额外的并发控制。

1. 明确系统边界

设计以这些前提为基础:

  • 系统使用已训练好的模型进行推理,暂不包含模型训练。
  • 上传模式处理一张图像;webcam 模式持续处理采样帧。
  • 系统保存任务和识别结果,是否保存原始图像由需求决定。
  • 一张图像可能包含多张人脸,因此可以产生多条分类结果。

如果项目只展示实时结果、不保存历史记录,ER 图可以简化。用户登录、模型训练和人工标注等功能,也应在确定需要后再加入。

2. DFD:上下文图与一级分解图

上下文图

上下文图将整个应用视为一个处理过程,只展示系统与外部实体之间的数据交换。

flowchart LR
    U["用户端"]
    P0(("0 面部情绪识别系统"))

    U -->|"输入模式、上传图像或摄像头帧、开始或停止请求"| P0
    P0 -->|"任务状态、人脸位置、情绪标签及分数、错误信息"| U

这里将浏览器及其 webcam 采集功能放在系统边界之外,系统接收用户端提交的图像数据。如果摄像头采集模块属于应用内部,就应调整边界,将采集过程画入系统。

不同课程对 DFD 层级的命名可能不同。明确标注“上下文图”和“一级分解图”,可以避免只写 Level 0、Level 1 带来的歧义。

一级分解图

两种输入接入后,共用同一条识别流程:

flowchart LR
    U["用户端"]

    P1(("1.0 接入与校验"))
    P2(("2.0 人脸检测与预处理"))
    P3(("3.0 情绪分类"))
    P4(("4.0 整理并返回结果"))

    D1[("D1 任务、样本与结果库")]
    D2[("D2 模型仓库")]

    U -->|"输入模式、图像或帧、开始或停止请求"| P1

    D2 -->|"可用模型版本与配置"| P1
    P1 -->|"任务与样本记录"| D1
    P1 -->|"有效图像或帧、任务及样本标识"| P2
    P1 -->|"校验错误或任务状态"| P4

    P2 -->|"人脸张量、边界框、样本标识"| P3
    P2 -->|"未检测到人脸或预处理错误"| P4

    D2 -->|"模型权重、预处理配置、标签映射"| P3
    P3 -->|"各人脸的情绪标签、分数及位置"| P4

    P4 -->|"识别结果与状态更新"| D1
    P4 -->|"识别结果、任务状态或错误信息"| U
处理过程主要职责
接入与校验校验任务模式、输入类型和文件内容,接收 webcam 帧,处理任务开始与结束
人脸检测与预处理定位人脸,按模型要求裁剪、缩放、归一化或对齐
情绪分类加载指定模型,对每张人脸执行推理,映射输出标签
整理并返回结果关联任务、样本和人脸位置,保存结果并返回用户端

预处理必须与模型训练时的要求一致。输入尺寸、颜色通道和归一化方法都应以实际模型配置为准。

如何表达两种模式互斥

DFD 的箭头表示数据流,程序分支需要用其他方式表达。可以在图旁补充业务规则:

一个识别任务只能绑定一种输入模式。上传模式接收上传图像;webcam 模式接收摄像头帧。切换模式时结束当前任务,再创建新任务。

“用户选择模式”的判断菱形适合放在流程图或活动图中。正式提交 DFD 时,应按要求使用 Yourdon/DeMarco 或 Gane–Sarson 等符号体系;上述 Mermaid 图用于表达数据流结构。

3. ER diagram:任务、样本与预测结果

建议使用以下实体:

实体含义
RECOGNITION_TASK一次上传识别,或一次 webcam 检测会话
INPUT_SAMPLE一张上传图像,或一个被处理的摄像头帧
PREDICTION某个样本中一张人脸的分类结果
MODEL_VERSION本次任务使用的模型版本及相关配置
erDiagram
    MODEL_VERSION ||--o{ RECOGNITION_TASK : used_by
    RECOGNITION_TASK ||--o{ INPUT_SAMPLE : contains
    INPUT_SAMPLE ||--o{ PREDICTION : produces

    MODEL_VERSION {
        string model_version_id PK
        string weights_ref
        string preprocessing_ref
        string label_mapping_ref
    }

    RECOGNITION_TASK {
        string task_id PK
        string model_version_id FK
        string input_mode
        string status
        datetime started_at
        datetime ended_at
    }

    INPUT_SAMPLE {
        string sample_id PK
        string task_id FK
        int frame_index
        bigint offset_ms
        string storage_uri
        string status
    }

    PREDICTION {
        string prediction_id PK
        string sample_id FK
        int face_index
        string emotion_label
        float score
        float bbox_x
        float bbox_y
        float bbox_width
        float bbox_height
    }

这里假定每个任务固定使用一个模型版本。如果需要在同一任务中比较多个模型,就应重新设计模型与预测结果的关联。

关系与字段说明

一个任务可以有零到多个样本。刚创建、尚未收到输入或接入失败的任务可能没有样本。上传任务成功接收图像后只有一个样本,webcam 任务可以有多个样本。

一个样本可以有零到多条预测结果:

  • 未检测到人脸时,只记录样本状态,不创建预测记录。
  • 检测到一张人脸时,创建一条预测记录。
  • 检测到多张人脸时,每张人脸各创建一条预测记录。

face_index 用于区分同一样本内的人脸,不代表人物身份。跨帧跟踪同一个人,需要另行设计跟踪标识。

storage_uri 可以为空,表示只保存处理记录和结果,不保留原始图像。webcam 场景也不必将所有原始帧写入数据库。

建议补充以下约束:

  • input_mode 必填,取值限定为 upload 或 webcam。
  • (task_id, frame_index) 唯一,防止重复写入同一帧。
  • (sample_id, face_index) 唯一,前提是每张人脸只保存一条最终分类结果。
  • 上传任务只允许一个样本,webcam 任务允许多个样本。这项跨表规则需要由应用逻辑或数据库触发器实现。

如果项目有账号和历史记录查询功能,可以增加 USER 实体,通过 user_id 关联任务。DFD 中的外部实体“用户”并不意味着数据库必须有用户表。

4. 代码示例:校验输入模式与数据是否匹配

这段 Python 代码用于校验任务创建后的图像数据请求。task_mode 应从任务记录中读取。

def select_payload(task_mode, image_bytes=None, frame_bytes=None):
    if task_mode == "upload":
        if image_bytes is None or frame_bytes is not None:
            raise ValueError("Upload mode requires only image_bytes.")
        return image_bytes

    if task_mode == "webcam":
        if frame_bytes is None or image_bytes is not None:
            raise ValueError("Webcam mode requires only frame_bytes.")
        return frame_bytes

    raise ValueError("Unsupported task mode.")

代码只校验数据来源是否与任务模式匹配。实际接入时,还需要检查任务状态、图像能否解码,以及上传任务是否已接收过图像。开始、停止等控制请求应使用各自的校验逻辑。

如果“每次只能选择一种方式”还要求同一用户只能有一个运行中的任务,就需要在创建任务时使用事务、锁或适合所用数据库的唯一性约束。仅禁用前端按钮,无法防止多标签页或并发请求。

切换模式时,还应停止旧任务的采集和请求,并按 task_id 丢弃旧任务迟到的结果,避免将结果显示到新任务中。

5. 设计时容易遗漏的细节

情绪标签应使用实际模型的标签映射,不能在图中默认某一套分类。也需要说明 score 的含义:即使模型输出分数位于 [0, 1],也不能直接将其解释为识别正确的概率。

webcam 持续输入图像,需要明确采样策略,以及如何处理积压帧。只有实际送入识别流程的帧,才需要记录为 INPUT_SAMPLE。

未检测到人脸、摄像头权限被拒绝、图像无法解码和模型推理失败,都应通过状态或错误信息表达,避免统一返回一个情绪标签。

面部表情分类结果应表述为模型对图像的预测,不能直接作为判断当事人真实心理状态的依据。保存原始图像前,也应明确访问权限、保存期限和删除方式。

备注:内容仅供参考。