safesight-edge/docs/config_guide.md

837 lines
26 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.

# 配置文件编写指南
本文档说明当前项目主线配置的写法,重点覆盖两阶段鞋检测、劳保鞋颜色判断、告警节流,以及 RK3588 上与性能稳定性直接相关的参数。
---
## 1. 当前推荐架构
对车间劳保鞋场景,当前推荐链路是:
```text
input_rtsp
-> preprocess(rgb)
-> ai_yolo(person only)
-> tracker(person only)
-> ai_shoe_det(dynamic roi)
-> logic_gate(person_shoe_check)
-> logic_gate(ppe_boots_check)
-> osd
-> preprocess(nv12)
-> publish
-> alarm
```
业务目标:
- 先检测到人
- 再只在脚部 ROI 检鞋
- 只关心“检测到鞋后,颜色是否接近黑色劳保鞋”
- 不再把“没穿鞋”作为主告警目标
---
## 2. 配置结构
当前项目常用的是 graph 模式:
```json
{
"queue": {
"size": 8,
"strategy": "drop_oldest"
},
"graphs": [
{
"name": "person_shoe_two_stage_workshoe_alarm",
"executor": {
"batch_size": 2,
"run_budget": 8
},
"nodes": [ ... ],
"edges": [ ... ]
}
]
}
```
### 2.1 queue
```json
{
"queue": {
"size": 8,
"strategy": "drop_oldest"
}
}
```
说明:
- `size`:默认队列长度
- `strategy`
- `drop_oldest`:推荐,实时性最好
- `drop_newest`
- `block`
### 2.2 executor
```json
{
"executor": {
"batch_size": 2,
"run_budget": 8
}
}
```
说明:
- `batch_size`:执行器单次批量处理帧数
- `run_budget`:单次调度预算
在 RK3588 上,如果出现“隔几秒卡一下”,通常先减小 `run_budget`,再看是否需要调 `batch_size`
---
## 3. 关键节点
### 3.1 input_rtsp
```json
{
"id": "in",
"type": "input_rtsp",
"role": "source",
"enable": true,
"url": "rtsp://10.0.0.49:8554/cam",
"fps": 30,
"width": 1920,
"height": 1080,
"use_ffmpeg": true,
"use_mpp": false,
"force_tcp": true
}
```
当前推荐:
- 对会在固定画面卡顿的 RTSP 源,优先使用 `use_ffmpeg: true`、`use_mpp: false`
- 原因是部分源流在 `ffmpeg demux + mpp decode` 路径上会出现固定位置卡顿,而 VLC 直拉源流正常
### 3.2 preprocess
```json
{
"id": "pre_rgb",
"type": "preprocess",
"role": "filter",
"enable": true,
"dst_w": 1920,
"dst_h": 1080,
"dst_format": "rgb",
"dst_packed": true,
"resize_mode": "stretch",
"rga_gate": "person_shoe_two_stage_workshoe_alarm",
"use_rga": true
}
```
说明:
- 前级 `pre_rgb` 准备共享的高分辨率 RGB 主帧
- 后级 `post` 再转回 `nv12` 给编码器
- `use_rga: true` 是 RK3588 上的推荐项
### 3.3 ai_yolo
```json
{
"id": "person_det",
"type": "ai_yolo",
"role": "filter",
"enable": true,
"infer_fps": 2,
"infer_phase_ms": 0,
"use_rga": true,
"use_dma_input": true,
"model_path": "./models/object_det_yolov8n_coco_640_rk3588.rknn",
"model_version": "v8",
"model_w": 640,
"model_h": 640,
"num_classes": 80,
"conf": 0.35,
"nms": 0.45,
"class_filter": [0],
"bbox_expand": {
"enable": true,
"class_id": 0,
"left": 0.06,
"right": 0.06,
"top": 0.04,
"bottom": 0.16
}
}
```
当前用途:
- 只做人检测前级
- 不再直接承担鞋检测
关键参数:
| 参数 | 作用 | 当前建议 |
|------|------|----------|
| `infer_fps` | 人体检测频率 | `2` |
| `infer_phase_ms` | 与鞋检错峰 | `0` |
| `class_filter` | 只保留 `person` | `[0]` |
| `bbox_expand.bottom` | 补偿漏脚 | `0.16` 左右 |
| `use_rga` / `use_dma_input` | 输入性能优化 | 建议开启 |
### 3.4 tracker
```json
{
"id": "person_trk",
"type": "tracker",
"role": "filter",
"enable": true,
"mode": "bytetrack_lite",
"per_class": true,
"track_classes": [0],
"high_th": 0.55,
"low_th": 0.10,
"iou_th": 0.3,
"max_age_ms": 900,
"min_hits": 2
}
```
当前用途:
- 稳定人框
- 为鞋子关联和按人节流提供 `track_id`
### 3.4.1 人脸检测和识别
完整流程中,人脸检测/识别建议放在 `person_trk` 之后,让人脸识别可以复用人体跟踪结果:
```text
pre_rgb -> face_det -> person_det -> person_trk -> face_recog -> ...
```
人脸检测可使用 `ai_scrfd_sliding`,在 1080p 高机位画面中建议按左右窗口滑动检测:
```json
{
"id": "face_det",
"type": "ai_scrfd_sliding",
"enable": true,
"infer_fps": 3,
"model_path": "./models/face_det_scrfd_500m_640_rk3588.rknn",
"model_w": 640,
"model_h": 640,
"windows": [
{"x": 0, "y": 0, "w": 960, "h": 1080},
{"x": 960, "y": 0, "w": 960, "h": 1080}
],
"conf_thresh": 0.5,
"nms_thresh": 0.4,
"max_faces": 50
}
```
人脸识别节点示例:
```json
{
"id": "face_recog",
"type": "ai_face_recog",
"enable": true,
"infer_fps": 2,
"infer_phase_ms": 120,
"model_path": "./models/face_recog_mobilefacenet_arcface_112_rk3588.rknn",
"align": true,
"emit_embedding": false,
"max_faces": 50,
"person_class_id": 0,
"track_state_max_age_ms": 1000,
"input_format": "rgb",
"input_dtype": "uint8",
"threshold": {
"accept": 0.45,
"margin": 0.05
},
"gallery": {
"backend": "sqlite",
"path": "./models/face_gallery.db",
"load_on_start": true,
"dtype": "auto"
},
"debug": {
"enabled": true,
"log_matches": true,
"min_log_interval_ms": 0
}
}
```
关键参数:
| 参数 | 作用 | 当前建议 |
|------|------|----------|
| `face_det.infer_fps` | 人脸检测频率 | `3`,多人/小脸测试时可提高,性能紧张时降低 |
| `face_recog.infer_fps` | 人脸识别频率 | `2`,与人体/鞋检测错峰运行 |
| `infer_phase_ms` | 推理错峰 | `120` 左右,避免多个 NPU 节点同一时刻抢资源 |
| `align` | 使用 5 点关键点做人脸对齐 | 建议 `true` |
| `threshold.accept` | 识别为已知人的最低相似度 | 当前测试用 `0.45` |
| `threshold.margin` | top1 与 top2 的最小差值 | 当前测试用 `0.05`,用于降低相似人员误认 |
| `gallery.path` | SQLite 人脸库路径 | `./models/face_gallery.db` |
| `track_state_max_age_ms` | 可接受的跟踪状态最大年龄 | `1000` 左右 |
| `debug.log_matches` | 打印每次人脸匹配结果 | 测试阶段开启,正式运行可关闭 |
说明:
- 人脸识别会自动读取同一 graph 内 tracker 发布的人体跟踪状态,不需要配置 shared-state key。
- 人脸库 embedding 维度会从图库数据自动推断,不需要在配置文件中填写。
识别状态含义:
- `known`:满足 `threshold.accept``threshold.margin`,可以作为“已知人”证据。
- `uncertain`:像某个已知人,但证据不足;不会直接当作陌生人。
人脸识别模型输出的是 embedding不是带有 `unknown` 类别的分类结果。因此人脸识别节点只输出 `known` / `uncertain`。`unknown_face` 属于告警规则语义,由 alarm 结合 track 聚合、质量门槛和“没有已知人证据”来判断。
日志分析:
```bash
python3 tools/analyze_face_recog_log.py /tmp/media-server.log
```
本地从 RK3588 拉回日志后也可以直接分析:
```powershell
scp orangepi@10.0.0.81:/tmp/media-server.log .\logs\media-server_latest.log
python tools/analyze_face_recog_log.py .\logs\media-server_latest.log
```
人脸库说明:
- SQLite 人脸库支持同一个人多条 embedding。
- 建议每个人至少提供正脸,条件允许时增加左/右侧脸或不同光照照片。
- 运行时检索会先按 `person_id` 聚合,同一个人的多张照片不会互相抢 top1/top2。
- 真实场景只有几十人时,不需要担心多 embedding 带来的库大小问题。
### 3.5 ai_shoe_det
```json
{
"id": "shoe_det",
"type": "ai_shoe_det",
"role": "filter",
"enable": true,
"infer_fps": 2,
"infer_phase_ms": 150,
"use_rga": true,
"use_dma_input": false,
"model_path": "./models/shoe_det_yolov8s_workshoe_640_rk3588.rknn",
"model_w": 640,
"model_h": 640,
"conf": 0.22,
"nms": 0.45,
"v8_box_format": "cxcywh",
"append_detections": true,
"dynamic_roi": {
"enable": true,
"person_class_id": 0,
"shoe_class_id": 1,
"debug_roi_class_id": -1,
"max_rois": 3,
"min_person_height": 60,
"max_box_area_ratio": 0.6,
"y_offset": 0.7,
"width_scale": 1.6,
"height_scale": 0.4
}
}
```
当前用途:
- 从人框动态生成脚部 ROI
- 只在 ROI 内跑鞋模型
- 将鞋框追加回 `frame->det`
关键参数:
| 参数 | 作用 | 当前建议 |
|------|------|----------|
| `conf` | 鞋候选召回阈值 | `0.22` |
| `append_detections` | 保留人框并追加鞋框 | 必须 `true` |
| `dynamic_roi.max_rois` | 每帧最多处理多少人 | `3` |
| `dynamic_roi.min_person_height` | 过滤太远的人 | `60` |
| `dynamic_roi.max_box_area_ratio` | 过滤接近整块脚区的大误框 | `0.6` |
| `dynamic_roi.y_offset` | 脚部 ROI 起点高度 | `0.7` |
| `dynamic_roi.width_scale` | 脚部 ROI 宽度比例 | `1.6` |
| `dynamic_roi.height_scale` | 脚部 ROI 高度比例 | `0.4` |
说明:
- `shoe_det.conf` 看起来偏低,这是有意为之
- 当前方案依赖“低阈值召回 + 人鞋关联 + 颜色判断 + 告警节流”整体收敛
- 在高机位小鞋场景中,如果把这里直接调到 `0.4``0.5`,通常会明显漏检
- 横向 ROI 已固定为按 `width_scale` 自动居中,不再提供 `x_offset` 配置
### 3.6 logic_gate
#### 模式一person_shoe_check
```json
{
"id": "shoe_assoc",
"type": "logic_gate",
"role": "filter",
"enable": true,
"mode": "person_shoe_check",
"person_shoe_check": {
"person_class": 0,
"shoe_class": 1,
"violation_class": 2,
"min_person_score": 0.30,
"min_shoe_score": 0.22,
"foot_region": {
"y_offset": 0.7,
"width_scale": 1.6,
"height_scale": 0.4
},
"min_shoe_height_ratio": 0.08,
"min_shoe_area_ratio": 0.012,
"max_shoe_height_ratio": 0.14,
"max_shoe_width_ratio": 0.38,
"max_shoe_area_ratio": 0.05,
"max_shoe_roi_width_ratio": 0.45,
"max_shoe_roi_height_ratio": 0.35,
"max_shoe_roi_area_ratio": 0.10
}
}
```
当前用途:
- 把鞋关联到对应的人
- 把人的 `track_id` 传给鞋
- 不再输出“没鞋违规”
关键参数:
| 参数 | 作用 | 当前建议 |
|------|------|----------|
| `min_person_score` | 进入人鞋关联的人框最低分数 | `0.30` |
| `min_shoe_score` | 进入人鞋关联的鞋框最低分数 | `0.22` |
| `foot_region.y_offset` | 关联阶段脚部 ROI 起点高度 | `0.7` |
| `foot_region.width_scale` | 关联阶段脚部 ROI 宽度比例 | `1.6` |
| `foot_region.height_scale` | 关联阶段脚部 ROI 高度比例 | `0.4` |
| `min_shoe_height_ratio` | 过滤过矮鞋框 | `0.08` |
| `min_shoe_area_ratio` | 过滤过小鞋框 | `0.012` |
| `max_shoe_height_ratio` | 过滤过高鞋框 | `0.14` |
| `max_shoe_width_ratio` | 过滤过宽鞋框 | `0.38` |
| `max_shoe_area_ratio` | 过滤过大鞋框 | `0.05` |
| `max_shoe_roi_width_ratio` | 过滤相对脚部 ROI 过宽的鞋框 | `0.45` |
| `max_shoe_roi_height_ratio` | 过滤相对脚部 ROI 过高的鞋框 | `0.35` |
| `max_shoe_roi_area_ratio` | 过滤相对脚部 ROI 过大的鞋框 | `0.10` |
#### 模式二ppe_boots_check
```json
{
"id": "shoe_color",
"type": "logic_gate",
"role": "filter",
"enable": true,
"mode": "ppe_boots_check",
"anchor_class": 0,
"boots_class": 1,
"violation_class": 2,
"color_check": {
"enable": true
}
}
```
当前用途:
- 只对已检测到的鞋做颜色判断
- 深色鞋:视为合规
- 非深色鞋:追加 `cls=2` 的违规框,供 OSD 和 alarm 使用
### 3.7 osd
```json
{
"id": "osd",
"type": "osd",
"role": "filter",
"enable": true,
"draw_bbox": true,
"draw_text": false,
"use_rga_bbox": false,
"labels": ["person", "shoe", "non_black_shoe"]
}
```
当前显示含义:
- `person`
- `shoe`
- `non_black_shoe`
### 3.8 publish
```json
{
"id": "pub",
"type": "publish",
"role": "filter",
"enable": true,
"codec": "h264",
"fps": 30,
"bitrate_kbps": 2000,
"mpp_output_timeout_ms": 50,
"mpp_packet_wait_ms": 10,
"use_mpp": true,
"outputs": [
{"proto": "rtsp_server", "port": 8555, "path": "/live/cam1"}
]
}
```
当前推荐:
- 输入端优先 FFmpeg CPU decode
- 输出端继续使用 MPP 编码
### 3.9 alarm
```json
{
"id": "alarm",
"type": "alarm",
"role": "sink",
"enable": true,
"eval_fps": 2,
"labels": ["person", "shoe", "non_black_shoe"],
"rules": [
{
"name": "non_compliant_workshoe",
"class_ids": [2],
"roi": {"x": 0.0, "y": 0.0, "w": 1.0, "h": 1.0},
"min_score": 0.30,
"require_track_id": false,
"min_duration_ms": 800,
"min_hits": 2,
"hit_window_ms": 2000,
"cooldown_ms": 15000,
"per_track_cooldown_ms": 0
}
],
"actions": {
"log": {
"enable": true,
"level": "info",
"include_detections": true,
"min_interval_ms": 2000
}
}
}
```
生产默认告警策略:
- 只对 `cls=2 non_black_shoe` 告警
- 蓝框稳定出现 2 次以上,且持续约 `800ms`,才触发
- 触发后进入 `15s` 冷却,避免反复刷屏
测试短视频如果需要快速验证链路,可以使用 `configs/overlays/shoe_test_sensitive.json` 临时恢复更灵敏的阈值:
- `min_score=0.1`
- `min_duration_ms=0`
- `min_hits=1`
- `cooldown_ms=1000`
完整流程中还可以配置人脸告警:
```json
{
"face_track_aggregation": {
"known": {
"min_hits": 3,
"hit_window_ms": 3000,
"reentry_cooldown_ms": 300000
},
"unknown": {
"min_track_age_ms": 2000,
"min_quality_hits": 4
}
},
"face_rules": [
{
"name": "unknown_face",
"type": "unknown",
"cooldown_ms": 7000,
"max_known_sim": 0.35,
"min_hits": 2,
"hit_window_ms": 1500,
"min_face_area_ratio": 0.001,
"min_face_aspect": 0.6,
"max_face_aspect": 1.6
},
{
"name": "known_person",
"type": "person",
"cooldown_ms": 7000,
"min_sim": 0.6,
"min_hits": 2,
"hit_window_ms": 1500,
"min_face_area_ratio": 0.001,
"min_face_aspect": 0.6,
"max_face_aspect": 1.6
}
]
}
```
人脸告警关键参数:
| 参数 | 作用 | 设置建议 |
|------|------|----------|
| `face_track_aggregation.known.min_hits` | 同一人体 track 需要多少次 `known` 才触发已知人告警 | 正式运行建议 `2``3`;验证链路可用 `face_test_sensitive` 降为 `1` |
| `face_track_aggregation.known.hit_window_ms` | `known` 证据累计窗口 | `3000`,人脸出现时间短可适当加大 |
| `face_track_aggregation.known.reentry_cooldown_ms` | 同一已知人短时间离开再进入时的抑制时间 | 打卡场景建议使用分钟级,例如模板默认 `300000` |
| `face_track_aggregation.unknown.min_track_age_ms` | 陌生人候选 track 至少持续多久 | 正式默认 `2000`;测试短视频可用 `face_test_sensitive` 降为 `1500` |
| `face_track_aggregation.unknown.min_quality_hits` | 陌生人候选需要多少次有效质量帧 | 建议 `4` 起,保证陌生人告警更准 |
| `known_person.min_sim` | 确认已知人的最低相似度条件 | 模板默认 `0.6`;测试短视频可用 `face_test_sensitive` 降为 `0.45` |
| `unknown_face.max_known_sim` | 陌生人候选允许的最高“已知人相似度” | 当前测试为 `0.35`;超过该值说明仍像库中某人,不直接报陌生人 |
| `face_rules[].min_face_area_ratio` | 过滤小脸框 | 1080p 下 `0.0002` 约等于 `415px²``0.001` 约等于 `2074px²` |
| `face_rules[].cooldown_ms` | 同一规则冷却 | 测试可 `7000`,正式按后台接收频率调整 |
| `face_rules[].min_face_aspect / max_face_aspect` | 过滤异常长宽比人脸框 | `known_person` 当前测试为 `0.55``1.6``unknown_face` 建议保持 `0.6``1.6` |
`min_face_area_ratio` 取值参考,按 1920x1080 画面计算:
| 参数值 | 面积阈值 | 典型含义 |
|--------|----------|----------|
| `0.0001` | 约 `207px²` | 很宽松,容易放过极小脸 |
| `0.0002` | 约 `415px²` | 当前测试值,可过滤明显小框,同时保留 `22x36` 级别人脸 |
| `0.0003` | 约 `622px²` | 更稳,适合人脸稍大的现场 |
| `0.0005` | 约 `1037px²` | 较严格,适合近距离较清晰人脸 |
| `0.001` | 约 `2074px²` | 对高机位远景视频通常过严 |
---
## 4. 连接关系
```json
{
"edges": [
["in", "pre_rgb"],
["pre_rgb", "person_det"],
["person_det", "person_trk"],
["person_trk", "shoe_det"],
["shoe_det", "shoe_assoc"],
["shoe_assoc", "shoe_color"],
["shoe_color", "osd"],
["osd", "post"],
["post", "pub"],
["pub", "alarm"]
]
}
```
说明:
- `publish -> alarm` 是合法链路
- `alarm` 会继续读取前面节点保留下来的 `frame->det`
---
## 5. 推荐配置
| 配置文件 | 说明 |
|----------|------|
| `configs/person_shoe_two_stage_workshoe_alarm_v8s_shoe640.json` | 单路劳保鞋颜色告警主线配置 |
| `configs/person_shoe_two_stage_workshoe_alarm_v8s_shoe640_strict.json` | 单路劳保鞋颜色告警严格版 |
| `configs/full_pipeline_1080p.json` | 人脸检测/识别 + 劳保鞋颜色告警完整流程 |
---
## 6. 模板化配置
推荐以模板作为运维核心资产,避免为每台 RK3588 或每次调参复制完整配置。
当前标准模板来自 `configs/full_pipeline_1080p_test_alarm.json`包含人脸、人体、鞋子、OSD、发布、告警和上传链路
```bash
python tools/render_config.py \
--template configs/templates/workshop_face_shoe_alarm.json \
--profile configs/profiles/local_3588_test.json \
--overlay configs/overlays/face_debug.json \
--overlay configs/overlays/face_test_sensitive.json \
--out configs/generated/local_3588_face_debug.json
```
生成后的配置运行方式:
```bash
./build/media-server -c configs/generated/local_3588_face_debug.json
```
目录约定:
| 目录 | 用途 |
|------|------|
| `configs/templates/` | 长期维护的 pipeline 模板 |
| `configs/profiles/` | 设备、现场、摄像头差异参数 |
| `configs/overlays/` | 测试或运行场景覆盖,例如 debug、阈值、频率 |
| `configs/generated/` | 渲染产物,不手工维护,不提交生成的 JSON |
`--overlay` 可以指定多次,后面的 overlay 会覆盖前面的同名字段。建议:
- 生产:不加测试敏感 overlay或只加 `production_quiet.json`
- 人脸测试:`face_debug.json` + `face_test_sensitive.json`
- 鞋子测试:`shoe_debug.json` + `shoe_test_sensitive.json`
- 人脸和鞋子同时测试:四个 overlay 可按 debug、test sensitive 的顺序叠加。
---
## 7. 调参顺序
建议按下面顺序调,不要同时乱改:
1. `ai_yolo.conf``bbox_expand`
目标:先保证人体框稳定且脚下留出空间
2. `ai_shoe_det.conf``dynamic_roi`
目标:先让鞋框能出来
3. `shoe_assoc.person_shoe_check` 尺寸过滤参数
目标:拦住双鞋框、大框和整块裤腿误框
4. `alarm.min_hits / min_duration_ms / cooldown_ms`
目标:把“会报警”收敛成“稳一点再报警”
### 7.1 实施人员重点参数
实施时优先看下面这些参数,不建议一开始改其它项。
| 节点 | 参数 | 期望效果 | 调大后的典型结果 | 调小后的典型结果 |
|------|------|----------|------------------|------------------|
| `input_rtsp` | `use_ffmpeg / use_mpp` | 解决固定画面卡顿 | `use_ffmpeg=true` 一般更稳 | `use_mpp=true` 某些源可能卡顿 |
| `person_det` | `infer_fps` | 控制人体检测负载 | 召回更及时,但更吃 NPU | 更省资源,但人框更新更慢 |
| `person_det` | `bbox_expand.bottom` | 给脚部 ROI 留空间 | 更不容易漏脚 | 人框更紧,鞋 ROI 更容易裁偏 |
| `shoe_det` | `conf` | 控制鞋框召回和误报平衡 | 误报减少,但漏鞋增多 | 鞋框更多,但误报也更多 |
| `shoe_det.dynamic_roi` | `max_rois` | 控制每帧最多处理多少人 | 覆盖更多人,但 FPS 下降 | 更省资源,但多人时会漏掉部分鞋 |
| `shoe_det.dynamic_roi` | `min_person_height` | 过滤远景小人 | 远处小人不参与鞋检 | 更多远景人进入鞋检 |
| `shoe_det.dynamic_roi` | `max_box_area_ratio` | 过滤接近整块脚区的大误框 | 大蓝框减少 | 更容易保留整块 ROI 级误报 |
| `shoe_det.dynamic_roi` | `y_offset / width_scale / height_scale` | 控制鞋检测脚部 ROI 的位置和范围 | ROI 更宽/更高/更靠下 | ROI 更窄/更低/更靠上 |
| `shoe_assoc` | `min_shoe_score` | 控制低分鞋框是否参与人鞋关联 | 低分误框减少 | 弱鞋框更容易进入后续逻辑 |
| `shoe_assoc` | `max_shoe_width_ratio` | 控制偏宽大框是否被过滤 | 双鞋合并框、大鞋框更少 | 更容易放过双鞋框和裤腿大框 |
| `shoe_assoc` | `max_shoe_area_ratio` | 控制偏大面积鞋框是否被过滤 | 大误框更少 | 大误框更容易进入颜色判断 |
| `shoe_assoc` | `max_shoe_roi_width_ratio / max_shoe_roi_height_ratio / max_shoe_roi_area_ratio` | 控制相对脚部 ROI 的鞋框上限 | 更能拦住整块脚区误框 | 更容易保留整块 ROI 级误报 |
| `face_recog` | `threshold.accept` | 控制已知人识别最低相似度 | 误认减少,但 known 变少 | known 变多,但误认风险升高 |
| `face_recog` | `threshold.margin` | 控制 top1 和 top2 的区分度 | 相似人员误认减少,但 known 变少 | known 变多,但相似人员更容易混淆 |
| `known_person` | `min_face_area_ratio` | 控制已知人告警可接受的人脸最小尺寸 | 小脸告警减少,更稳 | 更容易触发,但小脸质量风险升高 |
| `unknown_face` | `max_known_sim` | 控制陌生人候选是否“仍太像已知人” | 减少把已知人波动报成陌生人 | 更容易把未知人纳入陌生人聚合 |
| `face_track_aggregation.known` | `min_hits` | 控制已知人需要多少次稳定识别才告警 | 更稳,适合正式打卡 | 更灵敏,适合验证链路 |
| `alarm` | `min_duration_ms` | 控制要稳定多久才报警 | 更稳,但慢一点 | 更灵敏,但更容易闪报 |
| `alarm` | `cooldown_ms` | 控制两次告警间隔 | 减少重复告警 | 同一事件会更频繁重复报 |
### 7.2 推荐调参动作
现场遇到问题时,优先按下面方式处理:
- 鞋子漏报多:
- 先降低 `shoe_det.conf`
- 再降低 `shoe_assoc.min_shoe_score`
- 必要时降低 `dynamic_roi.min_person_height`
- 再检查 `dynamic_roi.y_offset / width_scale / height_scale` 是否把脚部 ROI 裁偏
- 蓝框误报多:
- 先提高 `shoe_det.conf`
- 再提高 `shoe_assoc.min_shoe_score`
- 如出现整块脚区级误框,再降低 `max_box_area_ratio`
- 如出现双鞋合并框或裤腿大框,再降低 `max_shoe_width_ratio / max_shoe_area_ratio`
- 黑色劳保鞋被误报:
- 先检查是否有大框、双鞋框、裤腿框混进来
- 优先收紧 `max_shoe_width_ratio / max_shoe_area_ratio / max_shoe_roi_*`
- 非黑鞋不报警:
- 先检查鞋框是否进入 `shoe selected`
- 再检查 `shoe_det.conf / shoe_assoc.min_shoe_score`
- 再检查 `dynamic_roi``foot_region` 是否把脚部 ROI 裁偏
- 检查 `alarm.min_score`
- 检查 `alarm.min_duration_ms / min_hits`
- 完整流程 FPS 不够:
- 先降低 `face_det.infer_fps`
- 再降低 `face_recog.infer_fps`
- 再考虑降低 `dynamic_roi.max_rois`
- 已知人识别有 `known`,但没有 `known_person` 告警:
- 先看日志中是否有 `status=known`
- 再看 `person_track_id` 是否为有效值,`-1` 不能用于按人稳定聚合
- 检查 `known_person.min_sim`
- 检查 `known_person.min_face_area_ratio`
- 检查 `face_track_aggregation.known.min_hits`
- 验证链路时可临时用 `min_hits=1`;正式打卡场景建议恢复到 `2``3`
- 大量 `uncertain`known 较少:
- 先确认人脸库是否加载:日志应有 `gallery loaded: n=<数量> dim=512`
- 确认同一个人是否录入了正脸、侧脸等多张照片
- 检查人脸框尺寸,远景小脸通常 best_sim 和 margin 都偏低
- 不要把 `uncertain` 当作陌生人直接上报
---
## 8. 常见问题
### Q1: 为什么鞋子检测阈值只有 0.22
因为当前场景是高机位、小鞋目标,单纯靠高阈值会先漏掉大量鞋框。系统依赖多级过滤,而不是单级高阈值。
### Q2: 为什么有蓝框却不告警?
优先检查:
- 是否跑的是 `person_shoe_two_stage_workshoe_alarm_v8s_shoe640.json`
- `alarm.rules[].class_ids` 是否包含 `2`
- `min_score / min_hits / min_duration_ms` 是否过严
### Q3: 为什么 RTSP 会固定画面卡顿?
如果 VLC 直拉源流不卡,而项目里卡,优先切到:
```json
"use_ffmpeg": true,
"use_mpp": false
```
这通常说明问题在输入解码兼容性,而不是 AI 链路。
### Q4: 为什么日志里有 known但后台没有 known_person 告警?
`known` 只是识别节点给出的单帧结果。告警还需要通过 `known_person` 的质量门槛和 `face_track_aggregation.known` 的稳定聚合。
优先检查:
- `person_track_id` 是否有效,`-1` 无法按人聚合。
- `known_person.min_face_area_ratio` 是否过高。1080p 下 `0.001` 约等于 `2074px²`,远景小脸常常达不到。
- `face_track_aggregation.known.min_hits` 是否过高。测试触发链路可用 `1`,正式打卡建议 `2``3`
- `known_person.cooldown_ms``known.reentry_cooldown_ms` 是否正在抑制重复上报。
### Q5: unknown_face 和 uncertain 有什么区别?
`uncertain` 是识别节点的单帧状态,表示“没有稳定确认是已知人”。它本身不能直接当作陌生人。`unknown_face` 是告警规则,使用开放集识别思路:人脸质量足够、不是 `known`、`best_sim < unknown_face.max_known_sim`、同一人体 track 持续存在并累计足够质量帧后才认为是陌生人这样可以避免远处小脸合成人脸或短暂模糊帧被误报成陌生人
---
**版本**v2.1
**更新日期**2026-04-16