iotaminer commited on
Commit
6ad9ec5
·
verified ·
1 Parent(s): 57889ce

scorevision: push artifact

Browse files
Files changed (1) hide show
  1. miner.py +29 -52
miner.py CHANGED
@@ -24,11 +24,11 @@ class TVFrameResult(BaseModel):
24
 
25
 
26
  class Miner:
27
- def __init__(self,
28
  path_hf_repo: Path
29
  ) -> None:
30
  model_path = path_hf_repo / "weights.onnx"
31
- self.class_names = ['bus', 'car', 'truck', 'motorcycle']
32
  print("ORT version:", ort.__version__)
33
 
34
  try:
@@ -74,26 +74,26 @@ class Miner:
74
 
75
  # ---------- Scoring-oriented thresholds ----------
76
  # Low threshold for candidate generation
77
- self.conf_thres = 0.15
78
 
79
  # High-confidence boxes can survive without TTA confirmation
80
- self.conf_high = 0.50
81
 
82
  # NMS threshold
83
- self.iou_thres = 0.66
84
 
85
  # TTA confirmation IoU
86
- self.tta_match_iou = 0.91
87
 
88
  self.max_det = 150
89
  self.use_tta = True
90
 
91
  # Box sanity filters
92
- self.min_box_area = 4 * 4
93
- self.min_w = 2
94
- self.min_h = 2
95
- self.max_aspect_ratio = 12.0
96
- self.max_box_area_ratio = 0.95
97
 
98
  print(f"✅ ONNX model loaded from: {model_path}")
99
  print(f"✅ ONNX providers: {self.session.get_providers()}")
@@ -217,29 +217,6 @@ class Miner:
217
 
218
  return np.array(keep, dtype=np.intp)
219
 
220
- @classmethod
221
- def _nms_per_class(
222
- cls,
223
- boxes: np.ndarray,
224
- scores: np.ndarray,
225
- cls_ids: np.ndarray,
226
- iou_thresh: float,
227
- max_det: int,
228
- ) -> np.ndarray:
229
- """NMS within each class so overlapping car vs bus predictions are not merged away."""
230
- if len(boxes) == 0:
231
- return np.array([], dtype=np.intp)
232
- keep_all: list[int] = []
233
- for c in np.unique(cls_ids):
234
- idxs = np.nonzero(cls_ids == c)[0]
235
- if len(idxs) == 0:
236
- continue
237
- local_keep = cls._hard_nms(boxes[idxs], scores[idxs], iou_thresh)
238
- keep_all.extend(idxs[local_keep].tolist())
239
- keep_all = np.array(keep_all, dtype=np.intp)
240
- order = np.argsort(scores[keep_all])[::-1]
241
- return keep_all[order[:max_det]]
242
-
243
  @staticmethod
244
  def _box_iou_one_to_many(box: np.ndarray, boxes: np.ndarray) -> np.ndarray:
245
  xx1 = np.maximum(box[0], boxes[:, 0])
@@ -317,7 +294,11 @@ class Miner:
317
  scores = preds[:, 4].astype(np.float32)
318
  cls_ids = preds[:, 5].astype(np.int32)
319
 
320
- # All trained vehicle classes pass: bus, car, truck, motorcycle.
 
 
 
 
321
 
322
  # candidate threshold
323
  keep = scores >= self.conf_thres
@@ -340,9 +321,8 @@ class Miner:
340
  if len(boxes) == 0:
341
  return []
342
 
343
- keep_idx = self._nms_per_class(
344
- boxes, scores, cls_ids, self.iou_thres, self.max_det
345
- )
346
 
347
  boxes = boxes[keep_idx]
348
  scores = scores[keep_idx]
@@ -404,6 +384,11 @@ class Miner:
404
  cls_scores = class_probs[np.arange(len(class_probs)), cls_ids]
405
  scores = obj * cls_scores
406
 
 
 
 
 
 
407
  keep = scores >= self.conf_thres
408
  boxes_xywh = boxes_xywh[keep]
409
  scores = scores[keep]
@@ -426,9 +411,8 @@ class Miner:
426
  if len(boxes) == 0:
427
  return []
428
 
429
- keep_idx = self._nms_per_class(
430
- boxes, scores, cls_ids, self.iou_thres, self.max_det
431
- )
432
 
433
  boxes = boxes[keep_idx]
434
  scores = scores[keep_idx]
@@ -505,15 +489,12 @@ class Miner:
505
 
