matrice-analytics 0.1.60__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.
Files changed (196) hide show
  1. matrice_analytics/__init__.py +28 -0
  2. matrice_analytics/boundary_drawing_internal/README.md +305 -0
  3. matrice_analytics/boundary_drawing_internal/__init__.py +45 -0
  4. matrice_analytics/boundary_drawing_internal/boundary_drawing_internal.py +1207 -0
  5. matrice_analytics/boundary_drawing_internal/boundary_drawing_tool.py +429 -0
  6. matrice_analytics/boundary_drawing_internal/boundary_tool_template.html +1036 -0
  7. matrice_analytics/boundary_drawing_internal/data/.gitignore +12 -0
  8. matrice_analytics/boundary_drawing_internal/example_usage.py +206 -0
  9. matrice_analytics/boundary_drawing_internal/usage/README.md +110 -0
  10. matrice_analytics/boundary_drawing_internal/usage/boundary_drawer_launcher.py +102 -0
  11. matrice_analytics/boundary_drawing_internal/usage/simple_boundary_launcher.py +107 -0
  12. matrice_analytics/post_processing/README.md +455 -0
  13. matrice_analytics/post_processing/__init__.py +732 -0
  14. matrice_analytics/post_processing/advanced_tracker/README.md +650 -0
  15. matrice_analytics/post_processing/advanced_tracker/__init__.py +17 -0
  16. matrice_analytics/post_processing/advanced_tracker/base.py +99 -0
  17. matrice_analytics/post_processing/advanced_tracker/config.py +77 -0
  18. matrice_analytics/post_processing/advanced_tracker/kalman_filter.py +370 -0
  19. matrice_analytics/post_processing/advanced_tracker/matching.py +195 -0
  20. matrice_analytics/post_processing/advanced_tracker/strack.py +230 -0
  21. matrice_analytics/post_processing/advanced_tracker/tracker.py +367 -0
  22. matrice_analytics/post_processing/config.py +146 -0
  23. matrice_analytics/post_processing/core/__init__.py +63 -0
  24. matrice_analytics/post_processing/core/base.py +704 -0
  25. matrice_analytics/post_processing/core/config.py +3291 -0
  26. matrice_analytics/post_processing/core/config_utils.py +925 -0
  27. matrice_analytics/post_processing/face_reg/__init__.py +43 -0
  28. matrice_analytics/post_processing/face_reg/compare_similarity.py +556 -0
  29. matrice_analytics/post_processing/face_reg/embedding_manager.py +950 -0
  30. matrice_analytics/post_processing/face_reg/face_recognition.py +2234 -0
  31. matrice_analytics/post_processing/face_reg/face_recognition_client.py +606 -0
  32. matrice_analytics/post_processing/face_reg/people_activity_logging.py +321 -0
  33. matrice_analytics/post_processing/ocr/__init__.py +0 -0
  34. matrice_analytics/post_processing/ocr/easyocr_extractor.py +250 -0
  35. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/__init__.py +9 -0
  36. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/__init__.py +4 -0
  37. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/cli.py +33 -0
  38. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/dataset_stats.py +139 -0
  39. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/export.py +398 -0
  40. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/train.py +447 -0
  41. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/utils.py +129 -0
  42. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/valid.py +93 -0
  43. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/validate_dataset.py +240 -0
  44. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_augmentation.py +176 -0
  45. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_predictions.py +96 -0
  46. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/__init__.py +3 -0
  47. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/process.py +246 -0
  48. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/types.py +60 -0
  49. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/utils.py +87 -0
  50. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/__init__.py +3 -0
  51. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/config.py +82 -0
  52. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/hub.py +141 -0
  53. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/plate_recognizer.py +323 -0
  54. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/py.typed +0 -0
  55. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/__init__.py +0 -0
  56. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/__init__.py +0 -0
  57. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/augmentation.py +101 -0
  58. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/dataset.py +97 -0
  59. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/__init__.py +0 -0
  60. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/config.py +114 -0
  61. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/layers.py +553 -0
  62. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/loss.py +55 -0
  63. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/metric.py +86 -0
  64. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_builders.py +95 -0
  65. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_schema.py +395 -0
  66. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/__init__.py +0 -0
  67. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/backend_utils.py +38 -0
  68. matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/utils.py +214 -0
  69. matrice_analytics/post_processing/ocr/postprocessing.py +270 -0
  70. matrice_analytics/post_processing/ocr/preprocessing.py +52 -0
  71. matrice_analytics/post_processing/post_processor.py +1175 -0
  72. matrice_analytics/post_processing/test_cases/__init__.py +1 -0
  73. matrice_analytics/post_processing/test_cases/run_tests.py +143 -0
  74. matrice_analytics/post_processing/test_cases/test_advanced_customer_service.py +841 -0
  75. matrice_analytics/post_processing/test_cases/test_basic_counting_tracking.py +523 -0
  76. matrice_analytics/post_processing/test_cases/test_comprehensive.py +531 -0
  77. matrice_analytics/post_processing/test_cases/test_config.py +852 -0
  78. matrice_analytics/post_processing/test_cases/test_customer_service.py +585 -0
  79. matrice_analytics/post_processing/test_cases/test_data_generators.py +583 -0
  80. matrice_analytics/post_processing/test_cases/test_people_counting.py +510 -0
  81. matrice_analytics/post_processing/test_cases/test_processor.py +524 -0
  82. matrice_analytics/post_processing/test_cases/test_usecases.py +165 -0
  83. matrice_analytics/post_processing/test_cases/test_utilities.py +356 -0
  84. matrice_analytics/post_processing/test_cases/test_utils.py +743 -0
  85. matrice_analytics/post_processing/usecases/Histopathological_Cancer_Detection_img.py +604 -0
  86. matrice_analytics/post_processing/usecases/__init__.py +267 -0
  87. matrice_analytics/post_processing/usecases/abandoned_object_detection.py +797 -0
  88. matrice_analytics/post_processing/usecases/advanced_customer_service.py +1601 -0
  89. matrice_analytics/post_processing/usecases/age_detection.py +842 -0
  90. matrice_analytics/post_processing/usecases/age_gender_detection.py +1085 -0
  91. matrice_analytics/post_processing/usecases/anti_spoofing_detection.py +656 -0
  92. matrice_analytics/post_processing/usecases/assembly_line_detection.py +841 -0
  93. matrice_analytics/post_processing/usecases/banana_defect_detection.py +624 -0
  94. matrice_analytics/post_processing/usecases/basic_counting_tracking.py +667 -0
  95. matrice_analytics/post_processing/usecases/blood_cancer_detection_img.py +881 -0
  96. matrice_analytics/post_processing/usecases/car_damage_detection.py +834 -0
  97. matrice_analytics/post_processing/usecases/car_part_segmentation.py +946 -0
  98. matrice_analytics/post_processing/usecases/car_service.py +1601 -0
  99. matrice_analytics/post_processing/usecases/cardiomegaly_classification.py +864 -0
  100. matrice_analytics/post_processing/usecases/cell_microscopy_segmentation.py +897 -0
  101. matrice_analytics/post_processing/usecases/chicken_pose_detection.py +648 -0
  102. matrice_analytics/post_processing/usecases/child_monitoring.py +814 -0
  103. matrice_analytics/post_processing/usecases/color/clip.py +660 -0
  104. matrice_analytics/post_processing/usecases/color/clip_processor/merges.txt +48895 -0
  105. matrice_analytics/post_processing/usecases/color/clip_processor/preprocessor_config.json +28 -0
  106. matrice_analytics/post_processing/usecases/color/clip_processor/special_tokens_map.json +30 -0
  107. matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer.json +245079 -0
  108. matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer_config.json +32 -0
  109. matrice_analytics/post_processing/usecases/color/clip_processor/vocab.json +1 -0
  110. matrice_analytics/post_processing/usecases/color/color_map_utils.py +70 -0
  111. matrice_analytics/post_processing/usecases/color/color_mapper.py +468 -0
  112. matrice_analytics/post_processing/usecases/color_detection.py +1936 -0
  113. matrice_analytics/post_processing/usecases/color_map_utils.py +70 -0
  114. matrice_analytics/post_processing/usecases/concrete_crack_detection.py +827 -0
  115. matrice_analytics/post_processing/usecases/crop_weed_detection.py +781 -0
  116. matrice_analytics/post_processing/usecases/customer_service.py +1008 -0
  117. matrice_analytics/post_processing/usecases/defect_detection_products.py +936 -0
  118. matrice_analytics/post_processing/usecases/distracted_driver_detection.py +822 -0
  119. matrice_analytics/post_processing/usecases/drone_traffic_monitoring.py +585 -0
  120. matrice_analytics/post_processing/usecases/drowsy_driver_detection.py +829 -0
  121. matrice_analytics/post_processing/usecases/dwell_detection.py +829 -0
  122. matrice_analytics/post_processing/usecases/emergency_vehicle_detection.py +827 -0
  123. matrice_analytics/post_processing/usecases/face_emotion.py +813 -0
  124. matrice_analytics/post_processing/usecases/face_recognition.py +827 -0
  125. matrice_analytics/post_processing/usecases/fashion_detection.py +835 -0
  126. matrice_analytics/post_processing/usecases/field_mapping.py +902 -0
  127. matrice_analytics/post_processing/usecases/fire_detection.py +1146 -0
  128. matrice_analytics/post_processing/usecases/flare_analysis.py +836 -0
  129. matrice_analytics/post_processing/usecases/flower_segmentation.py +1006 -0
  130. matrice_analytics/post_processing/usecases/gas_leak_detection.py +837 -0
  131. matrice_analytics/post_processing/usecases/gender_detection.py +832 -0
  132. matrice_analytics/post_processing/usecases/human_activity_recognition.py +871 -0
  133. matrice_analytics/post_processing/usecases/intrusion_detection.py +1672 -0
  134. matrice_analytics/post_processing/usecases/leaf.py +821 -0
  135. matrice_analytics/post_processing/usecases/leaf_disease.py +840 -0
  136. matrice_analytics/post_processing/usecases/leak_detection.py +837 -0
  137. matrice_analytics/post_processing/usecases/license_plate_detection.py +1188 -0
  138. matrice_analytics/post_processing/usecases/license_plate_monitoring.py +1781 -0
  139. matrice_analytics/post_processing/usecases/litter_monitoring.py +717 -0
  140. matrice_analytics/post_processing/usecases/mask_detection.py +869 -0
  141. matrice_analytics/post_processing/usecases/natural_disaster.py +907 -0
  142. matrice_analytics/post_processing/usecases/parking.py +787 -0
  143. matrice_analytics/post_processing/usecases/parking_space_detection.py +822 -0
  144. matrice_analytics/post_processing/usecases/pcb_defect_detection.py +888 -0
  145. matrice_analytics/post_processing/usecases/pedestrian_detection.py +808 -0
  146. matrice_analytics/post_processing/usecases/people_counting.py +706 -0
  147. matrice_analytics/post_processing/usecases/people_counting_bckp.py +1683 -0
  148. matrice_analytics/post_processing/usecases/people_tracking.py +1842 -0
  149. matrice_analytics/post_processing/usecases/pipeline_detection.py +605 -0
  150. matrice_analytics/post_processing/usecases/plaque_segmentation_img.py +874 -0
  151. matrice_analytics/post_processing/usecases/pothole_segmentation.py +915 -0
  152. matrice_analytics/post_processing/usecases/ppe_compliance.py +645 -0
  153. matrice_analytics/post_processing/usecases/price_tag_detection.py +822 -0
  154. matrice_analytics/post_processing/usecases/proximity_detection.py +1901 -0
  155. matrice_analytics/post_processing/usecases/road_lane_detection.py +623 -0
  156. matrice_analytics/post_processing/usecases/road_traffic_density.py +832 -0
  157. matrice_analytics/post_processing/usecases/road_view_segmentation.py +915 -0
  158. matrice_analytics/post_processing/usecases/shelf_inventory_detection.py +583 -0
  159. matrice_analytics/post_processing/usecases/shoplifting_detection.py +822 -0
  160. matrice_analytics/post_processing/usecases/shopping_cart_analysis.py +899 -0
  161. matrice_analytics/post_processing/usecases/skin_cancer_classification_img.py +864 -0
  162. matrice_analytics/post_processing/usecases/smoker_detection.py +833 -0
  163. matrice_analytics/post_processing/usecases/solar_panel.py +810 -0
  164. matrice_analytics/post_processing/usecases/suspicious_activity_detection.py +1030 -0
  165. matrice_analytics/post_processing/usecases/template_usecase.py +380 -0
  166. matrice_analytics/post_processing/usecases/theft_detection.py +648 -0
  167. matrice_analytics/post_processing/usecases/traffic_sign_monitoring.py +724 -0
  168. matrice_analytics/post_processing/usecases/underground_pipeline_defect_detection.py +775 -0
  169. matrice_analytics/post_processing/usecases/underwater_pollution_detection.py +842 -0
  170. matrice_analytics/post_processing/usecases/vehicle_monitoring.py +1029 -0
  171. matrice_analytics/post_processing/usecases/warehouse_object_segmentation.py +899 -0
  172. matrice_analytics/post_processing/usecases/waterbody_segmentation.py +923 -0
  173. matrice_analytics/post_processing/usecases/weapon_detection.py +771 -0
  174. matrice_analytics/post_processing/usecases/weld_defect_detection.py +615 -0
  175. matrice_analytics/post_processing/usecases/wildlife_monitoring.py +898 -0
  176. matrice_analytics/post_processing/usecases/windmill_maintenance.py +834 -0
  177. matrice_analytics/post_processing/usecases/wound_segmentation.py +856 -0
  178. matrice_analytics/post_processing/utils/__init__.py +150 -0
  179. matrice_analytics/post_processing/utils/advanced_counting_utils.py +400 -0
  180. matrice_analytics/post_processing/utils/advanced_helper_utils.py +317 -0
  181. matrice_analytics/post_processing/utils/advanced_tracking_utils.py +461 -0
  182. matrice_analytics/post_processing/utils/alerting_utils.py +213 -0
  183. matrice_analytics/post_processing/utils/category_mapping_utils.py +94 -0
  184. matrice_analytics/post_processing/utils/color_utils.py +592 -0
  185. matrice_analytics/post_processing/utils/counting_utils.py +182 -0
  186. matrice_analytics/post_processing/utils/filter_utils.py +261 -0
  187. matrice_analytics/post_processing/utils/format_utils.py +293 -0
  188. matrice_analytics/post_processing/utils/geometry_utils.py +300 -0
  189. matrice_analytics/post_processing/utils/smoothing_utils.py +358 -0
  190. matrice_analytics/post_processing/utils/tracking_utils.py +234 -0
  191. matrice_analytics/py.typed +0 -0
  192. matrice_analytics-0.1.60.dist-info/METADATA +481 -0
  193. matrice_analytics-0.1.60.dist-info/RECORD +196 -0
  194. matrice_analytics-0.1.60.dist-info/WHEEL +5 -0
  195. matrice_analytics-0.1.60.dist-info/licenses/LICENSE.txt +21 -0
  196. matrice_analytics-0.1.60.dist-info/top_level.txt +1 -0
