safesight-edge/docs/design/FaceRecognition_TrackAware_Alarm_Design.md

481 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 人脸识别按轨迹聚合告警设计
## 1. 背景
当前人脸识别告警链路为:
`face_det -> face_recog -> alarm.face_rules -> actions`
现有链路已经具备以下能力:
- 从 gallery 中识别已知人员
- 基于单帧识别结果判定 `known``unknown`
- 生成 `known_person``unknown_face` 告警
- 通过现有 alarm action 链路上传截图和视频片段
但当前告警行为仍然主要由单帧人脸识别结果驱动。在车间测试中,同一个已知人员可能出现:
- 近距离、高质量帧触发 `known_person`
- 远距离、小脸、低质量帧触发 `unknown_face`
这不符合目标场景要求。对当前车间场景来说:
- 低质量人脸数据可以直接忽略
- 告警准确率优先于告警召回率
- 告警频率需要尽量低
- 已知人员告警用于后台打卡
- 人员短暂离场再进入,不应重复触发打卡告警
仓库中已经有人体 tracker 和基于 `track_id` 的鞋子识别逻辑。本设计优先复用这套能力,而不是再新增一套独立的人脸 tracker。
## 2. 目标
### 2.1 功能目标
- 复用现有人体 `track_id` 进行人脸身份聚合
- 不再把 `unknown` 简单视为 `known` 的反面
- 对低质量人脸直接忽略,而不是强行归类为 `unknown_face`
- 告警由“按单帧”改为“按人轨迹”
- 同一个人持续在场时不重复触发告警
- 人员短时离场再进入时不立即重复告警
### 2.2 非目标
- 不替换现有人体 tracker 实现
- 不新增独立的人脸 tracker
- 不修改人脸 embedding 提取和 gallery 检索逻辑
- 不把检测、识别、跟踪、告警合并到一个插件中
## 3. 现状分析
### 3.1 已有能力
- `plugins/tracker/tracker_node.cpp`
- 会给 `frame->det` 中的人体检测框写入稳定的 `track_id`
- `plugins/logic_gate/logic_gate_node.cpp`
- 已经基于人体 `track_id` 做鞋子关联与规则判断
- `plugins/ai_face_det/*``plugins/ai_face_recog/ai_face_recog_node.cpp`
- 已经能输出人脸检测和人脸识别结果
- `plugins/alarm/alarm_node.cpp`
- 已经支持人脸规则和现有告警 action 链路
### 3.2 当前缺口
当前人脸链路实际上没有接入人体跟踪能力:
- `FaceDetItem` 虽然有 `track_id` 字段,但当前人脸检测节点都填的是 `-1`
- `FaceRecogItem` 只保留了 gallery 身份字段,如 `best_person_id`
- 当前人脸告警投票 key 为:
- 已知人规则使用 `best_person_id`
- 陌生人规则直接使用固定值 `unknown`
这意味着当前人脸告警链路无法回答以下问题:
- 两帧是否属于同一个真实人
- 某一帧的低分结果是否属于刚刚已经识别成功的那个人
- 某人还在画面中时,是否应该抑制重复告警
## 4. 设计概述
本设计在现有人体跟踪之上增加“按轨迹聚合的人脸身份确认层”。
改造后的行为如下:
1. 人体检测继续由现有 tracker 生成 `track_id`
2. 每张识别出的人脸在同帧内关联到一个人体框
3. 将关联后的人体 `track_id` 写入人脸识别结果
4. `alarm``person_track_id` 聚合多帧识别证据
5. 身份判定改为三态:
- `known`
- `unknown`
- `uncertain`
6. 只有稳定的 `known` 或稳定的 `unknown` 才允许触发告警
7. `uncertain` 状态直接忽略,不触发身份类告警
这样可以保持当前 DAG 架构和插件边界不变:
- tracker 只负责跟踪人体
- 人脸插件只负责输出识别证据
- alarm 节点负责业务层面的身份确认、去重和抑制
## 5. 数据流设计
目标运行链路变为:
`person_det -> tracker -> face_det -> face_recog(face-person association) -> alarm(track-aware face rules) -> actions`
### 5.1 人脸与人体关联
对每一张识别出的人脸,在同一帧的 `frame->det` 中寻找一个已经具备有效 `track_id` 的人体框进行关联。
建议采用以下匹配顺序:
1. 优先选择“人脸中心点落在人框内”的人体框
2. 若存在多个候选,则选择重叠关系最合理的那个
3. 若不存在包含关系,可选地退化到 IoU / overlap ratio 匹配
4. 若仍无可靠匹配,则该人脸视为未关联成功
这个方案简单、稳定,也更适合当前车间摄像头场景,因为正常情况下一个人脸应当落在一个人体框内部。
### 5.2 结果增强
对人脸识别结果增加与人体轨迹关联后的字段。
建议给 `FaceRecogItem` 增加:
- `int person_track_id = -1`
- 可选预留字段:`float person_match_score`
这样下游插件可以直接消费“带有人体连续性信息的人脸识别结果”,而不用再次读取原始人体框做推断。
## 6. 身份状态模型
`alarm` 节点中,按 `person_track_id` 维护一份短生命周期的人脸身份聚合状态。
建议维护的字段包括:
- `track_id`
- `first_seen_ms`
- `last_seen_ms`
- `last_quality_pass_ms`
- `best_known_person_id`
- `best_known_name`
- `best_sim_peak`
- `best_known_hit_count`
- `quality_pass_count`
- `unknown_candidate_count`
- `reported_known`
- `reported_unknown`
- `last_report_ms`
这份状态在轨迹有效期间存在,并在短暂 retention 窗口内保留,用于实现短时离场重入抑制。
## 7. 三态判定模型
### 7.1 状态定义
每个 `person_track_id` 只能处于以下三种状态之一:
- `uncertain`
- 质量不足,或证据不足
- `known`
- 已经稳定确认属于某个已知人员
- `unknown`
- 已经稳定确认无法归属到已知人员
### 7.2 为什么必须引入 `uncertain`
`uncertain` 是本方案的关键。
以下情况都应保持为 `uncertain`
- 人脸太小
- 对齐质量差
- 运动模糊
- 距离过远
- 相似度波动明显
- 当前轨迹累计证据不足
这些观察结果都不应直接触发身份类告警。
## 8. 质量门控
只有通过质量门控的人脸观测,才允许进入身份聚合逻辑。
建议质量条件包括:
- 已关联到有效 `person_track_id`
- 人脸面积占比达到下限
- 人脸长宽比处于合理范围
- 当需要对齐时,必须具备有效 landmarks
- 可选:人脸最小像素宽高门限
- 可选:最小人脸检测置信度
若某一帧未通过质量门控:
- 不计入 `unknown`
- 不计入 `known`
- 保持该轨迹状态为 `uncertain`
这与当前车间场景的业务要求一致:低质量数据可以直接忽略。
## 9. 已知人确认策略
已知人确认必须基于“同一人体轨迹内,对同一 gallery 身份的持续命中”。
建议条件如下:
- 当前帧通过质量门控
- `best_person_id >= 0`
- `best_sim >= known_accept`
- `(best_sim - second_sim) >= known_margin`
-`known_hit_window_ms` 时间窗内,同一个 `best_person_id` 至少命中 `known_min_hits`
可选增强:
-`best_sim` 足够高且连续稳定,可允许 peak-sim 快速确认
一旦某条轨迹稳定进入 `known`
- 触发一次 `known_person`
- 标记该轨迹 `reported_known = true`
- 在该轨迹存活期间不再重复触发已知人告警
## 10. 陌生人确认策略
陌生人确认必须比已知人确认更保守。
陌生人不应被定义为:
- “这一帧不是 known”
陌生人应被定义为:
- “这个人已经被持续观察了足够长时间,且人脸质量足够,但始终无法稳定归入任何已知身份”
建议条件如下:
- 当前帧通过质量门控
- 存在有效 `person_track_id`
- 轨迹存活时间超过 `unknown_min_track_age_ms`
- 质量合格帧数达到 `unknown_min_quality_hits`
- 该轨迹尚未稳定确认过已知人
- 在观察窗口内始终未满足已知人确认条件
可选附加条件:
- top1 候选身份长期不稳定
- 多帧均处于低置信或模糊匹配状态后,才允许最终确认陌生人
一旦某条轨迹稳定进入 `unknown`
- 触发一次 `unknown_face`
- 标记该轨迹 `reported_unknown = true`
- 在该轨迹存活期间不再重复触发陌生人告警
## 11. 告警去重与重入抑制
### 11.1 轨迹内去重
在同一个活跃 `person_track_id` 内:
- `known_person` 最多只允许触发一次
- `unknown_face` 最多只允许触发一次
### 11.2 离场重入抑制
当前场景中的已知人告警,本质上是打卡行为,因此:
- 同一个员工仍在画面中时,不应重复打卡
- 同一个员工短暂离开又回来时,也不应立即重复打卡
建议引入两类抑制 key
- 已知人:按 `gallery person_id` 做冷却
- 陌生人:按最近轨迹历史做冷却,后续可再增强为更稳定的陌生人指纹
建议增加两个可配置时间:
- `known_reentry_cooldown_ms`
- `unknown_reentry_cooldown_ms`
对于已知人,冷却时间应当相对较长,因为打卡行为本来就应当是稀疏的。
## 12. 配置设计
建议在 `alarm` 侧新增一组专门的人脸轨迹聚合配置。可以挂在 face rule 相关路径下,或作为 alarm 的一个同级子配置。
建议字段如下:
```json
{
"face_track_aggregation": {
"enable": true,
"associate_with_person_track": true,
"require_person_track": true,
"person_match_mode": "face_center_in_person",
"person_match_min_iou": 0.05,
"quality": {
"min_face_area_ratio": 0.001,
"min_face_width": 32,
"min_face_height": 32,
"require_landmarks": true
},
"known": {
"accept": 0.45,
"margin": 0.05,
"min_hits": 3,
"hit_window_ms": 3000,
"reentry_cooldown_ms": 300000
},
"unknown": {
"min_track_age_ms": 2000,
"min_quality_hits": 4,
"reentry_cooldown_ms": 300000
}
}
}
```
说明:
- 具体挂载位置可再根据现有配置风格微调
- 尽量保留现有 face rule 字段,避免一次性破坏旧配置
- 迁移时应优先保证兼容性和平滑切换
## 13. 文件级改动建议
### 13.1 数据结构
修改:
- `include/face/face_result.h`
改动内容:
-`FaceRecogItem` 增加 `person_track_id`
- 可选预留后续关联置信度等扩展字段
### 13.2 人脸识别节点
修改:
- `plugins/ai_face_recog/ai_face_recog_node.cpp`
改动内容:
- 对每张识别结果做人脸与人体关联
- 将关联后的人体 `track_id` 写入 `FaceRecogItem`
- 扩展 debug 日志,输出 `person_track_id`
### 13.3 告警节点
修改:
- `plugins/alarm/alarm_node.cpp`
改动内容:
- 增加按轨迹聚合的人脸身份状态
- 用按 `track_id` 的持续观察,替代当前单帧驱动的陌生人确认逻辑
- face vote key 优先使用 `person_track_id`
- 增加已知人 / 陌生人的按轨迹去重和离场重入抑制
### 13.4 测试
建议新增或修改以下平台无关测试:
- 人脸与人体关联逻辑测试
- 按轨迹已知人确认测试
- 按轨迹陌生人抑制测试
- 离场重入冷却测试
## 14. 兼容性与迁移策略
该设计应以“向后兼容优先”的方式落地。
建议策略:
1. 保留现有 face recognition 输出字段
2. 用新增字段而不是重命名旧字段
3. 当 track-aware aggregation 未开启时,继续支持当前旧行为
4. 在 rollout 期间允许旧 face rules 与新聚合模式并存,用于对比效果
这样可以实现:
- 更安全的分阶段上线
- 便于对比新旧逻辑行为差异
- 更容易在 RK3588 上做联调和回归
## 15. 验证策略
## 15.1 本地代码级验证
本地验证只聚焦平台无关逻辑:
- 人脸与人体关联行为
- 聚合状态机状态转换
- 已知人确认窗口逻辑
- 陌生人抑制逻辑
- 离场重入冷却逻辑
- 配置解析与兼容性
## 15.2 RK3588 设备侧验证
最终验证必须在 RK3588 上完成:
- 已知人从远到近进入画面
- 预期:延迟但稳定触发 `known_person`
- 预期:不出现 `unknown_face` 误报
- 已知人短暂离场并快速重入
- 预期:不重复触发打卡
- 已知人长时间离场并超过冷却后再进入
- 预期:允许再次打卡
- 真正陌生人且人脸质量足够
- 预期:经过持续观察后触发一次 `unknown_face`
- 低质量陌生人
- 预期:不触发告警
- 同帧多个人体
- 预期:人脸与人体关联正确,不串轨
## 16. 风险与缓解
### 风险 1人脸与人体关联错误
影响:
- 识别证据可能被挂到错误的人体轨迹上
缓解:
- 初版先采用简单稳定的 center-in-box 匹配
- 在 debug 模式下输出 `person_track_id` 与关联决策
- 在 RK3588 多人场景中重点验证
### 风险 2陌生人确认过于保守
影响:
- 陌生人告警触发变慢,或数量减少
缓解:
- 所有陌生人阈值均做成可配置
- 在早期 rollout 阶段宁可少报,也不要在车间场景中误报
### 风险 3离场重入抑制过强
影响:
- 合法的重复打卡事件可能被压掉
缓解:
- 冷却时间全部做成可配置
- 在文档与配置说明中明确“当前业务语义是打卡型告警,而不是持续在场播报”
## 17. 推荐落地顺序
建议按以下顺序逐步落地:
1. 增加 `person_track_id` 传递和 debug 日志
2. 实现按轨迹的已知人确认
3. 实现保守的按轨迹陌生人确认
4. 加入离场重入抑制
5. 在 RK3588 上用已知人 / 陌生人视频做回归验证
分阶段落地可以降低风险,也更方便逐步对比行为变化。
## 18. 预期效果
设计实现后,车间人脸识别告警行为应达到以下效果:
- 低质量人脸观测被直接忽略
- 已知员工通过多帧聚合而非单帧偶然命中被确认
- 同一个已知人不会因为个别低分帧被误报为陌生人
- 同一个人在场期间最多触发一次身份类告警
- 人员短时离场再进入时不会重复打卡
- 陌生人告警数量减少,但可信度明显提高
这正是当前车间部署所需要的取舍方向:降低告警频率,提高告警精度。