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,380 @@
1
+ """
2
+ Template Use Case for creating new standardized use cases.
3
+
4
+ This template shows how to create a new use case that follows the standardized
5
+ agg_summary structure. Copy this file and modify it for your specific use case.
6
+
7
+ Example use case: Fire Detection
8
+ """
9
+
10
+ from typing import Any, Dict, List, Optional, Union
11
+ from dataclasses import asdict
12
+ import time
13
+
14
+ from ..core.base import BaseProcessor, ProcessingContext, ProcessingResult, ConfigProtocol, ResultFormat
15
+ from ..core.config import BaseConfig
16
+ from ..utils import (
17
+ filter_by_confidence,
18
+ filter_by_categories,
19
+ apply_category_mapping,
20
+ count_objects_by_category,
21
+ calculate_counting_summary,
22
+ match_results_structure
23
+ )
24
+
25
+
26
+ class TemplateUseCaseConfig(BaseConfig):
27
+ """Configuration for Template Use Case."""
28
+
29
+ def __init__(self,
30
+ usecase: str = "template_usecase",
31
+ category: str = "general",
32
+ confidence_threshold: float = 0.5,
33
+ target_categories: List[str] = None,
34
+ enable_analytics: bool = True,
35
+ alert_threshold: int = 5,
36
+ **kwargs):
37
+ super().__init__(usecase=usecase, category=category, **kwargs)
38
+ self.confidence_threshold = confidence_threshold
39
+ self.target_categories = target_categories or ["fire", "smoke"] # Example categories
40
+ self.enable_analytics = enable_analytics
41
+ self.alert_threshold = alert_threshold
42
+
43
+ def validate(self) -> List[str]:
44
+ """Validate configuration."""
45
+ errors = super().validate()
46
+
47
+ if not 0.0 <= self.confidence_threshold <= 1.0:
48
+ errors.append("confidence_threshold must be between 0.0 and 1.0")
49
+
50
+ if self.alert_threshold < 1:
51
+ errors.append("alert_threshold must be positive")
52
+
53
+ return errors
54
+
55
+
56
+ class TemplateUseCase(BaseProcessor):
57
+ """Template use case showing how to implement standardized agg_summary structure."""
58
+
59
+ def __init__(self):
60
+ """Initialize template use case."""
61
+ super().__init__("template_usecase")
62
+ self.category = "general"
63
+
64
+ # Add any state tracking variables here
65
+ self._detection_count = 0
66
+ self._total_detections = 0
67
+
68
+ def get_config_schema(self) -> Dict[str, Any]:
69
+ """Get configuration schema for template use case."""
70
+ return {
71
+ "type": "object",
72
+ "properties": {
73
+ "confidence_threshold": {
74
+ "type": "number",
75
+ "minimum": 0.0,
76
+ "maximum": 1.0,
77
+ "default": 0.5,
78
+ "description": "Minimum confidence threshold for detections"
79
+ },
80
+ "target_categories": {
81
+ "type": "array",
82
+ "items": {"type": "string"},
83
+ "default": ["fire", "smoke"],
84
+ "description": "Target categories to detect"
85
+ },
86
+ "enable_analytics": {
87
+ "type": "boolean",
88
+ "default": True,
89
+ "description": "Enable analytics generation"
90
+ },
91
+ "alert_threshold": {
92
+ "type": "integer",
93
+ "minimum": 1,
94
+ "default": 5,
95
+ "description": "Threshold for generating alerts"
96
+ }
97
+ },
98
+ "required": ["confidence_threshold"],
99
+ "additionalProperties": False
100
+ }
101
+
102
+ def create_default_config(self, **overrides) -> TemplateUseCaseConfig:
103
+ """Create default configuration with optional overrides."""
104
+ defaults = {
105
+ "category": self.category,
106
+ "usecase": self.name,
107
+ "confidence_threshold": 0.5,
108
+ "target_categories": ["fire", "smoke"],
109
+ "enable_analytics": True,
110
+ "alert_threshold": 5,
111
+ }
112
+ defaults.update(overrides)
113
+ return TemplateUseCaseConfig(**defaults)
114
+
115
+ def process(self, data: Any, config: ConfigProtocol,
116
+ context: Optional[ProcessingContext] = None,
117
+ stream_info: Optional[Any] = None) -> ProcessingResult:
118
+ """
119
+ Process data using template use case - automatically detects single or multi-frame structure.
120
+
121
+ Args:
122
+ data: Raw model output (detection or tracking format)
123
+ config: Template use case configuration
124
+ context: Processing context
125
+ stream_info: Stream information (optional)
126
+
127
+ Returns:
128
+ ProcessingResult: Processing result with standardized agg_summary structure
129
+ """
130
+ try:
131
+ # Ensure we have the right config type
132
+ if not isinstance(config, TemplateUseCaseConfig):
133
+ return self.create_error_result(
134
+ "Invalid configuration type for template use case",
135
+ usecase=self.name,
136
+ category=self.category,
137
+ context=context
138
+ )
139
+
140
+ # Initialize processing context if not provided
141
+ if context is None:
142
+ context = ProcessingContext()
143
+
144
+ # Detect frame structure automatically
145
+ is_multi_frame = self.detect_frame_structure(data)
146
+
147
+ self.logger.info(f"Processing template use case - Multi-frame: {is_multi_frame}")
148
+
149
+ # Process based on frame structure
150
+ if is_multi_frame:
151
+ agg_summary = self._process_multi_frame(data, config, stream_info)
152
+ else:
153
+ agg_summary = self._process_single_frame(data, config, stream_info)
154
+
155
+ # Mark processing as completed
156
+ context.mark_completed()
157
+
158
+ # Create result with standardized agg_summary
159
+ return self.create_result(
160
+ data={"agg_summary": agg_summary},
161
+ usecase=self.name,
162
+ category=self.category,
163
+ context=context
164
+ )
165
+
166
+ except Exception as e:
167
+ self.logger.error(f"Template use case failed: {str(e)}", exc_info=True)
168
+
169
+ if context:
170
+ context.mark_completed()
171
+
172
+ return self.create_error_result(
173
+ str(e),
174
+ type(e).__name__,
175
+ usecase=self.name,
176
+ category=self.category,
177
+ context=context
178
+ )
179
+
180
+ def _process_multi_frame(self, data: Dict, config: TemplateUseCaseConfig,
181
+ stream_info: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
182
+ """Process multi-frame data to generate frame-wise agg_summary."""
183
+
184
+ frame_incidents = {}
185
+ frame_tracking_stats = {}
186
+ frame_business_analytics = {}
187
+ frame_human_text = {}
188
+
189
+ # Process each frame individually
190
+ for frame_key, frame_detections in data.items():
191
+ frame_id = str(frame_key)
192
+
193
+ # Process this single frame's detections
194
+ incidents, tracking_stats, business_analytics, summary = self._process_frame_detections(
195
+ frame_detections, config, frame_id, stream_info
196
+ )
197
+
198
+ # Store frame-wise results
199
+ if incidents:
200
+ frame_incidents[frame_id] = incidents
201
+ if tracking_stats:
202
+ frame_tracking_stats[frame_id] = tracking_stats
203
+ if business_analytics:
204
+ frame_business_analytics[frame_id] = business_analytics
205
+ if summary:
206
+ frame_human_text[frame_id] = summary
207
+
208
+ # Create frame-wise agg_summary
209
+ return self.create_frame_wise_agg_summary(
210
+ frame_incidents, frame_tracking_stats, frame_business_analytics,
211
+ frame_human_text=frame_human_text
212
+ )
213
+
214
+ def _process_single_frame(self, data: Any, config: TemplateUseCaseConfig,
215
+ stream_info: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
216
+ """Process single frame data and return standardized agg_summary."""
217
+
218
+ # Process frame data
219
+ incidents, tracking_stats, business_analytics, summary = self._process_frame_detections(
220
+ data, config, "current_frame", stream_info
221
+ )
222
+
223
+ # Create single-frame agg_summary
224
+ return self.create_agg_summary(
225
+ "current_frame", incidents, tracking_stats, business_analytics, human_text=summary
226
+ )
227
+
228
+ def _process_frame_detections(self, frame_data: Any, config: TemplateUseCaseConfig,
229
+ frame_id: str, stream_info: Optional[Dict[str, Any]] = None) -> tuple:
230
+ """Process detections from a single frame and return standardized components."""
231
+
232
+ # Convert frame_data to list if it's not already
233
+ if isinstance(frame_data, list):
234
+ detections = frame_data
235
+ else:
236
+ # Handle other formats as needed
237
+ detections = []
238
+
239
+ # Step 1: Apply confidence filtering
240
+ if config.confidence_threshold is not None:
241
+ detections = [d for d in detections if d.get("confidence", 0) >= config.confidence_threshold]
242
+
243
+ # Step 2: Apply category mapping if provided
244
+ if config.index_to_category:
245
+ detections = apply_category_mapping(detections, config.index_to_category)
246
+
247
+ # Step 3: Filter to target categories
248
+ if config.target_categories:
249
+ detections = [d for d in detections if d.get("category") in config.target_categories]
250
+
251
+ # Step 4: Update internal state
252
+ current_count = len(detections)
253
+ self._detection_count = current_count
254
+ self._total_detections += current_count
255
+
256
+ # Step 5: Generate standardized components
257
+ incidents = self._generate_incidents(detections, config, frame_id, stream_info)
258
+ tracking_stats = self._generate_tracking_stats(detections, config, stream_info)
259
+ business_analytics = self._generate_business_analytics(detections, config, stream_info) if config.enable_analytics else []
260
+ summary = self._generate_summary(detections, config)
261
+
262
+ return incidents, tracking_stats, business_analytics, summary
263
+
264
+ def _generate_incidents(self, detections: List[Dict], config: TemplateUseCaseConfig,
265
+ frame_id: str, stream_info: Optional[Dict[str, Any]] = None) -> List[Dict]:
266
+ """Generate standardized incidents."""
267
+ incidents = []
268
+
269
+ if len(detections) > 0:
270
+ # Determine severity level based on detection count
271
+ severity_level = self.determine_severity_level(
272
+ len(detections), threshold_low=1, threshold_medium=3, threshold_critical=config.alert_threshold
273
+ )
274
+
275
+ # Get camera info
276
+ camera_info = self.get_camera_info_from_stream(stream_info)
277
+
278
+ # Create incident
279
+ incident_id = f"template_detection_{frame_id}_{int(time.time())}"
280
+ incident_text = f"Template detection event with {len(detections)} detections [Severity: {severity_level}]"
281
+
282
+ incident = self.create_incident(
283
+ incident_id, "template_detection", severity_level,
284
+ incident_text, camera_info
285
+ )
286
+ incidents.append(incident)
287
+
288
+ return incidents
289
+
290
+ def _generate_tracking_stats(self, detections: List[Dict], config: TemplateUseCaseConfig,
291
+ stream_info: Optional[Dict[str, Any]] = None) -> List[Dict]:
292
+ """Generate standardized tracking stats."""
293
+
294
+ # Get camera info
295
+ camera_info = self.get_camera_info_from_stream(stream_info)
296
+
297
+ # Build total_counts and current_counts
298
+ total_counts = []
299
+ current_counts = []
300
+
301
+ for category in config.target_categories:
302
+ category_current = sum(1 for d in detections if d.get("category") == category)
303
+ category_total = self._total_detections # This would be category-specific in real implementation
304
+
305
+ if category_current > 0:
306
+ current_counts.append(self.create_count_object(category, category_current))
307
+ if category_total > 0:
308
+ total_counts.append(self.create_count_object(category, category_total))
309
+
310
+ # Prepare detections for tracking stats (without confidence and track_id)
311
+ tracking_detections = []
312
+ for detection in detections:
313
+ bbox = detection.get("bounding_box", {})
314
+ category = detection.get("category", "unknown")
315
+
316
+ detection_obj = self.create_detection_object(category, bbox)
317
+ tracking_detections.append(detection_obj)
318
+
319
+ # Generate human text
320
+ current_timestamp = self.get_high_precision_timestamp()
321
+ human_text = self.generate_tracking_human_text(
322
+ {cat: sum(1 for d in detections if d.get("category") == cat) for cat in config.target_categories},
323
+ {cat: self._total_detections for cat in config.target_categories}, # Simplified
324
+ current_timestamp, current_timestamp
325
+ )
326
+
327
+ # Create tracking stats
328
+ tracking_stat = self.create_tracking_stats(
329
+ total_counts, current_counts, tracking_detections, human_text, camera_info
330
+ )
331
+
332
+ return [tracking_stat]
333
+
334
+ def _generate_business_analytics(self, detections: List[Dict], config: TemplateUseCaseConfig,
335
+ stream_info: Optional[Dict[str, Any]] = None) -> List[Dict]:
336
+ """Generate standardized business analytics."""
337
+
338
+ # Get camera info
339
+ camera_info = self.get_camera_info_from_stream(stream_info)
340
+
341
+ # Calculate analytics statistics
342
+ analytics_stats = {
343
+ "detection_count": len(detections),
344
+ "total_detections": self._total_detections,
345
+ "detection_rate": len(detections) / max(1, self._total_detections) * 100
346
+ }
347
+
348
+ # Add category breakdown
349
+ for category in config.target_categories:
350
+ category_count = sum(1 for d in detections if d.get("category") == category)
351
+ analytics_stats[f"{category}_count"] = category_count
352
+
353
+ # Generate human text
354
+ current_timestamp = self.get_high_precision_timestamp()
355
+ analytics_human_text = self.generate_analytics_human_text(
356
+ "template_analytics", analytics_stats, current_timestamp, current_timestamp
357
+ )
358
+
359
+ # Create business analytics
360
+ analytics = self.create_business_analytics(
361
+ "template_analytics", analytics_stats, analytics_human_text, camera_info
362
+ )
363
+
364
+ return [analytics]
365
+
366
+ def _generate_summary(self, detections: List[Dict], config: TemplateUseCaseConfig) -> str:
367
+ """Generate human-readable summary."""
368
+ if len(detections) == 0:
369
+ return "No detections found"
370
+
371
+ category_counts = {}
372
+ for detection in detections:
373
+ category = detection.get("category", "unknown")
374
+ category_counts[category] = category_counts.get(category, 0) + 1
375
+
376
+ summary_parts = []
377
+ for category, count in category_counts.items():
378
+ summary_parts.append(f"{count} {category} detection{'s' if count != 1 else ''}")
379
+
380
+ return f"Template Use Case: {', '.join(summary_parts)} detected"