@@ -0,0 +1,367 @@
1
+ """
2
+ Advanced tracker implementation.
3
+
4
+ This module provides the AdvancedTracker class that implements BYTETracker-like
5
+ functionality for object tracking with support for various input formats.
6
+ """
7
+
8
+ from typing import Any, List, Optional, Tuple, Union, Dict
9
+ import numpy as np
10
+ import logging
11
+
12
+ from .base import BaseTrack, TrackState
13
+ from .config import TrackerConfig
14
+ from .kalman_filter import KalmanFilterXYAH
15
+ from .strack import STrack
16
+ from .matching import linear_assignment, iou_distance, fuse_score
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class AdvancedTracker:
22
+ """
23
+ AdvancedTracker: A tracking algorithm similar to BYTETracker for object detection and tracking.
24
+
25
+ This class encapsulates the functionality for initializing, updating, and managing the tracks for detected objects in a
26
+ video sequence. It maintains the state of tracked, lost, and removed tracks over frames, utilizes Kalman filtering for
27
+ predicting the new object locations, and performs data association.
28
+
29
+ Attributes:
30
+ tracked_stracks (List[STrack]): List of successfully activated tracks.
31
+ lost_stracks (List[STrack]): List of lost tracks.
32
+ removed_stracks (List[STrack]): List of removed tracks.
33
+ frame_id (int): The current frame ID.
34
+ config (TrackerConfig): Tracker configuration.
35
+ max_time_lost (int): The maximum frames for a track to be considered as 'lost'.
36
+ kalman_filter (KalmanFilterXYAH): Kalman Filter object.
37
+ """
38
+
39
+ def __init__(self, config: TrackerConfig):
40
+ """
41
+ Initialize an AdvancedTracker instance for object tracking.
42
+
43
+ Args:
44
+ config (TrackerConfig): Tracker configuration object.
45
+ """
46
+ self.tracked_stracks = [] # type: List[STrack]
47
+ self.lost_stracks = [] # type: List[STrack]
48
+ self.removed_stracks = [] # type: List[STrack]
49
+
50
+ self.frame_id = 0
51
+ self.config = config
52
+ self.max_time_lost = config.max_time_lost
53
+ self.kalman_filter = self.get_kalmanfilter()
54
+ self.reset_id()
55
+
56
+ def update(self, detections: Union[List[Dict], Dict[str, List[Dict]]],
57
+ img: Optional[np.ndarray] = None) -> Union[List[Dict], Dict[str, List[Dict]]]:
58
+ """
59
+ Update the tracker with new detections and return the current list of tracked objects.
60
+
61
+ Args:
62
+ detections: Detection results in various formats:
63
+ - List[Dict]: Single frame detections
64
+ - Dict[str, List[Dict]]: Multi-frame detections with frame keys
65
+ img: Optional image for motion compensation
66
+
67
+ Returns:
68
+ Tracking results in the same format as input
69
+ """
70
+ self.frame_id += 1
71
+
72
+ # Handle different input formats
73
+ if isinstance(detections, dict):
74
+ # Multi-frame format
75
+ return self._update_multi_frame(detections, img)
76
+ else:
77
+ # Single frame format
78
+ return self._update_single_frame(detections, img)
79
+
80
+ def _update_single_frame(self, detections: List[Dict], img: Optional[np.ndarray] = None) -> List[Dict]:
81
+ """Update tracker with single frame detections."""
82
+ # Convert detections to STrack format
83
+ stracks = self._convert_detections_to_stracks(detections)
84
+
85
+ # Perform tracking update
86
+ tracked_objects = self._perform_tracking_update(stracks, img)
87
+
88
+ # Convert back to detection format
89
+ return self._convert_stracks_to_detections(tracked_objects)
90
+
91
+ def _update_multi_frame(self, detections: Dict[str, List[Dict]],
92
+ img: Optional[np.ndarray] = None) -> Dict[str, List[Dict]]:
93
+ """Update tracker with multi-frame detections."""
94
+ results = {}
95
+
96
+ for frame_key, frame_detections in detections.items():
97
+ # Convert frame detections to STrack format
98
+ stracks = self._convert_detections_to_stracks(frame_detections)
99
+
100
+ # Perform tracking update
101
+ tracked_objects = self._perform_tracking_update(stracks, img)
102
+
103
+ # Convert back to detection format
104
+ results[frame_key] = self._convert_stracks_to_detections(tracked_objects)
105
+
106
+ return results
107
+
108
+ def _convert_detections_to_stracks(self, detections: List[Dict]) -> List[STrack]:
109
+ """Convert detection format to STrack objects."""
110
+ stracks = []
111
+
112
+ for i, det in enumerate(detections):
113
+ # Extract bounding box
114
+ bbox = det.get('bounding_box', {})
115
+ if 'x' in bbox and 'y' in bbox and 'width' in bbox and 'height' in bbox:
116
+ # Center format
117
+ x, y, w, h = bbox['x'], bbox['y'], bbox['width'], bbox['height']
118
+ elif 'xmin' in bbox and 'ymin' in bbox and 'xmax' in bbox and 'ymax' in bbox:
119
+ # Corner format
120
+ x = (bbox['xmin'] + bbox['xmax']) / 2
121
+ y = (bbox['ymin'] + bbox['ymax']) / 2
122
+ w = bbox['xmax'] - bbox['xmin']
123
+ h = bbox['ymax'] - bbox['ymin']
124
+ else:
125
+ # Try to extract from any format
126
+ values = list(bbox.values())
127
+ if len(values) >= 4:
128
+ x, y, w, h = values[0], values[1], values[2], values[3]
129
+ else:
130
+ continue
131
+
132
+ # Extract other properties
133
+ score = det.get('confidence', 0.0)
134
+ category = det.get('category', 'unknown')
135
+
136
+ # Create STrack
137
+ xywh = [x, y, w, h, i] # Add index as last element
138
+ strack = STrack(xywh, score, category)
139
+
140
+ # CRITICAL FIX: Store the original detection data to preserve all fields
141
+ # This ensures face recognition fields (embedding, landmarks, etc.) are preserved
142
+ strack.original_detection = det.copy()
143
+
144
+ stracks.append(strack)
145
+
146
+ return stracks
147
+
148
+ def _convert_stracks_to_detections(self, stracks: List[STrack]) -> List[Dict]:
149
+ """Convert STrack objects back to detection format."""
150
+ detections = []
151
+
152
+ for strack in stracks:
153
+ if strack.is_activated:
154
+ # Get bounding box in xyxy format
155
+ xyxy = strack.xyxy
156
+
157
+ # CRITICAL FIX: Start with original detection data to preserve all fields
158
+ if hasattr(strack, 'original_detection') and strack.original_detection:
159
+ # Start with the original detection to preserve all face recognition fields
160
+ detection = strack.original_detection.copy()
161
+
162
+ # Update with tracking-specific fields
163
+ detection['bounding_box'] = {
164
+ 'xmin': float(xyxy[0]),
165
+ 'ymin': float(xyxy[1]),
166
+ 'xmax': float(xyxy[2]),
167
+ 'ymax': float(xyxy[3])
168
+ }
169
+ detection['confidence'] = float(strack.score)
170
+ detection['category'] = strack.cls
171
+ detection['track_id'] = int(strack.track_id)
172
+ detection['frame_id'] = int(strack.frame_id)
173
+ else:
174
+ # Fallback to minimal detection if original data not available
175
+ detection = {
176
+ 'bounding_box': {
177
+ 'xmin': float(xyxy[0]),
178
+ 'ymin': float(xyxy[1]),
179
+ 'xmax': float(xyxy[2]),
180
+ 'ymax': float(xyxy[3])
181
+ },
182
+ 'confidence': float(strack.score),
183
+ 'category': strack.cls,
184
+ 'track_id': int(strack.track_id),
185
+ 'frame_id': int(strack.frame_id)
186
+ }
187
+
188
+ detections.append(detection)
189
+
190
+ return detections
191
+
192
+ def _perform_tracking_update(self, detections: List[STrack],
193
+ img: Optional[np.ndarray] = None) -> List[STrack]:
194
+ """Perform the core tracking update algorithm."""
195
+ activated_stracks = []
196
+ refind_stracks = []
197
+ lost_stracks = []
198
+ removed_stracks = []
199
+
200
+ # Separate high and low confidence detections
201
+ scores = np.array([det.score for det in detections])
202
+ remain_inds = scores >= self.config.track_high_thresh
203
+ inds_low = scores > self.config.track_low_thresh
204
+ inds_high = scores < self.config.track_high_thresh
205
+
206
+ inds_second = inds_low & inds_high
207
+ dets_second = [detections[i] for i in range(len(detections)) if inds_second[i]]
208
+ dets = [detections[i] for i in range(len(detections)) if remain_inds[i]]
209
+ scores_keep = scores[remain_inds]
210
+ scores_second = scores[inds_second]
211
+
212
+ # Step 1: First association, with high score detection boxes
213
+ unconfirmed = []
214
+ tracked_stracks = []
215
+ for track in self.tracked_stracks:
216
+ if not track.is_activated:
217
+ unconfirmed.append(track)
218
+ else:
219
+ tracked_stracks.append(track)
220
+
221
+ # Predict the current location with KF
222
+ strack_pool = self.joint_stracks(tracked_stracks, self.lost_stracks)
223
+ self.multi_predict(strack_pool)
224
+
225
+ # Calculate distances and perform matching
226
+ dists = self.get_dists(strack_pool, dets)
227
+ matches, u_track, u_detection = linear_assignment(dists, thresh=self.config.match_thresh)
228
+
229
+ for itracked, idet in matches:
230
+ track = strack_pool[itracked]
231
+ det = dets[idet]
232
+ if track.state == TrackState.Tracked:
233
+ track.update(det, self.frame_id)
234
+ activated_stracks.append(track)
235
+ else:
236
+ track.re_activate(det, self.frame_id, new_id=False)
237
+ refind_stracks.append(track)
238
+
239
+ # Step 2: Second association, with low score detection boxes
240
+ r_tracked_stracks = [strack_pool[i] for i in u_track if strack_pool[i].state == TrackState.Tracked]
241
+ dists = iou_distance(r_tracked_stracks, dets_second)
242
+ matches, u_track, u_detection_second = linear_assignment(dists, thresh=0.5)
243
+
244
+ for itracked, idet in matches:
245
+ track = r_tracked_stracks[itracked]
246
+ det = dets_second[idet]
247
+ if track.state == TrackState.Tracked:
248
+ track.update(det, self.frame_id)
249
+ activated_stracks.append(track)
250
+ else:
251
+ track.re_activate(det, self.frame_id, new_id=False)
252
+ refind_stracks.append(track)
253
+
254
+ for it in u_track:
255
+ track = r_tracked_stracks[it]
256
+ if track.state != TrackState.Lost:
257
+ track.mark_lost()
258
+ lost_stracks.append(track)
259
+
260
+ # Step 3: Deal with unconfirmed tracks
261
+ detections = [dets[i] for i in u_detection]
262
+ dists = self.get_dists(unconfirmed, detections)
263
+ matches, u_unconfirmed, u_detection = linear_assignment(dists, thresh=0.7)
264
+
265
+ for itracked, idet in matches:
266
+ unconfirmed[itracked].update(detections[idet], self.frame_id)
267
+ activated_stracks.append(unconfirmed[itracked])
268
+
269
+ for it in u_unconfirmed:
270
+ track = unconfirmed[it]
271
+ track.mark_removed()
272
+ removed_stracks.append(track)
273
+
274
+ # Step 4: Init new stracks
275
+ for inew in u_detection:
276
+ track = detections[inew]
277
+ if track.score < self.config.new_track_thresh:
278
+ continue
279
+ track.activate(self.kalman_filter, self.frame_id)
280
+ activated_stracks.append(track)
281
+
282
+ # Step 5: Update state
283
+ for track in self.lost_stracks:
284
+ if self.frame_id - track.end_frame > self.max_time_lost:
285
+ track.mark_removed()
286
+ removed_stracks.append(track)
287
+
288
+ self.tracked_stracks = [t for t in self.tracked_stracks if t.state == TrackState.Tracked]
289
+ self.tracked_stracks = self.joint_stracks(self.tracked_stracks, activated_stracks)
290
+ self.tracked_stracks = self.joint_stracks(self.tracked_stracks, refind_stracks)
291
+ self.lost_stracks = self.sub_stracks(self.lost_stracks, self.tracked_stracks)
292
+ self.lost_stracks.extend(lost_stracks)
293
+ self.lost_stracks = self.sub_stracks(self.lost_stracks, self.removed_stracks)
294
+ self.tracked_stracks, self.lost_stracks = self.remove_duplicate_stracks(self.tracked_stracks, self.lost_stracks)
295
+ self.removed_stracks.extend(removed_stracks)
296
+
297
+ if len(self.removed_stracks) > 1000:
298
+ self.removed_stracks = self.removed_stracks[-999:]
299
+
300
+ return [x for x in self.tracked_stracks if x.is_activated]
301
+
302
+ def get_kalmanfilter(self) -> KalmanFilterXYAH:
303
+ """Return a Kalman filter object for tracking bounding boxes using KalmanFilterXYAH."""
304
+ return KalmanFilterXYAH()
305
+
306
+ def get_dists(self, tracks: List[STrack], detections: List[STrack]) -> np.ndarray:
307
+ """Calculate the distance between tracks and detections using IoU and optionally fuse scores."""
308
+ dists = iou_distance(tracks, detections)
309
+ if self.config.fuse_score:
310
+ dists = fuse_score(dists, detections)
311
+ return dists
312
+
313
+ def multi_predict(self, tracks: List[STrack]):
314
+ """Predict the next states for multiple tracks using Kalman filter."""
315
+ STrack.multi_predict(tracks)
316
+
317
+ @staticmethod
318
+ def reset_id():
319
+ """Reset the ID counter for STrack instances to ensure unique track IDs across tracking sessions."""
320
+ STrack.reset_id()
321
+
322
+ def reset(self):
323
+ """Reset the tracker by clearing all tracked, lost, and removed tracks and reinitializing the Kalman filter."""
324
+ self.tracked_stracks = []
325
+ self.lost_stracks = []
326
+ self.removed_stracks = []
327
+ self.frame_id = 0
328
+ self.kalman_filter = self.get_kalmanfilter()
329
+ self.reset_id()
330
+
331
+ @staticmethod
332
+ def joint_stracks(tlista: List[STrack], tlistb: List[STrack]) -> List[STrack]:
333
+ """Combine two lists of STrack objects into a single list, ensuring no duplicates based on track IDs."""
334
+ exists = {}
335
+ res = []
336
+ for t in tlista:
337
+ exists[t.track_id] = 1
338
+ res.append(t)
339
+ for t in tlistb:
340
+ tid = t.track_id
341
+ if not exists.get(tid, 0):
342
+ exists[tid] = 1
343
+ res.append(t)
344
+ return res
345
+
346
+ @staticmethod
347
+ def sub_stracks(tlista: List[STrack], tlistb: List[STrack]) -> List[STrack]:
348
+ """Filter out the stracks present in the second list from the first list."""
349
+ track_ids_b = {t.track_id for t in tlistb}
350
+ return [t for t in tlista if t.track_id not in track_ids_b]
351
+
352
+ @staticmethod
353
+ def remove_duplicate_stracks(stracksa: List[STrack], stracksb: List[STrack]) -> Tuple[List[STrack], List[STrack]]:
354
+ """Remove duplicate stracks from two lists based on Intersection over Union (IoU) distance."""
355
+ pdist = iou_distance(stracksa, stracksb)
356
+ pairs = np.where(pdist < 0.15)
357
+ dupa, dupb = [], []
358
+ for p, q in zip(*pairs):
359
+ timep = stracksa[p].frame_id - stracksa[p].start_frame
360
+ timeq = stracksb[q].frame_id - stracksb[q].start_frame
361
+ if timep > timeq:
362
+ dupb.append(q)
363
+ else:
364
+ dupa.append(p)
365
+ resa = [t for i, t in enumerate(stracksa) if i not in dupa]
366
+ resb = [t for i, t in enumerate(stracksb) if i not in dupb]
367
+ return resa, resb
@@ -0,0 +1,146 @@
1
+ APP_NAME_TO_USECASE = {
2
+ "people_counting": "people_counting",
3
+ "drone_traffic_monitoring": "drone_traffic_monitoring",
4
+ "intrusion_detection": "intrusion_detection",
5
+ "proximity_detection": "proximity_detection",
6
+ "mask_detection": "mask_detection",
7
+ "pipeline_detection": "pipeline_detection",
8
+ "vehicle_monitoring": "vehicle_monitoring",
9
+ "Vehicle Type Monitoring": "vehicle_monitoring",
10
+ "weapon_detection": "weapon_detection",
11
+ "traffic_sign_monitoring": "traffic_sign_monitoring",
12
+ "flare_analysis": "flare_analysis",
13
+ "ppe_compliance": "ppe_compliance",
14
+ "advanced_customer_service": "advanced_customer_service",
15
+ "assembly_line_detection": "assembly_line_detection",
16
+ "crop_weed_detection" : "crop_weed_detection",
17
+ "emergency_vehicle_detection": "emergency_vehicle_detection",
18
+ "fashion_detection": "fashion_detection",
19
+ "gender_detection": "gender_detection",
20
+ "price_tag_detection": "price_tag_detection",
21
+ "windmill_maintenance": "windmill_maintenance",
22
+ "underwater_pollution_detection": "underwater_pollution_detection",
23
+ "solar_panel": "solar_panel",
24
+ "face_emotion": "face_emotion",
25
+ "pedestrian_detection": "pedestrian_detection",
26
+ "warehouse_object_segmentation": "warehouse_object_segmentation",
27
+ "flower_segmentation": "flower_segmentation",
28
+ "shopping_cart_analysis": "shopping_cart_analysis",
29
+ "car_part_segmentation": "car_part_segmentation",
30
+ "weld_defect_detection" : "weld_defect_detection",
31
+ "fruit_monitoring" : "fruit_monitoring",
32
+ "concrete_crack_detection": "concrete_crack_detection",
33
+ "lane_detection" : "lane_detection",
34
+ "shelf_inventory" :"shelf_inventory",
35
+ "smoker_detection": "smoker_detection",
36
+ "age_detection": "age_detection",
37
+ "defect_detection_products": "defect_detection_products",
38
+ "parking_space_detection": "parking_space_detection",
39
+ "car_damage_detection": "car_damage_detection",
40
+ "license_plate_detection": "license_plate_detection",
41
+ "shoplifting_detection": "shoplifting_detection",
42
+ "cardiomegaly_classification": "cardiomegaly_classification",
43
+ "road_traffic_density": "road_traffic_density",
44
+ "histopathological_cancer_detection" : "histopathological_cancer_detection",
45
+ "road_view_segmentation": "road_view_segmentation",
46
+ "face_recognition": "face_recognition",
47
+ "drowsy_driver_detection": "drowsy_driver_detection",
48
+ "waterbody_segmentation": "waterbody_segmentation",
49
+ "litter_detection" : "litter_detection",
50
+ "leak_detection": "leak_detection",
51
+ "Fire Safety Monitoring": "fire_smoke_detection",
52
+ "human_activity_recognition": "human_activity_recognition",
53
+ "abandoned_object_detection" : "abandoned_object_detection",
54
+ "gas_leak_detection": "gas_leak_detection",
55
+ "color_detection": "color_detection",
56
+ "Color Detection": "color_detection",
57
+ "License Plate Recognition" : "license_plate_monitor",
58
+ "License Plate Monitoring" : "license_plate_monitor",
59
+ "cell_microscopy_segmentation": "cell_microscopy_segmentation",
60
+ "Dwell Detection": "dwell",
61
+ "age_gender_detection": "age_gender_detection",
62
+ "People Tracking" : "people_tracking",
63
+ "wildlife_monitoring": "wildlife_monitoring",
64
+ "pcb_defect_detection": "pcb_defect_detection",
65
+ "underground_pipeline_defect" : "underground_pipeline_defect",
66
+ "suspicious_activity_detection": "suspicious_activity_detection",
67
+ "natural_disaster_detection": "natural_disaster_detection",
68
+ }
69
+
70
+ APP_NAME_TO_CATEGORY = {
71
+ "people_counting": "general",
72
+ "drone_traffic_monitoring": "traffic",
73
+ "intrusion_detection": "security",
74
+ "proximity_detection": "security",
75
+ "mask_detection": "mask_detection",
76
+ "pipeline_detection": "pipeline_detection",
77
+ "vehicle_monitoring": "traffic",
78
+ "Vehicle Type Monitoring": "traffic",
79
+ "weapon_detection": "security",
80
+ "traffic_sign_monitoring": "traffic",
81
+ "flare_analysis": "flare_detection",
82
+ "ppe_compliance": "security",
83
+ "advanced_customer_service": "sales",
84
+ "assembly_line_detection": "manufacturing",
85
+ "crop_weed_detection": "agriculture",
86
+ "emergency_vehicle_detection": "traffic",
87
+ "fashion_detection": "retail",
88
+ "gender_detection": "general",
89
+ "price_tag_detection": "retail",
90
+ "windmill_maintenance": "windmill_maintenance",
91
+ "underwater_pollution_detection": "environmental",
92
+ "solar_panel": "energy",
93
+ "face_emotion": "general",
94
+ "pedestrian_detection": "pedestrian",
95
+ "warehouse_object_segmentation": "retail",
96
+ "flower_segmentation": "agriculture",
97
+ "shopping_cart_analysis": "retail",
98
+ "car_part_segmentation": "automobile",
99
+ "weld_defect_detection" : "weld",
100
+ "fruit_monitoring" : "agriculture",
101
+ "concrete_crack_detection": "general",
102
+ "lane_detection" : "traffic",
103
+ "shelf_inventory" : "retail",
104
+ "smoker_detection": "general",
105
+ "age_detection": "general",
106
+ "defect_detection_products": "retail",
107
+ "parking_space_detection": "parking_space",
108
+ "car_damage_detection": "car_damage",
109
+ "license_plate_detection": "license_plate",
110
+ "shoplifting_detection": "security",
111
+ "cardiomegaly_classification": "healthcare",
112
+ "road_traffic_density": "automobile",
113
+ "histopathological_cancer_detection" : "healthcare",
114
+ "road_view_segmentation": "automobile",
115
+ "face_recognition": "security",
116
+ "drowsy_driver_detection": "automobile",
117
+ "waterbody_segmentation": "agriculture",
118
+ "litter_detection" : "litter_detection",
119
+ "leak_detection": "oil_gas",
120
+ "Fire Safety Monitoring": "hazard",
121
+ "human_activity_recognition": "general",
122
+ "abandoned_object_detection" : "security",
123
+ "gas_leak_detection": "oil_gas",
124
+ "color_detection": "visual_appearance",
125
+ "Color Detection": "visual_appearance",
126
+ "License Plate Recognition" : "license_plate_monitor",
127
+ "License Plate Monitoring" : "license_plate_monitor",
128
+ "cell_microscopy_segmentation" : "healthcare",
129
+ "Dwell Detection": "general",
130
+ "age_gender_detection": "age_gender_detection",
131
+ "People Tracking" : "general",
132
+
133
+ "wildlife_monitoring": "environmental",
134
+ "pcb_defect_detection": "manufacturing",
135
+ "underground_pipeline_defect" : "general",
136
+ "suspicious_activity_detection": "security",
137
+ "natural_disaster_detection": "environmental",
138
+ }
139
+
140
+ def get_usecase_from_app_name(app_name: str) -> str:
141
+ normalized_app_name = app_name.lower().replace(" ", "_").replace("-", "_")
142
+ return APP_NAME_TO_USECASE.get(app_name, APP_NAME_TO_USECASE.get(normalized_app_name))
143
+
144
+ def get_category_from_app_name(app_name: str) -> str:
145
+ normalized_app_name = app_name.lower().replace(" ", "_").replace("-", "_")
146
+ return APP_NAME_TO_CATEGORY.get(app_name, APP_NAME_TO_CATEGORY.get(normalized_app_name))
@@ -0,0 +1,63 @@
1
+ """
2
+ Core components for post-processing.
3
+
4
+ This module contains core base classes and configuration utilities.
5
+ Note: Use case imports have been moved to avoid circular imports.
6
+ """
7
+
8
+ # Core components that don't create circular imports
9
+ from .base import (
10
+ ProcessingResult,
11
+ ProcessingContext,
12
+ ProcessingStatus,
13
+ ResultFormat,
14
+ BaseProcessor,
15
+ BaseUseCase,
16
+ ProcessorRegistry,
17
+ registry
18
+ )
19
+
20
+ from .config import (
21
+ BaseConfig,
22
+ PeopleCountingConfig,
23
+ CustomerServiceConfig,
24
+ IntrusionConfig,
25
+ ZoneConfig,
26
+ TrackingConfig,
27
+ AlertConfig,
28
+ ConfigManager,
29
+ config_manager,
30
+ ConfigValidationError,
31
+ PeopleTrackingConfig
32
+ )
33
+
34
+ # Note: Use case imports have been removed from this file to avoid circular imports.
35
+ # Use cases should be imported directly from their respective modules in the usecases package.
36
+
37
+
38
+ # Export only core components to avoid circular imports
39
+ __all__ = [
40
+ # Base classes
41
+ 'ProcessingResult',
42
+ 'ProcessingContext',
43
+ 'ProcessingStatus',
44
+ 'ResultFormat',
45
+ 'BaseProcessor',
46
+ 'BaseUseCase',
47
+ 'ProcessorRegistry',
48
+ 'registry',
49
+
50
+ # Configuration classes
51
+ 'BaseConfig',
52
+ 'PeopleCountingConfig',
53
+ 'IntrusionConfig',
54
+ 'ProximityConfig',
55
+ 'CustomerServiceConfig',
56
+ 'ZoneConfig',
57
+ 'TrackingConfig',
58
+ 'AlertConfig',
59
+ 'ConfigManager',
60
+ 'config_manager',
61
+ 'ConfigValidationError',
62
+ 'PeopleTrackingConfig',
63
+ ]