diff --git a/Readme.md b/Readme.md index f930a65..25a3455 100644 --- a/Readme.md +++ b/Readme.md @@ -849,6 +849,52 @@ CREATE TABLE embedding ( | :---------- | :--------------------------------- | :----------------------------------- | :----------------- | | `osd` | 绘制检测框、文字等 | `draw_bbox`, `draw_text`, `labels`, `line_width`, `font_scale` | RGA / CPU | | `alarm` | 报警规则 + 多种报警动作 | `rules`, `actions`(见下文详细说明) | CPU | + +#### 6.3 Behavior Events + +Behavior events are emitted through `frame->behavior_events` and are not encoded as synthetic detection classes. + +First-release behavior nodes: + +- `region_event`: rule-driven `intrusion` and rule-based `climb` +- `action_recog`: temporal-rule `fall` and `fight` +- `event_fusion`: stable `event_id` assignment and lifecycle normalization + +Recommended first-release graph order: + +```text +[input_rtsp] -> [preprocess] -> [ai_yolo] -> [tracker] -> [region_event] -> [action_recog] -> [event_fusion] -> [osd] -> [publish] -> [alarm] +``` + +Behavior event payload includes: + +- event type +- lifecycle status +- related `track_id` values +- duration in milliseconds +- event bbox +- optional `region_id` + +Behavior event alarm rules should use: + +- `use_behavior_events: true` +- `event_types` +- `region_ids` when region filtering is needed +- `min_duration_ms` +- `cooldown_ms` + +Example alarm rule: + +```json +{ + "name": "intrusion_zone_a", + "use_behavior_events": true, + "event_types": ["intrusion"], + "region_ids": ["zone_a"], + "min_duration_ms": 1000, + "cooldown_ms": 10000 +} +``` | `storage` | 持续录像(MP4/TS 切片) | `mode`, `segment_sec`, `path` | MPP VENC + IO | | `publish` | 编码并推流(RTSP/HLS) | `codec`, `bitrate`, `outputs` | MPP VENC + 网络 | | `zlm_http` | 内嵌 HTTP 文件服务(为 HLS 提供访问) | `root`, `prefix`, `port`, `ssl` | ZLMediaKit(mk_api) | @@ -1220,4 +1266,3 @@ rsync -avz build-cross/ user@board_ip:/opt/media-server/ - [docs/models.md](docs/models.md) - 模型转换与部署指南 - [docs/Agent_API_Extensions.md](docs/Agent_API_Extensions.md) - Agent API 扩展说明 - [docs/API_Device_RemoteMgmt_InterfaceTable.md](docs/API_Device_RemoteMgmt_InterfaceTable.md) - 远程管理接口 - diff --git a/configs/sample_region_behavior_full.json b/configs/sample_region_behavior_full.json new file mode 100644 index 0000000..55c7964 --- /dev/null +++ b/configs/sample_region_behavior_full.json @@ -0,0 +1,203 @@ +{ + "queue": { + "size": 8, + "strategy": "drop_oldest" + }, + "graphs": [ + { + "name": "sample_region_behavior_full", + "nodes": [ + { + "id": "in", + "type": "input_rtsp", + "role": "source", + "enable": true, + "url": "rtsp://127.0.0.1/live", + "fps": 25, + "width": 1920, + "height": 1080, + "use_ffmpeg": true, + "use_mpp": false, + "force_tcp": true + }, + { + "id": "pre", + "type": "preprocess", + "role": "filter", + "enable": true, + "dst_w": 1920, + "dst_h": 1080, + "dst_format": "rgb", + "dst_packed": true, + "resize_mode": "stretch", + "use_rga": true + }, + { + "id": "person_det", + "type": "ai_yolo", + "role": "filter", + "enable": true, + "model_path": "./models/yolov8n-640.rknn", + "model_version": "v8", + "model_w": 640, + "model_h": 640, + "num_classes": 80, + "class_filter": [0], + "conf": 0.35, + "nms": 0.45 + }, + { + "id": "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.30, + "max_age_ms": 1200, + "min_hits": 2 + }, + { + "id": "region_evt", + "type": "region_event", + "role": "filter", + "enable": true, + "events": [ + { + "type": "intrusion", + "region_id": "zone_a", + "roi": { "x": 0.08, "y": 0.12, "w": 0.30, "h": 0.42 }, + "min_duration_ms": 1000 + }, + { + "type": "climb", + "region_id": "fence_1", + "line": { "x1": 0.20, "y1": 0.40, "x2": 0.80, "y2": 0.40 }, + "min_duration_ms": 300, + "min_vertical_motion": 50 + } + ] + }, + { + "id": "action_evt", + "type": "action_recog", + "role": "filter", + "enable": true, + "events": [ + { + "type": "fall", + "window_ms": 1500, + "min_drop_pixels": 120, + "min_aspect_ratio_delta": 0.35, + "activate_duration_ms": 300 + }, + { + "type": "fight", + "window_ms": 1200, + "proximity_pixels": 220, + "min_motion_pixels": 90, + "activate_duration_ms": 200 + } + ] + }, + { + "id": "fusion", + "type": "event_fusion", + "role": "filter", + "enable": true + }, + { + "id": "osd", + "type": "osd", + "role": "filter", + "enable": true, + "draw_bbox": true, + "draw_text": true, + "labels": ["person"] + }, + { + "id": "post", + "type": "preprocess", + "role": "filter", + "enable": true, + "dst_w": 1920, + "dst_h": 1080, + "dst_format": "nv12", + "resize_mode": "stretch", + "use_rga": true + }, + { + "id": "pub", + "type": "publish", + "role": "filter", + "enable": true, + "codec": "h264", + "fps": 25, + "bitrate_kbps": 2000, + "outputs": [ + { "proto": "rtsp_server", "port": 8555, "path": "/live/behavior_full" } + ] + }, + { + "id": "alarm", + "type": "alarm", + "role": "sink", + "enable": true, + "rules": [ + { + "name": "intrusion_zone_a", + "use_behavior_events": true, + "event_types": ["intrusion"], + "region_ids": ["zone_a"], + "min_duration_ms": 1000, + "cooldown_ms": 10000 + }, + { + "name": "climb_fence_1", + "use_behavior_events": true, + "event_types": ["climb"], + "region_ids": ["fence_1"], + "min_duration_ms": 300, + "cooldown_ms": 8000 + }, + { + "name": "fall_detected", + "use_behavior_events": true, + "event_types": ["fall"], + "min_duration_ms": 300, + "cooldown_ms": 12000 + }, + { + "name": "fight_detected", + "use_behavior_events": true, + "event_types": ["fight"], + "min_duration_ms": 200, + "cooldown_ms": 12000 + } + ], + "actions": { + "log": { + "enable": true, + "level": "info" + } + } + } + ], + "edges": [ + ["in", "pre"], + ["pre", "person_det"], + ["person_det", "trk"], + ["trk", "region_evt"], + ["region_evt", "action_evt"], + ["action_evt", "fusion"], + ["fusion", "osd"], + ["osd", "post"], + ["post", "pub"], + ["pub", "alarm"] + ] + } + ] +} diff --git a/configs/sample_region_behavior_intrusion.json b/configs/sample_region_behavior_intrusion.json new file mode 100644 index 0000000..ab280d2 --- /dev/null +++ b/configs/sample_region_behavior_intrusion.json @@ -0,0 +1,151 @@ +{ + "queue": { + "size": 8, + "strategy": "drop_oldest" + }, + "graphs": [ + { + "name": "sample_region_behavior_intrusion", + "nodes": [ + { + "id": "in", + "type": "input_rtsp", + "role": "source", + "enable": true, + "url": "rtsp://127.0.0.1/live", + "fps": 25, + "width": 1920, + "height": 1080, + "use_ffmpeg": true, + "use_mpp": false, + "force_tcp": true + }, + { + "id": "pre", + "type": "preprocess", + "role": "filter", + "enable": true, + "dst_w": 1920, + "dst_h": 1080, + "dst_format": "rgb", + "dst_packed": true, + "resize_mode": "stretch", + "use_rga": true + }, + { + "id": "person_det", + "type": "ai_yolo", + "role": "filter", + "enable": true, + "model_path": "./models/yolov8n-640.rknn", + "model_version": "v8", + "model_w": 640, + "model_h": 640, + "num_classes": 80, + "class_filter": [0], + "conf": 0.35, + "nms": 0.45 + }, + { + "id": "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.30, + "max_age_ms": 1000, + "min_hits": 2 + }, + { + "id": "region_evt", + "type": "region_event", + "role": "filter", + "enable": true, + "events": [ + { + "type": "intrusion", + "region_id": "zone_a", + "roi": { "x": 0.10, "y": 0.10, "w": 0.35, "h": 0.45 }, + "min_duration_ms": 1000 + } + ] + }, + { + "id": "fusion", + "type": "event_fusion", + "role": "filter", + "enable": true + }, + { + "id": "osd", + "type": "osd", + "role": "filter", + "enable": true, + "draw_bbox": true, + "draw_text": true, + "labels": ["person"] + }, + { + "id": "post", + "type": "preprocess", + "role": "filter", + "enable": true, + "dst_w": 1920, + "dst_h": 1080, + "dst_format": "nv12", + "resize_mode": "stretch", + "use_rga": true + }, + { + "id": "pub", + "type": "publish", + "role": "filter", + "enable": true, + "codec": "h264", + "fps": 25, + "bitrate_kbps": 2000, + "outputs": [ + { "proto": "rtsp_server", "port": 8555, "path": "/live/behavior_intrusion" } + ] + }, + { + "id": "alarm", + "type": "alarm", + "role": "sink", + "enable": true, + "rules": [ + { + "name": "intrusion_zone_a", + "use_behavior_events": true, + "event_types": ["intrusion"], + "region_ids": ["zone_a"], + "min_duration_ms": 1000, + "cooldown_ms": 10000 + } + ], + "actions": { + "log": { + "enable": true, + "level": "info" + } + } + } + ], + "edges": [ + ["in", "pre"], + ["pre", "person_det"], + ["person_det", "trk"], + ["trk", "region_evt"], + ["region_evt", "fusion"], + ["fusion", "osd"], + ["osd", "post"], + ["post", "pub"], + ["pub", "alarm"] + ] + } + ] +}