coolroman commited on
Commit
365d39f
·
verified ·
1 Parent(s): 7691f8a

scorevision: push artifact

Browse files
Files changed (1) hide show
  1. miner.py +4 -9
miner.py CHANGED
@@ -1,4 +1,5 @@
1
- """ScoreVision crime detector — YOLOv11s with flip TTA + per-class conf + cross-class NMS."""
 
2
  from pathlib import Path
3
  import math
4
 
@@ -33,9 +34,9 @@ class Miner:
33
  cross_iou_thresh = 0.50
34
  max_aspect_ratio = 10.0
35
  max_det = 150
36
- # tuned on held-out SAM3-labeled crime set
37
  _conf_thres_array = np.array(
38
- [0.50, 0.50, 0.30, 0.30, 0.40, 0.40], dtype=np.float32
39
  )
40
 
41
  def __init__(self, path_hf_repo: Path) -> None:
@@ -167,7 +168,6 @@ class Miner:
167
  return np.array(keep_all, dtype=np.intp)
168
 
169
  def _cross_class_dedup(self, boxes, scores, cls_ids, iou_thr):
170
- """If two boxes (any class) heavily overlap, keep only the higher-scoring one."""
171
  n = len(boxes)
172
  if n == 0:
173
  return np.array([], dtype=np.intp)
@@ -211,7 +211,6 @@ class Miner:
211
 
212
  def _decode(self, preds: ndarray, ratio: float, pad: tuple[float, float],
213
  orig_size: tuple[int, int]) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
214
- """ONNX output is [1,300,6]: x1,y1,x2,y2,conf,cls in letterboxed coords."""
215
  if preds.ndim == 3 and preds.shape[0] == 1:
216
  preds = preds[0]
217
  if preds.ndim != 2 or preds.shape[1] < 6:
@@ -223,18 +222,15 @@ class Miner:
223
  boxes = preds[:, :4].astype(np.float32)
224
  scores = preds[:, 4].astype(np.float32)
225
  cls_ids = preds[:, 5].astype(np.int32)
226
- # drop padded rows
227
  keep = (scores > 0) & (cls_ids >= 0) & (cls_ids < len(self.class_names))
228
  boxes, scores, cls_ids = boxes[keep], scores[keep], cls_ids[keep]
229
  if len(boxes) == 0:
230
  return boxes, scores, cls_ids
231
- # per-class confidence
232
  thr = self._conf_thres_array[cls_ids]
233
  keep = scores >= thr
234
  boxes, scores, cls_ids = boxes[keep], scores[keep], cls_ids[keep]
235
  if len(boxes) == 0:
236
  return boxes, scores, cls_ids
237
- # untransform: subtract pad, divide ratio
238
  pad_w, pad_h = pad
239
  boxes[:, [0, 2]] -= pad_w
240
  boxes[:, [1, 3]] -= pad_h
@@ -262,7 +258,6 @@ class Miner:
262
  cls_ids = np.concatenate([c0, cf], axis=0) if len(b0) or len(bf) else c0
263
  if len(boxes) == 0:
264
  return []
265
- # filter + per-class NMS + cross-class dedup
266
  boxes, scores, cls_ids = self._filter_sane(
267
  boxes, scores, cls_ids, (image.shape[1], image.shape[0])
268
  )
 
1
+ """ScoreVision crime detector v24 — YOLOv11s trained on rival-consensus labels.
2
+ Per-class conf thresholds tuned vs validator-PGT proxy; flip TTA; cross-class NMS."""
3
  from pathlib import Path
4
  import math
5
 
 
34
  cross_iou_thresh = 0.50
35
  max_aspect_ratio = 10.0
36
  max_det = 150
37
+ # per-class thresholds — tuned on rival-consensus GT (proxy for validator PGT)
38
  _conf_thres_array = np.array(
39
+ [0.30, 0.70, 0.60, 0.50, 0.40, 0.40], dtype=np.float32
40
  )
41
 
42
  def __init__(self, path_hf_repo: Path) -> None:
 
168
  return np.array(keep_all, dtype=np.intp)
169
 
170
  def _cross_class_dedup(self, boxes, scores, cls_ids, iou_thr):
 
171
  n = len(boxes)
172
  if n == 0:
173
  return np.array([], dtype=np.intp)
 
211
 
212
  def _decode(self, preds: ndarray, ratio: float, pad: tuple[float, float],
213
  orig_size: tuple[int, int]) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
 
214
  if preds.ndim == 3 and preds.shape[0] == 1:
215
  preds = preds[0]
216
  if preds.ndim != 2 or preds.shape[1] < 6:
 
222
  boxes = preds[:, :4].astype(np.float32)
223
  scores = preds[:, 4].astype(np.float32)
224
  cls_ids = preds[:, 5].astype(np.int32)
 
225
  keep = (scores > 0) & (cls_ids >= 0) & (cls_ids < len(self.class_names))
226
  boxes, scores, cls_ids = boxes[keep], scores[keep], cls_ids[keep]
227
  if len(boxes) == 0:
228
  return boxes, scores, cls_ids
 
229
  thr = self._conf_thres_array[cls_ids]
230
  keep = scores >= thr
231
  boxes, scores, cls_ids = boxes[keep], scores[keep], cls_ids[keep]
232
  if len(boxes) == 0:
233
  return boxes, scores, cls_ids
 
234
  pad_w, pad_h = pad
235
  boxes[:, [0, 2]] -= pad_w
236
  boxes[:, [1, 3]] -= pad_h
 
258
  cls_ids = np.concatenate([c0, cf], axis=0) if len(b0) or len(bf) else c0
259
  if len(boxes) == 0:
260
  return []
 
261
  boxes, scores, cls_ids = self._filter_sane(
262
  boxes, scores, cls_ids, (image.shape[1], image.shape[0])
263
  )