开发后处理插件2
This commit is contained in:
parent
16c4e50535
commit
41c4a3de3b
95
Readme.md
95
Readme.md
@ -80,11 +80,13 @@
|
||||
示意:
|
||||
|
||||
```text
|
||||
[in] → [pre] → [ai] ─────→ [alarm]
|
||||
└──→ [osd] → [storage]
|
||||
[in] → [pre] → [ai_yolo] → [det_post] ───→ [alarm]
|
||||
└──────→ [osd] → [storage]
|
||||
└──→ [publish]
|
||||
```
|
||||
|
||||
> 说明:`det_post` 是检测结果后处理节点(可选)。它会对 `frame->det` 做过滤/修正/二次验证,使 OSD 与告警读取到一致的“后处理结果”。
|
||||
|
||||
---
|
||||
|
||||
## 三、数据模型(Frame & 元数据)
|
||||
@ -322,6 +324,23 @@ GraphMgr 负责:
|
||||
"nms": 0.5,
|
||||
"class_filter": [0, 1]
|
||||
},
|
||||
{
|
||||
"id": "pp_cam1",
|
||||
"type": "det_post",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"default": { "enable": false },
|
||||
"per_class": [
|
||||
{
|
||||
"class_id": 0,
|
||||
"enable": true,
|
||||
"processors": [
|
||||
{ "type": "conf_gate", "conf_min": 0.65 },
|
||||
{ "type": "bbox_gate", "min_w": 10, "min_h": 10 }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "osd_cam1",
|
||||
"type": "osd",
|
||||
@ -373,8 +392,9 @@ GraphMgr 负责:
|
||||
"edges": [
|
||||
["in_cam1", "pre_cam1"],
|
||||
["pre_cam1", "ai_cam1"],
|
||||
["ai_cam1", "alarm_cam1"],
|
||||
["ai_cam1", "osd_cam1"],
|
||||
["ai_cam1", "pp_cam1"],
|
||||
["pp_cam1", "alarm_cam1"],
|
||||
["pp_cam1", "osd_cam1"],
|
||||
["osd_cam1", "storage_cam1"],
|
||||
["osd_cam1", "publish_cam1"]
|
||||
]
|
||||
@ -383,6 +403,10 @@ GraphMgr 负责:
|
||||
}
|
||||
```
|
||||
|
||||
> 说明:如果不需要后处理:
|
||||
> - **推荐**:保留 `pp_cam1` 节点(`enable:true`),并确保其不启用任何处理链(例如:`default.enable=false` 且 `per_class` 为空),此时 `det_post` 会作为轻量透传。
|
||||
> - 若确实要移除该节点:需要**同时删除并重连拓扑**(例如改回 `ai_cam1 -> osd_cam1` 与 `ai_cam1 -> alarm_cam1`),仅设置 `enable=false` 会导致下游节点无输入而构图失败。
|
||||
|
||||
通过简单改动即可支持不同组合:
|
||||
|
||||
- 不报警:`alarm_cam1.enable = false` 或移除该节点/边。
|
||||
@ -400,13 +424,15 @@ GraphMgr 负责:
|
||||
{ "id": "in", "type": "input_rtsp", "role": "source", "url": "${url}" },
|
||||
{ "id": "pre", "type": "preprocess", "role": "filter", "dst_w": 640, "dst_h": 640 },
|
||||
{ "id": "ai", "type": "ai_yolo", "role": "filter", "model_path": "/models/yolov8n.rknn", "conf": 0.5 },
|
||||
{ "id": "pp", "type": "det_post", "role": "filter", "enable": true, "default": { "enable": false } },
|
||||
{ "id": "osd", "type": "osd", "role": "filter" },
|
||||
{ "id": "pub", "type": "publish", "role": "sink", "path": "/live/${name}" }
|
||||
],
|
||||
"edges": [
|
||||
["in", "pre"],
|
||||
["pre", "ai"],
|
||||
["ai", "osd"],
|
||||
["ai", "pp"],
|
||||
["pp", "osd"],
|
||||
["osd", "pub"]
|
||||
]
|
||||
}
|
||||
@ -485,6 +511,65 @@ GraphMgr 负责:
|
||||
| `ai_pose` | 关键点检测(可选扩展) | `model_path` | NPU |
|
||||
| `ai_custom` | 自定义 AI 算法 | `model_path`, `custom_param` 等 | NPU |
|
||||
|
||||
#### 6.2.1 det_post(检测结果后处理,按类别策略链)
|
||||
|
||||
`det_post` 是一个 **Filter** 节点,位于 `ai_yolo` 之后,负责对 `frame->det->items` 做**按类别可配置**的后处理。
|
||||
|
||||
**设计目标:**
|
||||
- 不同类别可以挂不同的处理器链(Processor/Strategy Registry),避免“一个类别一个插件”。
|
||||
- 默认改写 `frame->det`,让 `osd` / `alarm` 读到一致结果。
|
||||
|
||||
**配置示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "pp_cam1",
|
||||
"type": "det_post",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
|
||||
"default": { "enable": false },
|
||||
"per_class": [
|
||||
{
|
||||
"class_id": 3,
|
||||
"enable": true,
|
||||
"processors": [
|
||||
{ "type": "conf_gate", "conf_min": 0.65 },
|
||||
{ "type": "bbox_gate", "min_w": 10, "min_h": 10 },
|
||||
{ "type": "roi_gate", "roi": { "x": 0.1, "y": 0.1, "w": 0.8, "h": 0.8 }, "mode": "center" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"class_id": 5,
|
||||
"enable": true,
|
||||
"processors": [
|
||||
{ "type": "hsv_ratio", "h_min": 0, "h_max": 20, "s_min": 20, "v_min": 70, "ratio_min": 0.7,
|
||||
"max_samples": 2048, "step": 0, "min_samples": 32,
|
||||
"crop": { "x": 0.0, "y": 0.0, "w": 1.0, "h": 1.0 } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"class_id": 7,
|
||||
"enable": true,
|
||||
"processors": [
|
||||
{ "type": "lab_kmeans", "k": 3, "iters": 8, "l_max": 50, "ratio_min": 0.4,
|
||||
"max_samples": 2048, "step": 0, "min_samples": 64,
|
||||
"crop": { "x": 0.0, "y": 0.0, "w": 1.0, "h": 1.0 } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**内置 processors(当前实现):**
|
||||
- `conf_gate`:按置信度过滤(`conf_min`)
|
||||
- `bbox_gate`:按框尺寸过滤(`min_w`, `min_h`)
|
||||
- `roi_gate`:按 ROI 过滤(`roi:{x,y,w,h}` 归一化;`mode:center` 使用 bbox 中心点判断)
|
||||
- `hsv_ratio`:框内采样像素转 HSV,统计阈值命中占比(`h_min/h_max/s_min/s_max/v_min/v_max/ratio_min`,支持 `crop/max_samples/step`)
|
||||
- `lab_kmeans`:框内采样像素转 Lab,KMeans 聚类后取最暗簇做判定(`k/iters/l_max/ratio_min`,支持 `crop/max_samples/step`)
|
||||
|
||||
> 注意:`hsv_ratio/lab_kmeans` 需要 `Frame` 提供可读的像素数据(`frame->data` 可访问)。若上游是纯 DMA-BUF 且未映射到 CPU,这两类处理器会自然退化为“不过滤”。
|
||||
|
||||
**ai_yolo 参数说明:**
|
||||
- `model_version`: `"v5"`, `"v8"` 或 `"auto"`(自动检测)
|
||||
- `num_classes`: 模型类别数(默认 80)
|
||||
|
||||
@ -772,6 +772,13 @@ public:
|
||||
return NodeStatus::OK;
|
||||
}
|
||||
|
||||
// Fast path: no enabled pipelines configured.
|
||||
if (!cfg->def.enable && cfg->per_class.empty()) {
|
||||
PushToDownstream(frame);
|
||||
processed_.fetch_add(1);
|
||||
return NodeStatus::OK;
|
||||
}
|
||||
|
||||
if (!frame->det || frame->det->items.empty()) {
|
||||
PushToDownstream(frame);
|
||||
processed_.fetch_add(1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user