将 Frigate 默认的 SSD MobileNet 检测器替换为 YOLOv9t(tiny),通过 OpenVINO 运行在 Intel N97 的核显上。涵盖模型导出、正确的 Frigate 配置,以及一个会导致 100% 误报的关键坑。
环境#
- 服务器: Intel N97(Debian 13),8 路摄像头
- Frigate: 0.17,Docker 运行
- 检测器: OpenVINO GPU(
/dev/dri/renderD128) - 原模型: SSD MobileNet v2(内置,300×300)
- 新模型: YOLOv9t ONNX(320×320,8.3 MB)
为什么换 YOLOv9t?#
Frigate OpenVINO 镜像自带的 SSD MobileNet v2 速度快、资源占用低,但对画面边缘目标和部分遮挡目标的识别能力较弱。YOLOv9t(tiny)在精度上有明显提升,计算量却相差不大——在 320×320 输入、N97 核显约 18ms 推理速度下,跑 8 路摄像头完全够用。
导出模型#
YOLOv9t 不在 Frigate 内置镜像里,需要自行导出。在宿主机上运行:
| |
这个命令会下载预训练的 YOLOv9t 权重,以 320×320 输入尺寸导出为 ONNX 格式,并将 yolov9t.onnx(8.3 MB)保存到 Frigate 的 config 目录——该目录在容器内挂载为 /config。
Frigate 配置#
模型通过 /config 挂载,容器内路径为 /config/model_cache/yolov9t.onnx。YOLO 模型使用的 80 类 COCO labelmap 已内置于 Frigate 容器,路径为 /labelmap/coco-80.txt。
| |
关键坑:不要用 model_type: yolov9#
不要写 model_type: yolov9。 看起来是对的,但在 Frigate 0.17 中这是无效值。有效值只有:dfine、rfdetr、ssd、yolox、yolonas、yolo-generic。
写 yolov9 会触发配置校验错误,Frigate 进入 safe mode,悄悄回退到基于 CPU 的 TFLite 备用模型。那个模型对什么都给出接近 100% 的置信度——树叶被检测为人,空车道里全是车。看起来新模型完全失控,但实际上新模型根本没有加载。
所有 Ultralytics YOLO 模型(v8、v9 等)正确的写法都是 yolo-generic。
输出张量格式#
导出的 ONNX 模型输出形状为 [1, 84, 2100]:
- 84 个通道 = 4 个边框坐标(xywh,像素坐标)+ 80 个类别分数
- 2100 = 320×320 输入下的 anchor 点数量
Frigate 的 yolo-generic 处理器会正确地转置并后处理这个输出,包括坐标归一化和 NMS,无需额外配置。
推理速度#
切换后,OpenVINO 检测器推理速度约 18ms,对于 8 路 1–5 FPS 的摄像头流完全够用。
| |
API 分数显示 Bug#
在 Frigate 0.17 中,events API 顶层的 top_score 字段对自定义模型检测到的事件返回 null。真实分数嵌套在 data.score 和 data.top_score 里。这是一个显示 bug——检测本身正常工作,完整事件 JSON 中可以看到真实置信度(比如停放车辆 0.75–0.88)。
阈值#
原来各摄像头的 min_score 和 threshold 是针对 SSD 的置信度分布单独调过的。YOLOv9t 整体精度更高,重置为 Frigate 默认值(min_score: 0.5,threshold: 0.7),只保留各摄像头的遮罩区域(mask)。后续根据实际检测情况再微调。