scorevision: push artifact
Browse files
miner.py
CHANGED
|
@@ -35,9 +35,40 @@ from pathlib import Path
|
|
| 35 |
|
| 36 |
import numpy as np
|
| 37 |
import onnxruntime as ort
|
|
|
|
| 38 |
|
| 39 |
MANIFEST_OBJECTS = ["fire", "smoke", "fire extinguisher"]
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
MODEL_FILE = "model.onnx"
|
| 42 |
# 640/672/768 all fit the CPU budget; the incumbent runs 672 at 43.7 ms p95
|
| 43 |
# on a 4-thread box against a 110 ms ceiling, so 768 is affordable and buys
|
|
@@ -308,8 +339,8 @@ class Miner:
|
|
| 308 |
x1, y1, x2, y2 = boxes[i]
|
| 309 |
if x2 <= x1 or y2 <= y1:
|
| 310 |
continue
|
| 311 |
-
out.append(
|
| 312 |
-
|
| 313 |
if len(out) >= MAX_DET:
|
| 314 |
break
|
| 315 |
return out
|
|
@@ -335,6 +366,6 @@ class Miner:
|
|
| 335 |
# "crashed" - silent except made those indistinguishable.
|
| 336 |
self.last_error = f"{type(e).__name__}: {e}"
|
| 337 |
dets = []
|
| 338 |
-
results.append(
|
| 339 |
-
|
| 340 |
return results
|
|
|
|
| 35 |
|
| 36 |
import numpy as np
|
| 37 |
import onnxruntime as ort
|
| 38 |
+
from pydantic import BaseModel
|
| 39 |
|
| 40 |
MANIFEST_OBJECTS = ["fire", "smoke", "fire extinguisher"]
|
| 41 |
|
| 42 |
+
|
| 43 |
+
# predict_batch MUST return objects exposing .model_dump(), not plain dicts.
|
| 44 |
+
# The live chute does `fr = frame_result.model_dump()` unconditionally
|
| 45 |
+
# (chute_template/turbovision_chute.py.j2), while the compliance runner does
|
| 46 |
+
# `model_dump() if hasattr(...) else dict(frame_result)`. Returning dicts
|
| 47 |
+
# therefore PASSES compliance and fails every real challenge with
|
| 48 |
+
# "'dict' object has no attribute 'model_dump'" - a successful HTTP 200 whose
|
| 49 |
+
# body is {"success": false}, scored as zero. Mirror the reference contract in
|
| 50 |
+
# scorevision/miner/open_source/example_miner/miner.py exactly.
|
| 51 |
+
class BoundingBox(BaseModel):
|
| 52 |
+
x1: int
|
| 53 |
+
y1: int
|
| 54 |
+
x2: int
|
| 55 |
+
y2: int
|
| 56 |
+
cls_id: int
|
| 57 |
+
conf: float
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class Polygon(BaseModel):
|
| 61 |
+
cls_id: int
|
| 62 |
+
conf: float
|
| 63 |
+
points: list[tuple[int, int]]
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class TVFrameResult(BaseModel):
|
| 67 |
+
frame_id: int
|
| 68 |
+
boxes: list[BoundingBox] | None = None
|
| 69 |
+
polygons: list[Polygon] | None = None
|
| 70 |
+
keypoints: list[tuple[int, int]] | None = None
|
| 71 |
+
|
| 72 |
MODEL_FILE = "model.onnx"
|
| 73 |
# 640/672/768 all fit the CPU budget; the incumbent runs 672 at 43.7 ms p95
|
| 74 |
# on a 4-thread box against a 110 ms ceiling, so 768 is affordable and buys
|
|
|
|
| 339 |
x1, y1, x2, y2 = boxes[i]
|
| 340 |
if x2 <= x1 or y2 <= y1:
|
| 341 |
continue
|
| 342 |
+
out.append(BoundingBox(x1=int(x1), y1=int(y1), x2=int(x2), y2=int(y2),
|
| 343 |
+
cls_id=int(mapped[i]), conf=float(conf[i])))
|
| 344 |
if len(out) >= MAX_DET:
|
| 345 |
break
|
| 346 |
return out
|
|
|
|
| 366 |
# "crashed" - silent except made those indistinguishable.
|
| 367 |
self.last_error = f"{type(e).__name__}: {e}"
|
| 368 |
dets = []
|
| 369 |
+
results.append(TVFrameResult(frame_id=frame_id, boxes=dets,
|
| 370 |
+
polygons=[], keypoints=[]))
|
| 371 |
return results
|