506
  coords_o = np.array([[b.x1, b.y1, b.x2, b.y2] for b in boxes_orig], dtype=np.float32) if boxes_orig else np.empty((0, 4), dtype=np.float32)
507
  scores_o = np.array([b.conf for b in boxes_orig], dtype=np.float32) if boxes_orig else np.empty((0,), dtype=np.float32)
508
- cls_o = np.array([b.cls_id for b in boxes_orig], dtype=np.int32) if boxes_orig else np.empty((0,), dtype=np.int32)
509
 
510
  coords_f = np.array([[b.x1, b.y1, b.x2, b.y2] for b in boxes_flip], dtype=np.float32) if boxes_flip else np.empty((0, 4), dtype=np.float32)
511
  scores_f = np.array([b.conf for b in boxes_flip], dtype=np.float32) if boxes_flip else np.empty((0,), dtype=np.float32)
512
- cls_f = np.array([b.cls_id for b in boxes_flip], dtype=np.int32) if boxes_flip else np.empty((0,), dtype=np.int32)
513
 
514
  accepted_boxes = []
515
  accepted_scores = []
516
- accepted_cls = []
517
 
518
  # Original view candidates
519
  for i in range(len(coords_o)):
@@ -521,7 +502,6 @@ class Miner:
521
  if score >= self.conf_high:
522
  accepted_boxes.append(coords_o[i])
523
  accepted_scores.append(score)
524
- accepted_cls.append(int(cls_o[i]))
525
  elif len(coords_f) > 0:
526
  ious = self._box_iou_one_to_many(coords_o[i], coords_f)
527
  j = int(np.argmax(ious))
@@ -529,7 +509,6 @@ class Miner:
529
  fused_score = max(score, scores_f[j])
530
  accepted_boxes.append(coords_o[i])
531
  accepted_scores.append(fused_score)
532
- accepted_cls.append(int(cls_o[i]))
533
 
534
  # Flipped-view high-confidence boxes that original missed
535
  for i in range(len(coords_f)):
@@ -540,23 +519,21 @@ class Miner:
540
  if len(coords_o) == 0:
541
  accepted_boxes.append(coords_f[i])
542
  accepted_scores.append(score)
543
- accepted_cls.append(int(cls_f[i]))
544
  continue
545
 
546
  ious = self._box_iou_one_to_many(coords_f[i], coords_o)
547
  if np.max(ious) < self.tta_match_iou:
548
  accepted_boxes.append(coords_f[i])
549
  accepted_scores.append(score)
550
- accepted_cls.append(int(cls_f[i]))
551
 
552
  if not accepted_boxes:
553
  return []
554
 
555
  boxes = np.array(accepted_boxes, dtype=np.float32)
556
  scores = np.array(accepted_scores, dtype=np.float32)
557
- cls_ids = np.array(accepted_cls, dtype=np.int32)
558
 
559
- keep = self._nms_per_class(boxes, scores, cls_ids, self.iou_thres, self.max_det)
 
560
 
561
  out = []
562
  for idx in keep:
@@ -567,7 +544,7 @@ class Miner:
567
  y1=int(math.floor(y1)),
568
  x2=int(math.ceil(x2)),
569
  y2=int(math.ceil(y2)),
570
- cls_id=int(cls_ids[idx]),
571
  conf=float(scores[idx]),
572
  )
573
  )
@@ -620,4 +597,4 @@ class Miner:
620
  )
621
  )
622
 
623
- return results
 
24
 
25
 
26
  class Miner:
27
+ def __init__(self,
28
  path_hf_repo: Path
29
  ) -> None:
30
  model_path = path_hf_repo / "weights.onnx"
31
+ self.class_names = ["person"]
32
  print("ORT version:", ort.__version__)
33
 
34
  try:
 
74
 
75
  # ---------- Scoring-oriented thresholds ----------
76
  # Low threshold for candidate generation
77
+ self.conf_thres = 0.68
78
 
79
  # High-confidence boxes can survive without TTA confirmation
80
+ self.conf_high = 0.30
81
 
82
  # NMS threshold
83
+ self.iou_thres = 0.35
84
 
85
  # TTA confirmation IoU
86
+ self.tta_match_iou = 0.68
87
 
88
  self.max_det = 150
89
  self.use_tta = True
90
 
91
  # Box sanity filters
92
+ self.min_box_area = 14 * 14
93
+ self.min_w = 8
94
+ self.min_h = 8
95
+ self.max_aspect_ratio = 8.0
96
+ self.max_box_area_ratio = 0.8
97
 
