Switch Frigate detection model from YOLO-NAS-S to YOLOv9-c (#246)
## Summary - Replace abandoned YOLO-NAS-S (320x320, `yolonas`) with YOLOv9-c (640x640, `yolo-generic`) - YOLOv9-c benefits from CUDA Graphs in Frigate 0.17 on the RTX 4080 - Add `export_yolov9` Dagger pipeline and `frigate-export-model` mise task for reproducible model exports - Model already deployed to `sifaka:/volume1/frigate/models/yolov9-c-640.onnx` ## Config changes - `model_type: yolonas` → `yolo-generic` - `input_dtype: int` → `float` - `width/height: 320` → `640` - `path:` → `yolov9-c-640.onnx` ## Deployment and Testing - [ ] Merge and sync Frigate ArgoCD app: `argocd app sync frigate` - [ ] Verify Frigate starts and detects objects at https://nvr.ops.eblu.me - [ ] Confirm GPU inference via Frigate system metrics Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/246
This commit is contained in:
parent
2c081eed28
commit
d51c180fe6
5 changed files with 144 additions and 7 deletions
|
|
@ -152,6 +152,87 @@ class BlumeopsCi:
|
|||
.file(f"/workspace/{flake_path}/flake.lock")
|
||||
)
|
||||
|
||||
@function
|
||||
async def export_yolov9(
|
||||
self,
|
||||
model_size: str = "c",
|
||||
input_size: int = 640,
|
||||
) -> dagger.File:
|
||||
"""Export YOLOv9 pretrained weights to ONNX for Frigate NVR.
|
||||
|
||||
Downloads pretrained weights from the WongKinYiu/yolov9 repo and
|
||||
exports to ONNX with onnx-simplifier. Use with Frigate's
|
||||
`model_type: yolo-generic`.
|
||||
|
||||
Args:
|
||||
model_size: Model variant: s (small), c (compact), e (extra-large).
|
||||
input_size: Input resolution (width and height). 640 recommended.
|
||||
"""
|
||||
output_file = f"yolov9-{model_size}-{input_size}.onnx"
|
||||
weights_url = (
|
||||
"https://github.com/WongKinYiu/yolov9/releases/download/v0.1/"
|
||||
f"yolov9-{model_size}-converted.pt"
|
||||
)
|
||||
# Patch torch.load to allow weights_only=False (required for
|
||||
# YOLOv9 checkpoints that contain non-tensor objects).
|
||||
patch_and_export = (
|
||||
"set -e; "
|
||||
"cd /yolov9 && "
|
||||
"sed -i "
|
||||
'"s/ckpt = torch.load(attempt_download(w),'
|
||||
" map_location='cpu')/ckpt = torch.load(attempt_download(w),"
|
||||
" map_location='cpu', weights_only=False)/g\""
|
||||
" models/experimental.py && "
|
||||
f"python3 export.py --weights ./weights.pt"
|
||||
f" --imgsz {input_size} --simplify --include onnx && "
|
||||
f"mv ./weights.onnx /output/{output_file}"
|
||||
)
|
||||
return await (
|
||||
dag.container(platform=dagger.Platform("linux/amd64"))
|
||||
.from_("python:3.11-slim")
|
||||
.with_exec(["apt-get", "update", "-qq"])
|
||||
.with_exec(
|
||||
[
|
||||
"apt-get",
|
||||
"install",
|
||||
"-y",
|
||||
"-qq",
|
||||
"git",
|
||||
"libgl1",
|
||||
"libglib2.0-0",
|
||||
"cmake",
|
||||
"build-essential",
|
||||
]
|
||||
)
|
||||
.with_exec(
|
||||
[
|
||||
"git",
|
||||
"clone",
|
||||
"--depth=1",
|
||||
"https://github.com/WongKinYiu/yolov9.git",
|
||||
"/yolov9",
|
||||
]
|
||||
)
|
||||
.with_exec(
|
||||
[
|
||||
"pip",
|
||||
"install",
|
||||
"--quiet",
|
||||
"-r",
|
||||
"/yolov9/requirements.txt",
|
||||
"numpy<2",
|
||||
"onnx>=1.18.0",
|
||||
"onnxruntime",
|
||||
"onnx-simplifier>=0.4.1",
|
||||
"onnxscript",
|
||||
]
|
||||
)
|
||||
.with_exec(["mkdir", "-p", "/output"])
|
||||
.with_file("/yolov9/weights.pt", dag.http(weights_url))
|
||||
.with_exec(["sh", "-c", patch_and_export])
|
||||
.file(f"/output/{output_file}")
|
||||
)
|
||||
|
||||
@function
|
||||
async def flake_update(
|
||||
self, src: dagger.Directory, flake_path: str = "nixos/ringtail"
|
||||
|
|
|
|||
|
|
@ -63,12 +63,12 @@ data:
|
|||
type: onnx
|
||||
|
||||
model:
|
||||
model_type: yolonas
|
||||
width: 320
|
||||
height: 320
|
||||
model_type: yolo-generic
|
||||
width: 640
|
||||
height: 640
|
||||
input_tensor: nchw
|
||||
input_dtype: int
|
||||
path: /media/frigate/models/yolo_nas_s.onnx
|
||||
input_dtype: float
|
||||
path: /media/frigate/models/yolov9-c-640.onnx
|
||||
labelmap_path: /labelmap/coco-80.txt
|
||||
|
||||
record:
|
||||
|
|
|
|||
1
docs/changelog.d/feature-frigate-yolov9-model.feature.md
Normal file
1
docs/changelog.d/feature-frigate-yolov9-model.feature.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Switch Frigate object detection from YOLO-NAS-S (320x320) to YOLOv9-c (640x640) with CUDA Graphs support, and add `frigate-export-model` Dagger pipeline + mise task for reproducible model exports.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Frigate
|
||||
modified: 2026-02-19
|
||||
modified: 2026-02-22
|
||||
tags:
|
||||
- service
|
||||
- surveillance
|
||||
|
|
@ -47,7 +47,7 @@ Camera credentials are stored in 1Password and synced via [[external-secrets]] t
|
|||
|
||||
## Detection
|
||||
|
||||
Object detection runs on [[ringtail]]'s RTX 4080 via the ONNX detector with CUDA execution provider. The model is YOLO-NAS-S (`yolo_nas_s.onnx`). The previous Apple Silicon Detector on [[indri]] has been retired.
|
||||
Object detection runs on [[ringtail]]'s RTX 4080 via the ONNX detector with CUDA execution provider (TensorRT). The model is YOLOv9-c at 640x640 (`yolov9-c-640.onnx`, `model_type: yolo-generic`), which benefits from CUDA Graphs in Frigate 0.17. To re-export or change model size, use `mise run frigate-export-model`.
|
||||
|
||||
Two zones are configured: `driveway_entrance` (triggers review alerts for person/car) and `driveway` (triggers review detections).
|
||||
|
||||
|
|
|
|||
55
mise-tasks/frigate-export-model
Executable file
55
mise-tasks/frigate-export-model
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env bash
|
||||
#MISE description="Export YOLOv9 model weights to ONNX for Frigate NVR via Dagger"
|
||||
#USAGE flag "--model-size <size>" default="c" help="Model variant: s (small), c (compact), e (extra-large)"
|
||||
#USAGE flag "--input-size <pixels>" default="640" help="Input resolution (width=height)"
|
||||
#USAGE flag "--deploy" help="Copy exported model to sifaka NAS frigate share"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
MODEL_SIZE="${usage_model_size:-c}"
|
||||
INPUT_SIZE="${usage_input_size:-640}"
|
||||
DEPLOY="${usage_deploy:-false}"
|
||||
OUTPUT_FILE="yolov9-${MODEL_SIZE}-${INPUT_SIZE}.onnx"
|
||||
|
||||
echo "Exporting YOLOv9-${MODEL_SIZE} (${INPUT_SIZE}x${INPUT_SIZE}) via Dagger..."
|
||||
echo ""
|
||||
|
||||
dagger call export-yolov-9 \
|
||||
--model-size="$MODEL_SIZE" \
|
||||
--input-size="$INPUT_SIZE" \
|
||||
export --path="$OUTPUT_FILE"
|
||||
|
||||
SIZE=$(du -h "$OUTPUT_FILE" | cut -f1)
|
||||
echo ""
|
||||
echo "Exported: ${OUTPUT_FILE} (${SIZE})"
|
||||
|
||||
if [[ "$DEPLOY" == "true" ]]; then
|
||||
DEST="sifaka:/volume1/frigate/models/${OUTPUT_FILE}"
|
||||
echo "Copying to ${DEST}..."
|
||||
scp -O "$OUTPUT_FILE" "$DEST"
|
||||
echo "Deployed."
|
||||
echo ""
|
||||
echo "Update argocd/manifests/frigate/configmap.yaml:"
|
||||
echo " model:"
|
||||
echo " model_type: yolo-generic"
|
||||
echo " width: ${INPUT_SIZE}"
|
||||
echo " height: ${INPUT_SIZE}"
|
||||
echo " input_tensor: nchw"
|
||||
echo " input_dtype: float"
|
||||
echo " path: /media/frigate/models/${OUTPUT_FILE}"
|
||||
echo " labelmap_path: /labelmap/coco-80.txt"
|
||||
else
|
||||
echo ""
|
||||
echo "To deploy to Frigate NAS:"
|
||||
echo " scp ${OUTPUT_FILE} sifaka:/volume1/frigate/models/"
|
||||
echo ""
|
||||
echo "Then update argocd/manifests/frigate/configmap.yaml:"
|
||||
echo " model:"
|
||||
echo " model_type: yolo-generic"
|
||||
echo " width: ${INPUT_SIZE}"
|
||||
echo " height: ${INPUT_SIZE}"
|
||||
echo " input_tensor: nchw"
|
||||
echo " input_dtype: float"
|
||||
echo " path: /media/frigate/models/${OUTPUT_FILE}"
|
||||
echo " labelmap_path: /labelmap/coco-80.txt"
|
||||
fi
|
||||
Loading…
Add table
Add a link
Reference in a new issue