matrice-analytics 0.1.70__py3-none-any.whl → 0.1.96__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_analytics/post_processing/__init__.py +8 -2
- matrice_analytics/post_processing/config.py +4 -2
- matrice_analytics/post_processing/core/base.py +1 -1
- matrice_analytics/post_processing/core/config.py +40 -3
- matrice_analytics/post_processing/face_reg/face_recognition.py +1014 -201
- matrice_analytics/post_processing/face_reg/face_recognition_client.py +171 -29
- matrice_analytics/post_processing/face_reg/people_activity_logging.py +19 -0
- matrice_analytics/post_processing/post_processor.py +4 -0
- matrice_analytics/post_processing/usecases/__init__.py +4 -1
- matrice_analytics/post_processing/usecases/advanced_customer_service.py +913 -500
- matrice_analytics/post_processing/usecases/color_detection.py +19 -18
- matrice_analytics/post_processing/usecases/customer_service.py +356 -9
- matrice_analytics/post_processing/usecases/fire_detection.py +241 -23
- matrice_analytics/post_processing/usecases/footfall.py +750 -0
- matrice_analytics/post_processing/usecases/license_plate_monitoring.py +638 -40
- matrice_analytics/post_processing/usecases/people_counting.py +66 -33
- matrice_analytics/post_processing/usecases/vehicle_monitoring.py +35 -34
- matrice_analytics/post_processing/usecases/weapon_detection.py +2 -1
- matrice_analytics/post_processing/utils/alert_instance_utils.py +1018 -0
- matrice_analytics/post_processing/utils/business_metrics_manager_utils.py +1338 -0
- matrice_analytics/post_processing/utils/incident_manager_utils.py +1754 -0
- {matrice_analytics-0.1.70.dist-info → matrice_analytics-0.1.96.dist-info}/METADATA +1 -1
- {matrice_analytics-0.1.70.dist-info → matrice_analytics-0.1.96.dist-info}/RECORD +26 -22
- {matrice_analytics-0.1.70.dist-info → matrice_analytics-0.1.96.dist-info}/WHEEL +0 -0
- {matrice_analytics-0.1.70.dist-info → matrice_analytics-0.1.96.dist-info}/licenses/LICENSE.txt +0 -0
- {matrice_analytics-0.1.70.dist-info → matrice_analytics-0.1.96.dist-info}/top_level.txt +0 -0
|
@@ -36,7 +36,7 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
36
36
|
self.category = "general"
|
|
37
37
|
self.CASE_TYPE: Optional[str] = 'people_counting'
|
|
38
38
|
self.CASE_VERSION: Optional[str] = '1.4'
|
|
39
|
-
self.target_categories = ['person', 'people','human','man','woman','male','female']
|
|
39
|
+
self.target_categories = ['person'] #['person', 'people','human','man','woman','male','female']
|
|
40
40
|
self.smoothing_tracker = None
|
|
41
41
|
self.tracker = None
|
|
42
42
|
self._total_frame_counter = 0
|
|
@@ -50,6 +50,19 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
50
50
|
self.current_incident_end_timestamp: str = "N/A"
|
|
51
51
|
self.start_timer = None
|
|
52
52
|
|
|
53
|
+
def _simple_tracker_update(self, detections: list) -> list:
|
|
54
|
+
"""
|
|
55
|
+
====== PERFORMANCE: Lightweight tracker alternative ======
|
|
56
|
+
Simple tracker using frame-local indexing.
|
|
57
|
+
Much faster than AdvancedTracker - O(n) complexity.
|
|
58
|
+
Does not persist track IDs across frames.
|
|
59
|
+
Enable via config.enable_simple_tracker = True
|
|
60
|
+
"""
|
|
61
|
+
for i, det in enumerate(detections):
|
|
62
|
+
if det.get('track_id') is None:
|
|
63
|
+
det['track_id'] = f"simple_{self._total_frame_counter}_{i}"
|
|
64
|
+
return detections
|
|
65
|
+
|
|
53
66
|
def process(self, data: Any, config: ConfigProtocol, context: Optional[ProcessingContext] = None,
|
|
54
67
|
stream_info: Optional[Dict[str, Any]] = None) -> ProcessingResult:
|
|
55
68
|
processing_start = time.time()
|
|
@@ -90,20 +103,29 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
90
103
|
# self.smoothing_tracker = BBoxSmoothingTracker(smoothing_config)
|
|
91
104
|
# processed_data = bbox_smoothing(processed_data, self.smoothing_tracker.config, self.smoothing_tracker)
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
# ====== TRACKER SELECTION (both disabled by default for max performance) ======
|
|
107
|
+
# Set config.enable_advanced_tracker=True or config.enable_simple_tracker=True to enable
|
|
108
|
+
if getattr(config, 'enable_advanced_tracker', False):
|
|
109
|
+
# Heavy O(n³) tracker - use only when tracking quality is critical
|
|
110
|
+
try:
|
|
111
|
+
from ..advanced_tracker import AdvancedTracker
|
|
112
|
+
from ..advanced_tracker.config import TrackerConfig
|
|
113
|
+
if self.tracker is None:
|
|
114
|
+
tracker_config = TrackerConfig(
|
|
115
|
+
track_high_thresh=0.4,
|
|
116
|
+
track_low_thresh=0.05,
|
|
117
|
+
new_track_thresh=0.3,
|
|
118
|
+
match_thresh=0.8)
|
|
119
|
+
self.tracker = AdvancedTracker(tracker_config)
|
|
120
|
+
self.logger.info("Initialized AdvancedTracker for People Counting")
|
|
121
|
+
processed_data = self.tracker.update(processed_data)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
self.logger.warning(f"AdvancedTracker failed: {e}")
|
|
124
|
+
elif getattr(config, 'enable_simple_tracker', False):
|
|
125
|
+
# Lightweight O(n) tracker - fast but no cross-frame persistence
|
|
126
|
+
processed_data = self._simple_tracker_update(processed_data)
|
|
127
|
+
# else: No tracking - maximum performance, just use raw detections
|
|
128
|
+
# ====== END TRACKER SELECTION ======
|
|
107
129
|
|
|
108
130
|
self._update_tracking_state(processed_data)
|
|
109
131
|
self._total_frame_counter += 1
|
|
@@ -333,20 +355,20 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
333
355
|
})
|
|
334
356
|
|
|
335
357
|
human_text_lines = []
|
|
336
|
-
human_text_lines.append(f"CURRENT FRAME @ {current_timestamp}")
|
|
358
|
+
human_text_lines.append(f"CURRENT FRAME @ {current_timestamp}:")
|
|
337
359
|
for cat, count in per_category_count.items():
|
|
338
360
|
human_text_lines.append(f"\t- People Detected: {count}")
|
|
339
361
|
human_text_lines.append("")
|
|
340
|
-
human_text_lines.append(f"TOTAL SINCE {start_timestamp}")
|
|
341
|
-
for cat, count in total_counts_dict.items():
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if alerts:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
else:
|
|
349
|
-
|
|
362
|
+
# human_text_lines.append(f"TOTAL SINCE {start_timestamp}")
|
|
363
|
+
# for cat, count in total_counts_dict.items():
|
|
364
|
+
# if count > 0:
|
|
365
|
+
# human_text_lines.append("")
|
|
366
|
+
# human_text_lines.append(f"\t- Total unique people count: {count}")
|
|
367
|
+
# if alerts:
|
|
368
|
+
# for alert in alerts:
|
|
369
|
+
# human_text_lines.append(f"Alerts: {alert.get('settings', {})} sent @ {current_timestamp}")
|
|
370
|
+
# else:
|
|
371
|
+
# human_text_lines.append("Alerts: None")
|
|
350
372
|
human_text = "\n".join(human_text_lines)
|
|
351
373
|
|
|
352
374
|
reset_settings = [{"interval_type": "daily", "reset_time": {"value": 9, "time_unit": "hour"}}]
|
|
@@ -362,6 +384,7 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
362
384
|
start_time=high_precision_start_timestamp,
|
|
363
385
|
reset_time=high_precision_reset_timestamp
|
|
364
386
|
)
|
|
387
|
+
tracking_stat['target_categories'] = self.target_categories
|
|
365
388
|
tracking_stats.append(tracking_stat)
|
|
366
389
|
return tracking_stats
|
|
367
390
|
|
|
@@ -414,14 +437,24 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
414
437
|
|
|
415
438
|
for det in detections:
|
|
416
439
|
cat = det.get("category")
|
|
417
|
-
|
|
418
|
-
if cat not in self.target_categories
|
|
440
|
+
track_id = det.get("track_id")
|
|
441
|
+
if cat not in self.target_categories:
|
|
419
442
|
continue
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
self.
|
|
443
|
+
|
|
444
|
+
# ====== PERFORMANCE: Skip heavy track merging O(n*m) ======
|
|
445
|
+
# To enable track merging, uncomment below and comment the simple counting section
|
|
446
|
+
# bbox = det.get("bounding_box", det.get("bbox"))
|
|
447
|
+
# canonical_id = self._merge_or_register_track(track_id, bbox)
|
|
448
|
+
# det["track_id"] = canonical_id
|
|
449
|
+
# self._per_category_total_track_ids.setdefault(cat, set()).add(canonical_id)
|
|
450
|
+
# self._current_frame_track_ids[cat].add(canonical_id)
|
|
451
|
+
# ====== END HEAVY TRACK MERGING ======
|
|
452
|
+
|
|
453
|
+
# ====== SIMPLE COUNTING (default - no track merging overhead) ======
|
|
454
|
+
if track_id is not None:
|
|
455
|
+
self._per_category_total_track_ids.setdefault(cat, set()).add(track_id)
|
|
456
|
+
self._current_frame_track_ids[cat].add(track_id)
|
|
457
|
+
# ====== END SIMPLE COUNTING ======
|
|
425
458
|
|
|
426
459
|
def get_total_counts(self):
|
|
427
460
|
return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
|
|
@@ -633,40 +633,40 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
633
633
|
human_text_lines.append(f"\t\t- {cat}: {count}")
|
|
634
634
|
|
|
635
635
|
human_text_lines.append("")
|
|
636
|
-
human_text_lines.append(f"TOTAL SINCE @ {start_timestamp}:")
|
|
637
|
-
|
|
638
|
-
# Display total counts - zone-wise or category-wise
|
|
639
|
-
if zone_analysis:
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
else:
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
# Display alerts
|
|
663
|
-
if alerts:
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
else:
|
|
668
|
-
|
|
669
|
-
|
|
636
|
+
# human_text_lines.append(f"TOTAL SINCE @ {start_timestamp}:")
|
|
637
|
+
|
|
638
|
+
# # Display total counts - zone-wise or category-wise
|
|
639
|
+
# if zone_analysis:
|
|
640
|
+
# human_text_lines.append("\t- Total Vehicles by Zone:")
|
|
641
|
+
# for zone_name, zone_data in zone_analysis.items():
|
|
642
|
+
# total_count = 0
|
|
643
|
+
# if isinstance(zone_data, dict):
|
|
644
|
+
# # Prefer the numeric cumulative total if available
|
|
645
|
+
# if "total_count" in zone_data and isinstance(zone_data.get("total_count"), (int, float)):
|
|
646
|
+
# total_count = zone_data.get("total_count", 0)
|
|
647
|
+
# # Fallback: compute from list of total_track_ids if present
|
|
648
|
+
# elif "total_track_ids" in zone_data and isinstance(zone_data.get("total_track_ids"), list):
|
|
649
|
+
# total_count = len(zone_data.get("total_track_ids", []))
|
|
650
|
+
# else:
|
|
651
|
+
# # Last resort: try to sum numeric values present
|
|
652
|
+
# counts_dict = zone_data if isinstance(zone_data, dict) else {}
|
|
653
|
+
# total_count = sum(v for v in counts_dict.values() if isinstance(v, (int, float)))
|
|
654
|
+
# human_text_lines.append(f"\t\t- {zone_name}: {int(total_count)}")
|
|
655
|
+
# else:
|
|
656
|
+
# if total_counts_dict:
|
|
657
|
+
# human_text_lines.append("\t- Total Unique Vehicles:")
|
|
658
|
+
# for cat, count in total_counts_dict.items():
|
|
659
|
+
# if count > 0:
|
|
660
|
+
# human_text_lines.append(f"\t\t- {cat}: {count}")
|
|
661
|
+
|
|
662
|
+
# # Display alerts
|
|
663
|
+
# if alerts:
|
|
664
|
+
# human_text_lines.append("")
|
|
665
|
+
# for alert in alerts:
|
|
666
|
+
# human_text_lines.append(f"Alerts: {alert.get('settings', {})} sent @ {current_timestamp}")
|
|
667
|
+
# else:
|
|
668
|
+
# human_text_lines.append("")
|
|
669
|
+
# human_text_lines.append("Alerts: None")
|
|
670
670
|
|
|
671
671
|
human_text = "\n".join(human_text_lines)
|
|
672
672
|
|
|
@@ -683,6 +683,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
683
683
|
start_time=high_precision_start_timestamp,
|
|
684
684
|
reset_time=high_precision_reset_timestamp
|
|
685
685
|
)
|
|
686
|
+
tracking_stat['target_categories'] = self.target_categories
|
|
686
687
|
tracking_stats.append(tracking_stat)
|
|
687
688
|
return tracking_stats
|
|
688
689
|
|
|
@@ -317,7 +317,7 @@ class WeaponDetectionUseCase(BaseProcessor):
|
|
|
317
317
|
total_counts = [{"category": cat, "count": count} for cat, count in total_counts_dict.items() if count > 0]
|
|
318
318
|
|
|
319
319
|
# Build current_counts
|
|
320
|
-
current_counts = [{"category":
|
|
320
|
+
current_counts = [{"category": 'Weapon', "count": count} for cat, count in per_category_count.items() if count > 0]
|
|
321
321
|
|
|
322
322
|
# Prepare detections
|
|
323
323
|
detections = []
|
|
@@ -377,6 +377,7 @@ class WeaponDetectionUseCase(BaseProcessor):
|
|
|
377
377
|
start_time=high_precision_start_timestamp,
|
|
378
378
|
reset_time=high_precision_reset_timestamp
|
|
379
379
|
)
|
|
380
|
+
tracking_stat['target_categories'] = ['Weapon']
|
|
380
381
|
tracking_stats.append(tracking_stat)
|
|
381
382
|
return tracking_stats
|
|
382
383
|
|