matrice 1.0.99269__py3-none-any.whl → 1.0.99270__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matrice/deploy/utils/post_processing/usecases/proximity_detection.py +85 -64
- {matrice-1.0.99269.dist-info → matrice-1.0.99270.dist-info}/METADATA +1 -1
- {matrice-1.0.99269.dist-info → matrice-1.0.99270.dist-info}/RECORD +6 -6
- {matrice-1.0.99269.dist-info → matrice-1.0.99270.dist-info}/WHEEL +0 -0
- {matrice-1.0.99269.dist-info → matrice-1.0.99270.dist-info}/licenses/LICENSE.txt +0 -0
- {matrice-1.0.99269.dist-info → matrice-1.0.99270.dist-info}/top_level.txt +0 -0
@@ -66,6 +66,7 @@ class ProximityUseCase(BaseProcessor):
|
|
66
66
|
# Proximity counting
|
67
67
|
self._total_proximity_count = 0 # Total proximity events across all calls
|
68
68
|
self._observed_proximity_pairs: Set[frozenset] = set() # Unique canonical ID pairs seen across frames
|
69
|
+
self._last_frame_proximity_pairs: Set[tuple] = set() # Pairs detected in the most recent frame (track-id based)
|
69
70
|
|
70
71
|
|
71
72
|
# --------------------------------------------------------------------- #
|
@@ -589,10 +590,10 @@ class ProximityUseCase(BaseProcessor):
|
|
589
590
|
"""Count UNIQUE proximity events between detections in a frame.
|
590
591
|
|
591
592
|
Rules:
|
592
|
-
-
|
593
|
-
-
|
594
|
-
- Count each pair once (i < j) using Euclidean distance between
|
595
|
-
- Distance is evaluated in meters when calibration is available
|
593
|
+
- Use IoU-NMS to deduplicate overlapping boxes (highest confidence kept).
|
594
|
+
- Use track IDs when available to build stable (id1,id2) pairs.
|
595
|
+
- Count each pair once (i < j) using Euclidean distance between box centers.
|
596
|
+
- Distance is evaluated in meters when calibration is available; otherwise, fallback to pixel threshold.
|
596
597
|
- Maintain a running set of unique canonical-ID pairs across frames to compute total unique proximity events.
|
597
598
|
"""
|
598
599
|
if not detections:
|
@@ -603,81 +604,101 @@ class ProximityUseCase(BaseProcessor):
|
|
603
604
|
threshold_meters = getattr(config, "proximity_threshold_meters", 1.0)
|
604
605
|
threshold_pixels_fallback = getattr(config, "proximity_threshold_pixels", 400.0)
|
605
606
|
|
606
|
-
|
607
|
+
overlap_iou_threshold = getattr(self, "_proximity_iou_duplicate_threshold", 0.5)
|
607
608
|
|
608
|
-
#
|
609
|
-
|
610
|
-
|
609
|
+
# Helper: convert bbox to xyxy list
|
610
|
+
def _to_xyxy(bbox: Any) -> List[float]:
|
611
|
+
if isinstance(bbox, list):
|
612
|
+
if len(bbox) >= 4:
|
613
|
+
return [float(bbox[0]), float(bbox[1]), float(bbox[2]), float(bbox[3])]
|
614
|
+
return []
|
615
|
+
if isinstance(bbox, dict):
|
616
|
+
if all(k in bbox for k in ("xmin", "ymin", "xmax", "ymax")):
|
617
|
+
return [float(bbox["xmin"]), float(bbox["ymin"]), float(bbox["xmax"]), float(bbox["ymax"])]
|
618
|
+
if all(k in bbox for k in ("x1", "y1", "x2", "y2")):
|
619
|
+
return [float(bbox["x1"]), float(bbox["y1"]), float(bbox["x2"]), float(bbox["y2"])]
|
620
|
+
# Fallback: take first four values
|
621
|
+
vals = list(bbox.values())
|
622
|
+
if len(vals) >= 4:
|
623
|
+
return [float(vals[0]), float(vals[1]), float(vals[2]), float(vals[3])]
|
624
|
+
return []
|
625
|
+
return []
|
611
626
|
|
627
|
+
# Prepare tracked detections (track_id, bbox_xyxy, conf)
|
628
|
+
tracked_detections: List[Dict[str, Any]] = []
|
612
629
|
for det in detections:
|
613
|
-
|
614
|
-
bbox = det.get("bounding_box", det.get("bbox", {}))
|
630
|
+
bbox = _to_xyxy(det.get("bounding_box", det.get("bbox", {})))
|
615
631
|
if not bbox:
|
616
632
|
continue
|
633
|
+
tracked_detections.append({
|
634
|
+
"track_id": det.get("track_id"),
|
635
|
+
"bbox": bbox,
|
636
|
+
"confidence": float(det.get("confidence", 1.0))
|
637
|
+
})
|
617
638
|
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
frame_unique_count = 0
|
638
|
-
|
639
|
-
for i in range(len(unique_detections)):
|
640
|
-
det_i = unique_detections[i]
|
641
|
-
bbox_i = det_i.get("bounding_box", det_i.get("bbox", {}))
|
642
|
-
p_i = get_bbox_bottom25_center(bbox_i) or get_bbox_center(bbox_i)
|
643
|
-
if not p_i:
|
644
|
-
continue
|
645
|
-
|
646
|
-
for j in range(i + 1, len(unique_detections)):
|
647
|
-
det_j = unique_detections[j]
|
648
|
-
bbox_j = det_j.get("bounding_box", det_j.get("bbox", {}))
|
649
|
-
p_j = get_bbox_bottom25_center(bbox_j) or get_bbox_center(bbox_j)
|
650
|
-
if not p_j:
|
651
|
-
continue
|
652
|
-
|
653
|
-
dx = float(p_i[0]) - float(p_j[0])
|
654
|
-
dy = float(p_i[1]) - float(p_j[1])
|
655
|
-
pixel_distance = math.hypot(dx, dy)
|
639
|
+
# IoU-NMS to remove overlapping boxes, keep highest confidence
|
640
|
+
kept: List[Dict[str, Any]] = self._nms_by_iou(tracked_detections, overlap_iou_threshold)
|
641
|
+
|
642
|
+
# Compute centroids
|
643
|
+
centroids: Dict[Any, tuple] = {}
|
644
|
+
for td in kept:
|
645
|
+
x1, y1, x2, y2 = map(float, td["bbox"])
|
646
|
+
cx, cy = (x1 + x2) / 2.0, (y1 + y2) / 2.0
|
647
|
+
centroids[td.get("track_id")] = (cx, cy)
|
648
|
+
|
649
|
+
# Build current frame proximity pairs using track IDs only when both exist
|
650
|
+
current_pairs: Set[tuple] = set()
|
651
|
+
ids_list = [tid for tid in centroids.keys() if tid is not None]
|
652
|
+
for i in range(len(ids_list)):
|
653
|
+
for j in range(i + 1, len(ids_list)):
|
654
|
+
id1, id2 = ids_list[i], ids_list[j]
|
655
|
+
cx1, cy1 = centroids[id1]
|
656
|
+
cx2, cy2 = centroids[id2]
|
657
|
+
pixel_distance = math.hypot(cx1 - cx2, cy1 - cy2)
|
656
658
|
|
657
659
|
is_close = False
|
658
660
|
if meters_per_pixel:
|
659
661
|
meters_distance = pixel_distance * float(meters_per_pixel)
|
660
|
-
|
661
|
-
is_close = True
|
662
|
+
is_close = meters_distance < float(threshold_meters)
|
662
663
|
else:
|
663
|
-
|
664
|
-
|
664
|
+
is_close = pixel_distance < float(threshold_pixels_fallback)
|
665
|
+
|
666
|
+
if is_close:
|
667
|
+
pair = (id1, id2) if id1 <= id2 else (id2, id1)
|
668
|
+
current_pairs.add(pair)
|
665
669
|
|
666
|
-
|
667
|
-
|
670
|
+
# Update global unique proximity pairs
|
671
|
+
new_unique_pairs = {frozenset(p) for p in current_pairs} - self._observed_proximity_pairs
|
672
|
+
if new_unique_pairs:
|
673
|
+
self._total_proximity_count += len(new_unique_pairs)
|
674
|
+
self._observed_proximity_pairs.update(new_unique_pairs)
|
668
675
|
|
669
|
-
|
676
|
+
# Store last frame pairs
|
677
|
+
self._last_frame_proximity_pairs = current_pairs
|
670
678
|
|
671
|
-
|
672
|
-
|
673
|
-
id_j = det_j.get("track_id")
|
674
|
-
if id_i is not None and id_j is not None:
|
675
|
-
pair_key = frozenset({id_i, id_j})
|
676
|
-
if pair_key not in self._observed_proximity_pairs:
|
677
|
-
self._observed_proximity_pairs.add(pair_key)
|
678
|
-
self._total_proximity_count += 1
|
679
|
+
# Return count of unique pairs in current frame
|
680
|
+
return len(current_pairs)
|
679
681
|
|
680
|
-
|
682
|
+
def _nms_by_iou(self, detections: List[Dict[str, Any]], iou_threshold: float) -> List[Dict[str, Any]]:
|
683
|
+
"""Perform simple IoU-based NMS on a list of detections.
|
684
|
+
|
685
|
+
Each detection is a dict with keys: 'bbox' as [x1,y1,x2,y2], 'confidence' (float), and optional 'track_id'.
|
686
|
+
Keeps highest-confidence detections when overlap exceeds threshold.
|
687
|
+
"""
|
688
|
+
if not detections:
|
689
|
+
return []
|
690
|
+
# Sort by confidence descending
|
691
|
+
dets = sorted(detections, key=lambda d: float(d.get("confidence", 1.0)), reverse=True)
|
692
|
+
kept: List[Dict[str, Any]] = []
|
693
|
+
for det in dets:
|
694
|
+
should_keep = True
|
695
|
+
for kept_det in kept:
|
696
|
+
if self._compute_iou(det["bbox"], kept_det["bbox"]) >= iou_threshold:
|
697
|
+
should_keep = False
|
698
|
+
break
|
699
|
+
if should_keep:
|
700
|
+
kept.append(det)
|
701
|
+
return kept
|
681
702
|
|
682
703
|
def _get_meters_per_pixel(self, config: ProximityConfig, stream_info: Optional[Dict[str, Any]] = None) -> Optional[float]:
|
683
704
|
"""Compute meters-per-pixel scale using config and optional stream_info.
|
@@ -204,7 +204,7 @@ matrice/deploy/utils/post_processing/usecases/plaque_segmentation_img.py,sha256=
|
|
204
204
|
matrice/deploy/utils/post_processing/usecases/pothole_segmentation.py,sha256=jXTb8ZqInp5xJ-O3Zp3zQBiryFVD0-WBbhW6Kux_NDo,44905
|
205
205
|
matrice/deploy/utils/post_processing/usecases/ppe_compliance.py,sha256=G9P9j9E9nfNJInHJxmK1Lb4daFBlG5hq0aqotTLvFFE,30146
|
206
206
|
matrice/deploy/utils/post_processing/usecases/price_tag_detection.py,sha256=09Tp6MGAHh95s-NSAp-4WC9iCc20sajWApuUBAvgXiQ,39880
|
207
|
-
matrice/deploy/utils/post_processing/usecases/proximity_detection.py,sha256=
|
207
|
+
matrice/deploy/utils/post_processing/usecases/proximity_detection.py,sha256=EBpu9tR_OOPfES0lM-YzBJN4FMwxc31TRKMS4OSLg4k,86507
|
208
208
|
matrice/deploy/utils/post_processing/usecases/road_lane_detection.py,sha256=V_KxwBtAHSNkyoH8sXw-U-P3J8ToXtX3ncc69gn6Tds,31591
|
209
209
|
matrice/deploy/utils/post_processing/usecases/road_traffic_density.py,sha256=YiHQ0kKhXglagHPvygywxMqZAw8s0WharrBQqLQj2q4,40311
|
210
210
|
matrice/deploy/utils/post_processing/usecases/road_view_segmentation.py,sha256=BcBbOOg5622KuvzKrzs9cJW1wkRoIIcOab0N7BONQKQ,44986
|
@@ -243,8 +243,8 @@ matrice/deployment/camera_manager.py,sha256=e1Lc81RJP5wUWRdTgHO6tMWF9BkBdHOSVyx3
|
|
243
243
|
matrice/deployment/deployment.py,sha256=HFt151eWq6iqIAMsQvurpV2WNxW6Cx_gIUVfnVy5SWE,48093
|
244
244
|
matrice/deployment/inference_pipeline.py,sha256=6b4Mm3-qt-Zy0BeiJfFQdImOn3FzdNCY-7ET7Rp8PMk,37911
|
245
245
|
matrice/deployment/streaming_gateway_manager.py,sha256=ifYGl3g25wyU39HwhPQyI2OgF3M6oIqKMWt8RXtMxY8,21401
|
246
|
-
matrice-1.0.
|
247
|
-
matrice-1.0.
|
248
|
-
matrice-1.0.
|
249
|
-
matrice-1.0.
|
250
|
-
matrice-1.0.
|
246
|
+
matrice-1.0.99270.dist-info/licenses/LICENSE.txt,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
247
|
+
matrice-1.0.99270.dist-info/METADATA,sha256=oBNUFZl4QKsG87Nbl2m9QwrbUSzHoKLMSEKZ3l9VMQI,14624
|
248
|
+
matrice-1.0.99270.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
249
|
+
matrice-1.0.99270.dist-info/top_level.txt,sha256=P97js8ur6o5ClRqMH3Cjoab_NqbJ6sOQ3rJmVzKBvMc,8
|
250
|
+
matrice-1.0.99270.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|