跳过正文
  1. 文章/

Frigate 换用 YOLOv9t + OpenVINO(Intel N97)

作者
Yang Hu

将 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 内置镜像里,需要自行导出。在宿主机上运行:

1
2
3
4
5
mkdir -p /home/yang/docker/frigate/config/model_cache
docker run --rm \
  -v /home/yang/docker/frigate/config/model_cache:/output \
  ultralytics/ultralytics:latest \
  bash -c 'cd /output && yolo export model=yolov9t.pt format=onnx imgsz=320'

这个命令会下载预训练的 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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
detectors:
  ov:
    type: openvino
    device: GPU

model:
  path: /config/model_cache/yolov9t.onnx
  model_type: yolo-generic
  input_tensor: nchw
  input_pixel_format: bgr
  input_dtype: float
  width: 320
  height: 320
  labelmap_path: /labelmap/coco-80.txt

关键坑:不要用 model_type: yolov9
#

不要写 model_type: yolov9 看起来是对的,但在 Frigate 0.17 中这是无效值。有效值只有:dfinerfdetrssdyoloxyolonasyolo-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 的摄像头流完全够用。

1
2
Detector: ov
  inference_speed: 18.5 ms

API 分数显示 Bug
#

在 Frigate 0.17 中,events API 顶层的 top_score 字段对自定义模型检测到的事件返回 null。真实分数嵌套在 data.scoredata.top_score 里。这是一个显示 bug——检测本身正常工作,完整事件 JSON 中可以看到真实置信度(比如停放车辆 0.75–0.88)。

阈值
#

原来各摄像头的 min_scorethreshold 是针对 SSD 的置信度分布单独调过的。YOLOv9t 整体精度更高,重置为 Frigate 默认值(min_score: 0.5threshold: 0.7),只保留各摄像头的遮罩区域(mask)。后续根据实际检测情况再微调。