apocaliss92's picture
camstack-train 0.1.0: YOLOv9 root detector fine-tune (job.json in, result.json + bundle.tar out)
ebeed67 verified
Raw History Blame Contribute Delete
2.41 kB
"""YOLO-NAS postprocessor — Frigate-style flat batched-NMS ONNX export.
Frigate+ ``yolonas`` models (and any super-gradients ``model.export()`` with
fused NMS in FLAT format) emit ONE output tensor of shape ``[N, 7]`` where each
row is ``(batch_index, x1, y1, x2, y2, score, class_id)``:
- coordinates are in INPUT pixel space (0..inputSize), post-NMS,
- GPU exports pad unused slots with a NEGATIVE class id (skip them),
- class ids index the model's own label map (Frigate+ label set or COCO-80).
Output matches the yolo postprocessor:
``{"kind": "detections", "detections": [{"class", "score", "bbox": [x1,y1,x2,y2]}]}``
with pixel bboxes re-projected to ORIGINAL frame coordinates (letterbox undone
via the pool-provided ``scale`` + ``pad``).
"""
from __future__ import annotations
import numpy as np
from .yolo import COCO_80
def postprocess_yolonas(
predictions: dict,
config: dict,
orig_w: int,
orig_h: int,
scale: float,
pad: tuple[int, int],
) -> dict:
conf_threshold = float(config.get("confidence", 0))
labels = config.get("labels", COCO_80)
output = np.asarray(list(predictions.values())[0])
# Accept [1, N, 7] batched exports by squeezing the batch axis.
if output.ndim == 3:
output = output.reshape(-1, output.shape[-1])
if output.ndim != 2 or output.shape[-1] != 7:
raise ValueError(
f"yolonas postprocessor expects a flat [N, 7] output, got shape {output.shape}"
)
detections = []
for row in output:
_batch_idx, x1, y1, x2, y2, score, class_id = row
score = float(score)
class_id = int(class_id)
if class_id < 0:
continue
if score < conf_threshold:
continue
ox1 = max(0.0, min(float(orig_w), (float(x1) - pad[0]) / scale))
oy1 = max(0.0, min(float(orig_h), (float(y1) - pad[1]) / scale))
ox2 = max(0.0, min(float(orig_w), (float(x2) - pad[0]) / scale))
oy2 = max(0.0, min(float(orig_h), (float(y2) - pad[1]) / scale))
label = labels[class_id] if class_id < len(labels) else str(class_id)
detections.append(
{
"class": label,
"score": round(score, 4),
"bbox": [round(ox1, 1), round(oy1, 1), round(ox2, 1), round(oy2, 1)],
}
)
return {"kind": "detections", "detections": detections}