meaculpitt commited on
Commit
2020e13
Β·
verified Β·
1 Parent(s): 01a958c

scorevision: push artifact

Browse files
Files changed (1) hide show
  1. miner.py +80 -29
miner.py CHANGED
@@ -1,5 +1,5 @@
1
  """
2
- Score Vision SN44 β€” Unified miner v3.23.3 (2026-04-07). Diagnostic: vehicle provider logging. Lazy FP32, trigger 0 boxes. TTA consensus (person), parts_confirm on vehicle, car 0.60, VEH_MIN_WH=20.
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.25
 
 
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
- logger.info(f"[init] Petrol model loaded: {petrol_shape}, end2end={self._petrol_end2end}")
 
 
 
 
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: aspect ratio + area checks."""
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
- penalty = PETROL_GEOM_PENALTY
2258
- elif cls_id == PETROL_CLS_PUMP and aspect > PETROL_PUMP_MAX_ASPECT:
2259
- penalty = PETROL_GEOM_PENALTY
2260
- elif cls_id == PETROL_CLS_PRICEBOARD and area_frac > PETROL_PRICEBOARD_MAX_AREA_FRAC:
2261
- penalty = PETROL_GEOM_PENALTY
2262
- elif cls_id == PETROL_CLS_HOSE and area_frac < PETROL_HOSE_MIN_AREA_FRAC:
2263
- penalty = PETROL_GEOM_PENALTY
2264
- new_conf = max(0.0, conf - penalty)
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 _infer_petrol(self, image_bgr: ndarray) -> list[BoundingBox]:
2319
- """Full petrol inference pipeline: preprocess β†’ forward β†’ decode β†’ validate β†’ cooccurrence."""
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
- dets = self._petrol_decode_end2end(out, orig_h, orig_w)
2325
  else:
2326
- dets = self._petrol_decode_raw(out, orig_h, orig_w)
2327
- if not dets:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2328
  return []
2329
 
2330
- dets = self._petrol_geometric_validate(dets, orig_h, orig_w)
2331
- dets = self._petrol_spatial_cooccurrence(dets, orig_h, orig_w)
2332
 
2333
  out_boxes = []
2334
- for x1, y1, x2, y2, conf, cls_id in dets:
2335
  out_boxes.append(BoundingBox(
2336
- x1=max(0, min(orig_w, math.floor(x1))),
2337
- y1=max(0, min(orig_h, math.floor(y1))),
2338
- x2=max(0, min(orig_w, math.ceil(x2))),
2339
- y2=max(0, min(orig_h, math.ceil(y2))),
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
  ))