98
  print(f"✅ ONNX model loaded from: {model_path}")
99
  print(f"✅ ONNX providers: {self.session.get_providers()}")
 
217
 
218
  return np.array(keep, dtype=np.intp)
219
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  @staticmethod
221
  def _box_iou_one_to_many(box: np.ndarray, boxes: np.ndarray) -> np.ndarray:
222
  xx1 = np.maximum(box[0], boxes[:, 0])
 
294
  scores = preds[:, 4].astype(np.float32)
295
  cls_ids = preds[:, 5].astype(np.int32)
296
 
297
+ # person only
298
+ keep = cls_ids == 0
299
+ boxes = boxes[keep]
300
+ scores = scores[keep]
301
+ cls_ids = cls_ids[keep]
302
 
303
  # candidate threshold
304
  keep = scores >= self.conf_thres
 
321
  if len(boxes) == 0:
322
  return []
323
 
324
+ keep_idx = self._hard_nms(boxes, scores, self.iou_thres)
325
+ keep_idx = keep_idx[: self.max_det]
 
326
 
327
  boxes = boxes[keep_idx]
328
  scores = scores[keep_idx]
 
384
  cls_scores = class_probs[np.arange(len(class_probs)), cls_ids]
385
  scores = obj * cls_scores
386
 
387
+ keep = cls_ids == 0
388
+ boxes_xywh = boxes_xywh[keep]
389
+ scores = scores[keep]
390
+ cls_ids = cls_ids[keep]
391
+
392
  keep = scores >= self.conf_thres
393
  boxes_xywh = boxes_xywh[keep]
394
  scores = scores[keep]
 
411
  if len(boxes) == 0:
412
  return []
413
 
414
+ keep_idx = self._hard_nms(boxes, scores, self.iou_thres)
415
+ keep_idx = keep_idx[: self.max_det]
 
416
 
417
  boxes = boxes[keep_idx]
418
  scores = scores[keep_idx]
 
489
 
490
  coords_o = np.array([[b.x1, b.y1, b.x2, b.y2] for b in boxes_orig], dtype=np.float32) if boxes_orig else np.empty((0, 4), dtype=np.float32)
491
  scores_o = np.array([b.conf for b in boxes_orig], dtype=np.float32) if boxes_orig else np.empty((0,), dtype=np.float32)
 
492
 
493
  coords_f = np.array([[b.x1, b.y1, b.x2, b.y2] for b in boxes_flip], dtype=np.float32) if boxes_flip else np.empty((0, 4), dtype=np.float32)
494
  scores_f = np.array([b.conf for b in boxes_flip], dtype=np.float32) if boxes_flip else np.empty((0,), dtype=np.float32)
 
495
 
496
  accepted_boxes = []
497
  accepted_scores = []
 
498
 
499
  # Original view candidates
500
  for i in range(len(coords_o)):
 
502
  if score >= self.conf_high:
503
  accepted_boxes.append(coords_o[i])
504
  accepted_scores.append(score)
 
505
  elif len(coords_f) > 0:
506
  ious = self._box_iou_one_to_many(coords_o[i], coords_f)
507
  j = int(np.argmax(ious))
 
509
  fused_score = max(score, scores_f[j])
510
  accepted_boxes.append(coords_o[i])
511
  accepted_scores.append(fused_score)
 
512
 
513
  # Flipped-view high-confidence boxes that original missed
514
  for i in range(len(coords_f)):
 
519
  if len(coords_o) == 0:
520
  accepted_boxes.append(coords_f[i])
521
  accepted_scores.append(score)
 
522
  continue
523
 
524
  ious = self._box_iou_one_to_many(coords_f[i], coords_o)
525
  if np.max(ious) < self.tta_match_iou:
526
  accepted_boxes.append(coords_f[i])
527
  accepted_scores.append(score)
 
528
 
529
  if not accepted_boxes:
530
  return []
531
 
532
  boxes = np.array(accepted_boxes, dtype=np.float32)
533
  scores = np.array(accepted_scores, dtype=np.float32)
 
534
 
535
+ keep = self._hard_nms(boxes, scores, self.iou_thres)
536
+ keep = keep[: self.max_det]
537
 
538
  out = []
539
  for idx in keep:
 
544
  y1=int(math.floor(y1)),
545
  x2=int(math.ceil(x2)),
546
  y2=int(math.ceil(y2)),
547
+ cls_id=0,
548
  conf=float(scores[idx]),
549
  )
550
  )
 
597
  )
598
  )
599
 
600
+ return results