7.0 KiB
7.0 KiB
冷藏展示柜食品批次计时报警
这是一个独立项目,用于单摄像头监控冷藏展示柜和同画面垃圾桶,记录每个展示区域内食品批次的放置时长,并发现超过自定义报警时间后的异常处理行为。
已确认业务规则
- 摄像头同时看到展示柜和垃圾桶。
- 展示柜食品区域支持 1 到 10 个自定义区域。
- 食品区域使用阿拉伯数字标注:
1、2、3... - 垃圾桶 ROI 独立标定,不占用食品区域编号。
- 每个区域可以放多份食品,但这些食品按同一批次计时。
- 同一区域不允许混批,必须清空后才能放入新批次。
- 食品放入区域时记录开始时间。
- 区域清空时记录结束时间。
- 未达到报警阈值前清空视为正常消耗。
- 食品在区域内达到
max_dwell_seconds时先产生time_alarm。 - 已报警食品从区域移出后,必须在确认窗口内看到垃圾桶投放动作。
- 如果已报警食品移出后没有丢到垃圾桶里,报警事件升级为
warning_escalated警告事件。 - 已报警食品拿出后又放回展示柜,触发违规事件。
当前实现范围
当前版本已经接入可运行的轻量视觉流程:区域占用、垃圾桶动作和 v1.2 的轻量 motion trajectory 都使用启发式图像差分实现,不使用 YOLO。后续训练好的 YOLO 食品检测模型会通过统一的 disposal_evidence / backend 合约接入,不改变批次计时状态机的业务输入形态。
视觉或 backend 模块需要输出标准观察数据:
{
"ts": "2026-04-27T10:00:00+08:00",
"zone_counts": {
"1": 1,
"2": 0
},
"trash_deposit": false,
"disposal_evidence": [
{
"source_zone_id": "1",
"target": "trash",
"confidence": 0.9,
"method": "motion",
"track_points": [
{"x": 0.22, "y": 0.30},
{"x": 0.48, "y": 0.58},
{"x": 0.76, "y": 0.78}
],
"item_class": null,
"detector_score": null,
"observed_at": "2026-04-27T10:00:03+08:00"
}
]
}
程序会输出 JSONL 事件,例如:
batch_startedtime_alarmbatch_consumedbatch_pending_disposalbatch_discardedwarning_escalatedmixed_batch_violationoverdue_return_violation
配置
示例配置在 config/example.toml。
默认阈值:
- 时间报警阈值:
10800秒,也就是 3 小时;管理页按分钟输入,例如 20 分钟会保存为1200秒 - 垃圾桶投放确认窗口:
120秒
食品区域配置示例:
[layout]
zone_count = 3
zone_ids = ["1", "2", "3"]
[[zones]]
id = "1"
label = "区域 1"
polygon = [[0.1, 0.1], [0.3, 0.1], [0.3, 0.3]]
[trash]
roi = [[0.7, 0.7], [0.9, 0.7], [0.9, 0.9]]
区域标定
项目现在有正式管理页,前端默认 23000,后端默认 19080。
scripts/run_manage_api.sh
另开一个终端:
scripts/run_web.sh
打开:
http://127.0.0.1:23000
管理页支持:
- 配置 RTSP 地址和阈值
- 从 RTSP 拉取一帧截图
- 设置 1 到 10 个食品区域
- 标定数字食品区域和垃圾桶 ROI
- 直接保存标定结果到项目配置文件
- 查看事件汇总、区域序号、停留时间、报警和警告事件
项目仍保留 tools/calibrator 作为轻量单页标定工具,但正式使用建议走 23000 管理页。
管理 API
默认后端:
http://127.0.0.1:19080
主要接口:
GET /api/manage/healthGET /api/manage/configPUT /api/manage/configPOST /api/manage/snapshotPUT /api/manage/calibrationGET /api/manage/summaryGET /api/manage/events
运行识别计时进程
管理页只负责配置和查看数据。要产生数据,还需要启动运行进程:
scripts/run_runtime.sh
运行进程会:
- 按配置读取 RTSP。
- 用
ffmpeg周期抓取小尺寸 RGB 帧。 - 按标定区域做占用变化检测。
- 判断垃圾桶区域是否有明显投放动作。
- 对刚清空的来源区域运行轻量 motion trajectory,生成可选的
disposal_evidence。 - 调用批次计时状态机,优先使用匹配
source_zone_id的disposal_evidence确认丢弃,再回退到通用垃圾桶动作。 - 写入
logs/events.jsonl,管理页会读取这个文件。
当前视觉版本是可运行的启发式版本:
- 每个格口输出
0/1占用状态,不识别单份数量。 - 启动后的前几帧用于建立空柜基线,默认
3帧。 - 如果启动时格口里已经有食品,系统会把它当作基线,后续要等画面变化后才会产生计时事件。
- v1.2 轨迹识别是轻量 motion trajectory,不加载 YOLO,不要求模型文件。
- 训练好的 YOLO 模型后续应作为新的 backend 接入,并继续输出统一的
disposal_evidence。
可选运行参数可以放在配置文件的 [runtime] 中:
[runtime]
sample_interval_seconds = 5.0
frame_width = 640
frame_height = 360
capture_timeout_seconds = 12.0
baseline_frames = 3
sample_stride_pixels = 4
occupancy_mean_delta = 55.0
occupancy_texture_delta = 18.0
occupancy_dark_luma_threshold = 80.0
occupancy_dark_fraction = 0.06
occupancy_texture_dark_fraction = 0.04
occupancy_bright_luma_threshold = 220.0
occupancy_bright_reflection_fraction = 0.18
occupancy_reflection_dark_fraction = 0.10
occupancy_reflection_bright_dark_ratio = 2.0
occupancy_confirm_frames = 2
empty_confirm_frames = 2
lighting_shift_guard_enabled = true
lighting_shift_min_regions = 3
lighting_shift_region_fraction = 0.6
lighting_shift_mean_delta = 45.0
trash_motion_delta = 18.0
trash_sustained_motion_delta = 8.0
trash_sustained_motion_frames = 2
trash_motion_cooldown_seconds = 3
trajectory_enabled = true
trajectory_window_seconds = 8
trajectory_sample_interval_seconds = 1.0
trajectory_min_points = 3
trajectory_min_confidence = 0.72
trajectory_motion_delta = 20.0
trajectory_min_blob_area = 12
trajectory_max_blob_area_fraction = 0.35
trajectory_trash_entry_margin = 0.04
trajectory_backend = "motion"
yolo_enabled = false
yolo_model_path = ""
yolo_min_confidence = 0.65
diagnostics_path = "logs/runtime_diagnostics.jsonl"
trajectory_backend = "motion" 表示当前使用轻量轨迹 backend。yolo_enabled、yolo_model_path 和 yolo_min_confidence 是为后续训练模型预留的配置项;当前版本即使保留这些字段,也不会启用 YOLO 推理。
运行诊断写入 logs/runtime_diagnostics.jsonl。每行包含顶层 disposal_evidence,以及 diagnostics.trajectory:
- 顶层
disposal_evidence:本帧实际输出给状态机的来源区域到垃圾桶证据。 diagnostics.lighting_shift:多数区域同时同方向亮度漂移时启用,防止灯光/曝光变化被当成食品进出。diagnostics.trajectory:轻量轨迹 backend 的候选、过期、拒绝和已发出证据等调试信息。
本地测试
PYTHONPATH=src python3 -m unittest discover -s tests -v
前端测试和构建:
node --test web/test/zone-state.test.js
cd web && pnpm build