scorevision: push artifact
Browse files
miner.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
"""
|
| 2 |
-
Score Vision SN44 β Unified miner v3.
|
| 3 |
Tri-model: vehicle (YOLO11m INT8 1280) + person (YOLO12s FP16 960 TRT) + petrol (end2end 640).
|
| 4 |
Pose model: YOLOv8n-pose FP16 640 for false-positive filtering + keypoint box refinement.
|
| 5 |
Vehicle weights loaded from secondary HF repo (meaculpitt/ScoreVision-Vehicle).
|
|
@@ -378,7 +378,9 @@ VEHICLE_HF_REPO = "meaculpitt/ScoreVision-Vehicle"
|
|
| 378 |
|
| 379 |
# ββ Petrol config βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 380 |
PETROL_HF_REPO = "meaculpitt/ScoreVision-Petrol"
|
| 381 |
-
PETROL_CONF = 0.
|
|
|
|
|
|
|
| 382 |
PETROL_IOU = 0.45
|
| 383 |
# Class IDs (petrol model output β independent of person/vehicle cls_ids
|
| 384 |
# because element_hint routing ensures only one pipeline runs per challenge)
|
|
@@ -391,7 +393,6 @@ PETROL_CANOPY_MIN_ASPECT = 0.8
|
|
| 391 |
PETROL_PUMP_MAX_ASPECT = 4.0
|
| 392 |
PETROL_PRICEBOARD_MAX_AREA_FRAC = 0.15
|
| 393 |
PETROL_HOSE_MIN_AREA_FRAC = 0.0005
|
| 394 |
-
PETROL_GEOM_PENALTY = 0.10
|
| 395 |
# Spatial co-occurrence
|
| 396 |
PETROL_COOCCUR_PUMP_CANOPY = 0.05
|
| 397 |
PETROL_COOCCUR_PUMP_HOSE = 0.08
|
|
@@ -715,7 +716,11 @@ class Miner:
|
|
| 715 |
and petrol_out_shape[2] == 6
|
| 716 |
and (petrol_out_shape[1] or 0) <= 1000
|
| 717 |
)
|
| 718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 719 |
else:
|
| 720 |
self.petrol_session = None
|
| 721 |
self._petrol_end2end = False
|
|
@@ -2244,7 +2249,7 @@ class Miner:
|
|
| 2244 |
return [dets[idx] for idx in kept]
|
| 2245 |
|
| 2246 |
def _petrol_geometric_validate(self, dets, orig_h, orig_w):
|
| 2247 |
-
"""Per-class shape filters
|
| 2248 |
img_area = max(orig_h * orig_w, 1)
|
| 2249 |
result = []
|
| 2250 |
for x1, y1, x2, y2, conf, cls_id in dets:
|
|
@@ -2252,18 +2257,15 @@ class Miner:
|
|
| 2252 |
bh = max(y2 - y1, 1)
|
| 2253 |
aspect = bw / bh
|
| 2254 |
area_frac = (bw * bh) / img_area
|
| 2255 |
-
penalty = 0.0
|
| 2256 |
if cls_id == PETROL_CLS_CANOPY and aspect < PETROL_CANOPY_MIN_ASPECT:
|
| 2257 |
-
|
| 2258 |
-
|
| 2259 |
-
|
| 2260 |
-
|
| 2261 |
-
|
| 2262 |
-
|
| 2263 |
-
|
| 2264 |
-
|
| 2265 |
-
if new_conf >= PETROL_CONF:
|
| 2266 |
-
result.append((x1, y1, x2, y2, new_conf, cls_id))
|
| 2267 |
return result
|
| 2268 |
|
| 2269 |
def _petrol_spatial_cooccurrence(self, dets, orig_h, orig_w):
|
|
@@ -2315,28 +2317,77 @@ class Miner:
|
|
| 2315 |
result.append((x1, y1, x2, y2, new_conf, cls_id))
|
| 2316 |
return result
|
| 2317 |
|
| 2318 |
-
def
|
| 2319 |
-
"""
|
| 2320 |
inp, (orig_h, orig_w) = self._petrol_preprocess(image_bgr)
|
| 2321 |
out = self.petrol_session.run(None, {self.petrol_input_name: inp})[0]
|
| 2322 |
-
|
| 2323 |
if self._petrol_end2end:
|
| 2324 |
-
|
| 2325 |
else:
|
| 2326 |
-
|
| 2327 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2328 |
return []
|
| 2329 |
|
| 2330 |
-
|
| 2331 |
-
|
| 2332 |
|
| 2333 |
out_boxes = []
|
| 2334 |
-
for x1, y1, x2, y2, conf, cls_id in
|
| 2335 |
out_boxes.append(BoundingBox(
|
| 2336 |
-
x1=max(0, min(
|
| 2337 |
-
y1=max(0, min(
|
| 2338 |
-
x2=max(0, min(
|
| 2339 |
-
y2=max(0, min(
|
| 2340 |
cls_id=cls_id,
|
| 2341 |
conf=max(0.0, min(1.0, conf)),
|
| 2342 |
))
|
|
|
|
| 1 |
"""
|
| 2 |
+
Score Vision SN44 β Unified miner v3.24 (2026-04-07). Petrol v4 weights (960px, GDINO+Mapillary), petrol TTA consensus, hard geometric filter, provider logging. Vehicle: lazy FP32, 0-box trigger. Person: TTA consensus.
|
| 3 |
Tri-model: vehicle (YOLO11m INT8 1280) + person (YOLO12s FP16 960 TRT) + petrol (end2end 640).
|
| 4 |
Pose model: YOLOv8n-pose FP16 640 for false-positive filtering + keypoint box refinement.
|
| 5 |
Vehicle weights loaded from secondary HF repo (meaculpitt/ScoreVision-Vehicle).
|
|
|
|
| 378 |
|
| 379 |
# ββ Petrol config βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 380 |
PETROL_HF_REPO = "meaculpitt/ScoreVision-Petrol"
|
| 381 |
+
PETROL_CONF = 0.30
|
| 382 |
+
PETROL_CONF_ORIG = 0.35
|
| 383 |
+
PETROL_TTA_MATCH_IOU = 0.50
|
| 384 |
PETROL_IOU = 0.45
|
| 385 |
# Class IDs (petrol model output β independent of person/vehicle cls_ids
|
| 386 |
# because element_hint routing ensures only one pipeline runs per challenge)
|
|
|
|
| 393 |
PETROL_PUMP_MAX_ASPECT = 4.0
|
| 394 |
PETROL_PRICEBOARD_MAX_AREA_FRAC = 0.15
|
| 395 |
PETROL_HOSE_MIN_AREA_FRAC = 0.0005
|
|
|
|
| 396 |
# Spatial co-occurrence
|
| 397 |
PETROL_COOCCUR_PUMP_CANOPY = 0.05
|
| 398 |
PETROL_COOCCUR_PUMP_HOSE = 0.08
|
|
|
|
| 716 |
and petrol_out_shape[2] == 6
|
| 717 |
and (petrol_out_shape[1] or 0) <= 1000
|
| 718 |
)
|
| 719 |
+
petrol_actual = self.petrol_session.get_providers()
|
| 720 |
+
logger.warning(f"[init] Petrol session ACTIVE providers: {petrol_actual}")
|
| 721 |
+
if "CUDAExecutionProvider" not in petrol_actual:
|
| 722 |
+
logger.error("[init] β PETROL IS ON CPU β CUDA EP NOT ACTIVE")
|
| 723 |
+
logger.info(f"[init] Petrol model loaded: {self.petrol_h}x{self.petrol_w}, end2end={self._petrol_end2end}")
|
| 724 |
else:
|
| 725 |
self.petrol_session = None
|
| 726 |
self._petrol_end2end = False
|
|
|
|
| 2249 |
return [dets[idx] for idx in kept]
|
| 2250 |
|
| 2251 |
def _petrol_geometric_validate(self, dets, orig_h, orig_w):
|
| 2252 |
+
"""Per-class hard shape filters. Reject detections that fail."""
|
| 2253 |
img_area = max(orig_h * orig_w, 1)
|
| 2254 |
result = []
|
| 2255 |
for x1, y1, x2, y2, conf, cls_id in dets:
|
|
|
|
| 2257 |
bh = max(y2 - y1, 1)
|
| 2258 |
aspect = bw / bh
|
| 2259 |
area_frac = (bw * bh) / img_area
|
|
|
|
| 2260 |
if cls_id == PETROL_CLS_CANOPY and aspect < PETROL_CANOPY_MIN_ASPECT:
|
| 2261 |
+
continue
|
| 2262 |
+
if cls_id == PETROL_CLS_PUMP and (aspect > PETROL_PUMP_MAX_ASPECT or bh < 30):
|
| 2263 |
+
continue
|
| 2264 |
+
if cls_id == PETROL_CLS_PRICEBOARD and (area_frac > PETROL_PRICEBOARD_MAX_AREA_FRAC or (bw * bh) < 200):
|
| 2265 |
+
continue
|
| 2266 |
+
if cls_id == PETROL_CLS_HOSE and (bw * bh) < 400:
|
| 2267 |
+
continue
|
| 2268 |
+
result.append((x1, y1, x2, y2, conf, cls_id))
|
|
|
|
|
|
|
| 2269 |
return result
|
| 2270 |
|
| 2271 |
def _petrol_spatial_cooccurrence(self, dets, orig_h, orig_w):
|
|
|
|
| 2317 |
result.append((x1, y1, x2, y2, new_conf, cls_id))
|
| 2318 |
return result
|
| 2319 |
|
| 2320 |
+
def _petrol_run_pass(self, image_bgr):
|
| 2321 |
+
"""Single petrol inference pass: preprocess -> forward -> decode."""
|
| 2322 |
inp, (orig_h, orig_w) = self._petrol_preprocess(image_bgr)
|
| 2323 |
out = self.petrol_session.run(None, {self.petrol_input_name: inp})[0]
|
|
|
|
| 2324 |
if self._petrol_end2end:
|
| 2325 |
+
return self._petrol_decode_end2end(out, orig_h, orig_w), orig_h, orig_w
|
| 2326 |
else:
|
| 2327 |
+
return self._petrol_decode_raw(out, orig_h, orig_w), orig_h, orig_w
|
| 2328 |
+
|
| 2329 |
+
def _infer_petrol(self, image_bgr: ndarray) -> list[BoundingBox]:
|
| 2330 |
+
"""Petrol inference with flip TTA consensus merging."""
|
| 2331 |
+
if not hasattr(self, '_petrol_providers_logged'):
|
| 2332 |
+
provs = self.petrol_session.get_providers()
|
| 2333 |
+
logger.warning(f"[petrol] First inference β active providers: {provs}")
|
| 2334 |
+
self._petrol_providers_logged = True
|
| 2335 |
+
|
| 2336 |
+
oh, ow = image_bgr.shape[:2]
|
| 2337 |
+
|
| 2338 |
+
# Original pass
|
| 2339 |
+
dets_orig, _, _ = self._petrol_run_pass(image_bgr)
|
| 2340 |
+
|
| 2341 |
+
# Flip pass
|
| 2342 |
+
flipped = cv2.flip(image_bgr, 1)
|
| 2343 |
+
dets_flip, _, _ = self._petrol_run_pass(flipped)
|
| 2344 |
+
# Mirror flip boxes back
|
| 2345 |
+
dets_flip = [(ow - x2, y1, ow - x1, y2, conf, cls_id)
|
| 2346 |
+
for x1, y1, x2, y2, conf, cls_id in dets_flip]
|
| 2347 |
+
|
| 2348 |
+
# Consensus merge: match across views
|
| 2349 |
+
matched_orig = set()
|
| 2350 |
+
matched_flip = set()
|
| 2351 |
+
merged = []
|
| 2352 |
+
|
| 2353 |
+
for i, (ox1, oy1, ox2, oy2, oc, ocls) in enumerate(dets_orig):
|
| 2354 |
+
for j, (fx1, fy1, fx2, fy2, fc, fcls) in enumerate(dets_flip):
|
| 2355 |
+
if ocls != fcls or j in matched_flip:
|
| 2356 |
+
continue
|
| 2357 |
+
ix1, iy1 = max(ox1, fx1), max(oy1, fy1)
|
| 2358 |
+
ix2, iy2 = min(ox2, fx2), min(oy2, fy2)
|
| 2359 |
+
inter = max(0, ix2 - ix1) * max(0, iy2 - iy1)
|
| 2360 |
+
oa = (ox2 - ox1) * (oy2 - oy1)
|
| 2361 |
+
fa = (fx2 - fx1) * (fy2 - fy1)
|
| 2362 |
+
iou = inter / max(oa + fa - inter, 1e-6)
|
| 2363 |
+
if iou >= PETROL_TTA_MATCH_IOU:
|
| 2364 |
+
conf = max(oc, fc)
|
| 2365 |
+
if conf >= PETROL_CONF:
|
| 2366 |
+
merged.append((ox1, oy1, ox2, oy2, conf, ocls))
|
| 2367 |
+
matched_orig.add(i)
|
| 2368 |
+
matched_flip.add(j)
|
| 2369 |
+
break
|
| 2370 |
+
|
| 2371 |
+
# Original-only: keep at stricter threshold
|
| 2372 |
+
for i, det in enumerate(dets_orig):
|
| 2373 |
+
if i not in matched_orig and det[4] >= PETROL_CONF_ORIG:
|
| 2374 |
+
merged.append(det)
|
| 2375 |
+
|
| 2376 |
+
# Flip-only: discard
|
| 2377 |
+
|
| 2378 |
+
if not merged:
|
| 2379 |
return []
|
| 2380 |
|
| 2381 |
+
merged = self._petrol_geometric_validate(merged, oh, ow)
|
| 2382 |
+
merged = self._petrol_spatial_cooccurrence(merged, oh, ow)
|
| 2383 |
|
| 2384 |
out_boxes = []
|
| 2385 |
+
for x1, y1, x2, y2, conf, cls_id in merged:
|
| 2386 |
out_boxes.append(BoundingBox(
|
| 2387 |
+
x1=max(0, min(ow, math.floor(x1))),
|
| 2388 |
+
y1=max(0, min(oh, math.floor(y1))),
|
| 2389 |
+
x2=max(0, min(ow, math.ceil(x2))),
|
| 2390 |
+
y2=max(0, min(oh, math.ceil(y2))),
|
| 2391 |
cls_id=cls_id,
|
| 2392 |
conf=max(0.0, min(1.0, conf)),
|
| 2393 |
))
|