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,583 @@
1
+ """
2
+ Test data generators for post-processing tests.
3
+
4
+ This module provides functions to generate realistic test data for all
5
+ post-processing use cases including detection results, tracking data,
6
+ zone configurations, and various edge cases.
7
+ """
8
+
9
+ import random
10
+ import time
11
+ import math
12
+ from typing import Dict, List, Any, Optional, Tuple, Union
13
+
14
+ # Fix imports for proper module resolution
15
+ import sys
16
+ import os
17
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../src'))
18
+
19
+ from src.matrice_analytics.post_processing import (
20
+ PeopleCountingConfig, CustomerServiceConfig, ZoneConfig, AlertConfig, TrackingConfig
21
+ )
22
+
23
+
24
+ def create_detection_results(
25
+ num_detections: int = 10,
26
+ categories: List[str] = None,
27
+ confidence_range: Tuple[float, float] = (0.5, 0.95),
28
+ bbox_size_range: Tuple[int, int] = (20, 100),
29
+ image_size: Tuple[int, int] = (640, 480),
30
+ include_metadata: bool = True
31
+ ) -> List[Dict[str, Any]]:
32
+ """Create realistic detection results."""
33
+ if categories is None:
34
+ categories = ["person", "car", "bike", "truck", "bus"]
35
+
36
+ detections = []
37
+
38
+ for i in range(num_detections):
39
+ # Generate random bbox
40
+ width = random.randint(*bbox_size_range)
41
+ height = random.randint(*bbox_size_range)
42
+ x1 = random.randint(0, image_size[0] - width)
43
+ y1 = random.randint(0, image_size[1] - height)
44
+ x2 = x1 + width
45
+ y2 = y1 + height
46
+
47
+ detection = {
48
+ "bbox": [x1, y1, x2, y2],
49
+ "confidence": random.uniform(*confidence_range),
50
+ "category": random.choice(categories)
51
+ }
52
+
53
+ if include_metadata:
54
+ detection.update({
55
+ "detection_id": i,
56
+ "area": width * height,
57
+ "aspect_ratio": width / height,
58
+ "center": [(x1 + x2) / 2, (y1 + y2) / 2]
59
+ })
60
+
61
+ detections.append(detection)
62
+
63
+ return detections
64
+
65
+
66
+ def create_tracking_results(
67
+ num_tracks: int = 8,
68
+ categories: List[str] = None,
69
+ frames: int = 10,
70
+ confidence_range: Tuple[float, float] = (0.6, 0.9),
71
+ bbox_size_range: Tuple[int, int] = (30, 80),
72
+ image_size: Tuple[int, int] = (640, 480),
73
+ include_trajectory: bool = True
74
+ ) -> List[Dict[str, Any]]:
75
+ """Create realistic tracking results."""
76
+ if categories is None:
77
+ categories = ["person", "car", "bike"]
78
+
79
+ tracks = []
80
+
81
+ for track_id in range(1, num_tracks + 1):
82
+ category = random.choice(categories)
83
+
84
+ # Generate initial position and movement pattern
85
+ initial_x = random.randint(50, image_size[0] - 150)
86
+ initial_y = random.randint(50, image_size[1] - 150)
87
+
88
+ # Movement pattern
89
+ velocity_x = random.uniform(-2, 2)
90
+ velocity_y = random.uniform(-2, 2)
91
+
92
+ # Size variation
93
+ base_width = random.randint(*bbox_size_range)
94
+ base_height = random.randint(*bbox_size_range)
95
+
96
+ for frame in range(1, frames + 1):
97
+ # Calculate position with some noise
98
+ x = initial_x + velocity_x * frame + random.uniform(-5, 5)
99
+ y = initial_y + velocity_y * frame + random.uniform(-5, 5)
100
+
101
+ # Ensure bbox stays within image
102
+ x = max(0, min(x, image_size[0] - base_width))
103
+ y = max(0, min(y, image_size[1] - base_height))
104
+
105
+ # Size variation
106
+ width = base_width + random.randint(-5, 5)
107
+ height = base_height + random.randint(-5, 5)
108
+
109
+ track = {
110
+ "track_id": track_id,
111
+ "bbox": [int(x), int(y), int(x + width), int(y + height)],
112
+ "confidence": random.uniform(*confidence_range),
113
+ "category": category,
114
+ "frame": frame,
115
+ "timestamp": time.time() + frame * 0.033 # ~30 FPS
116
+ }
117
+
118
+ if include_trajectory:
119
+ track.update({
120
+ "velocity": [velocity_x, velocity_y],
121
+ "age": frame,
122
+ "hits": frame,
123
+ "time_since_update": 0
124
+ })
125
+
126
+ tracks.append(track)
127
+
128
+ return tracks
129
+
130
+
131
+ def create_zone_polygons(
132
+ zone_names: List[str],
133
+ image_size: Tuple[int, int] = (640, 480),
134
+ zone_types: List[str] = None
135
+ ) -> Dict[str, List[List[int]]]:
136
+ """Create zone polygon configurations."""
137
+ if zone_types is None:
138
+ zone_types = ["rectangular", "triangular", "complex"]
139
+
140
+ zones = {}
141
+
142
+ for i, zone_name in enumerate(zone_names):
143
+ zone_type = random.choice(zone_types)
144
+
145
+ if zone_type == "rectangular":
146
+ # Create rectangular zone
147
+ x1 = random.randint(0, image_size[0] // 2)
148
+ y1 = random.randint(0, image_size[1] // 2)
149
+ width = random.randint(100, image_size[0] // 2)
150
+ height = random.randint(100, image_size[1] // 2)
151
+ x2 = min(x1 + width, image_size[0])
152
+ y2 = min(y1 + height, image_size[1])
153
+
154
+ polygon = [[x1, y1], [x2, y1], [x2, y2], [x1, y2]]
155
+
156
+ elif zone_type == "triangular":
157
+ # Create triangular zone
158
+ center_x = random.randint(100, image_size[0] - 100)
159
+ center_y = random.randint(100, image_size[1] - 100)
160
+ radius = random.randint(50, 100)
161
+
162
+ polygon = [
163
+ [center_x, center_y - radius],
164
+ [center_x + int(radius * 0.866), center_y + radius // 2],
165
+ [center_x - int(radius * 0.866), center_y + radius // 2]
166
+ ]
167
+
168
+ else: # complex
169
+ # Create complex polygon
170
+ center_x = random.randint(150, image_size[0] - 150)
171
+ center_y = random.randint(150, image_size[1] - 150)
172
+
173
+ num_points = random.randint(5, 8)
174
+ polygon = []
175
+
176
+ for j in range(num_points):
177
+ angle = (2 * math.pi * j) / num_points
178
+ radius = random.randint(50, 100)
179
+ x = center_x + int(radius * math.cos(angle))
180
+ y = center_y + int(radius * math.sin(angle))
181
+ polygon.append([x, y])
182
+
183
+ zones[zone_name] = polygon
184
+
185
+ return zones
186
+
187
+
188
+ def create_customer_service_areas() -> Dict[str, Dict[str, List[List[int]]]]:
189
+ """Create customer service area configurations."""
190
+ return {
191
+ "customer_areas": {
192
+ "entrance": [[0, 0], [200, 0], [200, 150], [0, 150]],
193
+ "lobby": [[50, 150], [350, 150], [350, 300], [50, 300]],
194
+ "waiting_area": [[100, 300], [300, 300], [300, 400], [100, 400]],
195
+ "queue": [[200, 400], [250, 400], [250, 500], [200, 500]]
196
+ },
197
+ "staff_areas": {
198
+ "counter": [[350, 200], [500, 200], [500, 350], [350, 350]],
199
+ "office": [[500, 100], [600, 100], [600, 200], [500, 200]],
200
+ "break_room": [[500, 350], [600, 350], [600, 450], [500, 450]]
201
+ },
202
+ "service_areas": {
203
+ "service_desk_1": [[300, 200], [350, 200], [350, 250], [300, 250]],
204
+ "service_desk_2": [[300, 250], [350, 250], [350, 300], [300, 300]],
205
+ "consultation": [[400, 300], [500, 300], [500, 400], [400, 400]]
206
+ }
207
+ }
208
+
209
+
210
+ def create_line_crossing_data(
211
+ lines: Dict[str, List[List[int]]],
212
+ num_tracks: int = 5,
213
+ frames: int = 20
214
+ ) -> List[Dict[str, Any]]:
215
+ """Create tracking data that crosses specified lines."""
216
+ tracks = []
217
+
218
+ for track_id in range(1, num_tracks + 1):
219
+ # Pick a random line to cross
220
+ line_name = random.choice(list(lines.keys()))
221
+ line_points = lines[line_name]
222
+
223
+ # Start on one side of the line, end on the other
224
+ start_x = line_points[0][0] - 50
225
+ start_y = line_points[0][1] + random.randint(-20, 20)
226
+ end_x = line_points[1][0] + 50
227
+ end_y = line_points[1][1] + random.randint(-20, 20)
228
+
229
+ for frame in range(1, frames + 1):
230
+ # Linear interpolation
231
+ progress = frame / frames
232
+ x = start_x + (end_x - start_x) * progress
233
+ y = start_y + (end_y - start_y) * progress
234
+
235
+ track = {
236
+ "track_id": track_id,
237
+ "bbox": [int(x), int(y), int(x + 40), int(y + 60)],
238
+ "confidence": random.uniform(0.7, 0.9),
239
+ "category": "person",
240
+ "frame": frame,
241
+ "timestamp": time.time() + frame * 0.033
242
+ }
243
+
244
+ tracks.append(track)
245
+
246
+ return tracks
247
+
248
+
249
+ def create_people_counting_scenarios() -> List[Dict[str, Any]]:
250
+ """Create various people counting test scenarios."""
251
+ scenarios = []
252
+
253
+ # Scenario 1: Basic counting
254
+ scenarios.append({
255
+ "name": "basic_counting",
256
+ "description": "Basic people counting with simple detections",
257
+ "data": create_detection_results(
258
+ num_detections=15,
259
+ categories=["person"],
260
+ confidence_range=(0.6, 0.95)
261
+ ),
262
+ "config": {
263
+ "confidence_threshold": 0.5,
264
+ "person_categories": ["person"]
265
+ }
266
+ })
267
+
268
+ # Scenario 2: Zone-based counting
269
+ zones = create_zone_polygons(["entrance", "lobby", "exit"])
270
+ scenarios.append({
271
+ "name": "zone_counting",
272
+ "description": "People counting with zone analysis",
273
+ "data": create_detection_results(num_detections=20),
274
+ "config": {
275
+ "confidence_threshold": 0.6,
276
+ "zone_config": {"zones": zones}
277
+ }
278
+ })
279
+
280
+ # Scenario 3: Tracking-based unique counting
281
+ scenarios.append({
282
+ "name": "unique_counting",
283
+ "description": "Unique people counting with tracking",
284
+ "data": create_tracking_results(num_tracks=8, frames=15),
285
+ "config": {
286
+ "confidence_threshold": 0.5,
287
+ "enable_tracking": True,
288
+ "enable_unique_counting": True
289
+ }
290
+ })
291
+
292
+ return scenarios
293
+
294
+
295
+ def create_customer_service_scenarios() -> List[Dict[str, Any]]:
296
+ """Create customer service analysis test scenarios."""
297
+ scenarios = []
298
+ areas = create_customer_service_areas()
299
+
300
+ # Scenario 1: Basic customer service
301
+ scenarios.append({
302
+ "name": "basic_service",
303
+ "description": "Basic customer service analysis",
304
+ "data": create_detection_results(
305
+ num_detections=25,
306
+ categories=["person", "staff"]
307
+ ),
308
+ "config": {
309
+ "confidence_threshold": 0.6,
310
+ "customer_areas": areas["customer_areas"],
311
+ "staff_areas": areas["staff_areas"],
312
+ "service_areas": areas["service_areas"],
313
+ "staff_categories": ["staff"],
314
+ "customer_categories": ["person"]
315
+ }
316
+ })
317
+
318
+ # Scenario 2: Queue analysis
319
+ scenarios.append({
320
+ "name": "queue_analysis",
321
+ "description": "Customer queue analysis with wait times",
322
+ "data": create_tracking_results(
323
+ num_tracks=12,
324
+ frames=30,
325
+ categories=["person", "staff"]
326
+ ),
327
+ "config": {
328
+ "confidence_threshold": 0.5,
329
+ "enable_tracking": True,
330
+ "customer_areas": areas["customer_areas"],
331
+ "service_areas": areas["service_areas"],
332
+ "max_service_time": 300.0
333
+ }
334
+ })
335
+
336
+ return scenarios
337
+
338
+
339
+ def create_basic_counting_tracking_scenarios() -> List[Dict[str, Any]]:
340
+ """Create basic counting and tracking test scenarios."""
341
+ scenarios = []
342
+
343
+ # Scenario 1: Line crossing detection
344
+ lines = {
345
+ "entrance_line": [[100, 200], [200, 200]],
346
+ "exit_line": [[400, 200], [500, 200]]
347
+ }
348
+
349
+ scenarios.append({
350
+ "name": "line_crossing",
351
+ "description": "Line crossing detection and counting",
352
+ "data": create_line_crossing_data(lines, num_tracks=6, frames=25),
353
+ "config": {
354
+ "confidence_threshold": 0.6,
355
+ "enable_tracking": True,
356
+ "lines": lines
357
+ }
358
+ })
359
+
360
+ # Scenario 2: Zone tracking
361
+ zones = create_zone_polygons(["zone_a", "zone_b", "zone_c"])
362
+ scenarios.append({
363
+ "name": "zone_tracking",
364
+ "description": "Object tracking within zones",
365
+ "data": create_tracking_results(num_tracks=10, frames=20),
366
+ "config": {
367
+ "confidence_threshold": 0.5,
368
+ "enable_tracking": True,
369
+ "zones": zones
370
+ }
371
+ })
372
+
373
+ return scenarios
374
+
375
+
376
+ def create_edge_case_data() -> Dict[str, List[Dict[str, Any]]]:
377
+ """Create edge case test data."""
378
+ return {
379
+ "empty_results": [],
380
+ "single_detection": create_detection_results(num_detections=1),
381
+ "low_confidence": create_detection_results(
382
+ num_detections=5,
383
+ confidence_range=(0.1, 0.4)
384
+ ),
385
+ "high_confidence": create_detection_results(
386
+ num_detections=5,
387
+ confidence_range=(0.95, 1.0)
388
+ ),
389
+ "overlapping_bboxes": [
390
+ {"bbox": [100, 100, 200, 200], "confidence": 0.8, "category": "person"},
391
+ {"bbox": [150, 150, 250, 250], "confidence": 0.7, "category": "person"},
392
+ {"bbox": [120, 120, 220, 220], "confidence": 0.9, "category": "person"}
393
+ ],
394
+ "boundary_bboxes": [
395
+ {"bbox": [0, 0, 50, 50], "confidence": 0.8, "category": "person"},
396
+ {"bbox": [590, 430, 640, 480], "confidence": 0.7, "category": "person"}
397
+ ],
398
+ "malformed_data": [
399
+ {"bbox": [100, 100], "confidence": 0.8}, # Missing coordinates
400
+ {"confidence": 0.7, "category": "person"}, # Missing bbox
401
+ {"bbox": [100, 100, 200, 200]}, # Missing confidence
402
+ ]
403
+ }
404
+
405
+
406
+ def create_performance_test_data(scale: str = "medium") -> Dict[str, Any]:
407
+ """Create performance test data at different scales."""
408
+ scales = {
409
+ "small": {"detections": 50, "tracks": 10, "frames": 10},
410
+ "medium": {"detections": 500, "tracks": 50, "frames": 30},
411
+ "large": {"detections": 2000, "tracks": 200, "frames": 100},
412
+ "huge": {"detections": 10000, "tracks": 1000, "frames": 500}
413
+ }
414
+
415
+ if scale not in scales:
416
+ scale = "medium"
417
+
418
+ params = scales[scale]
419
+
420
+ return {
421
+ "detection_data": create_detection_results(
422
+ num_detections=params["detections"]
423
+ ),
424
+ "tracking_data": create_tracking_results(
425
+ num_tracks=params["tracks"],
426
+ frames=params["frames"]
427
+ ),
428
+ "zones": create_zone_polygons([f"zone_{i}" for i in range(10)]),
429
+ "scale_info": {
430
+ "scale": scale,
431
+ "expected_detections": params["detections"],
432
+ "expected_tracks": params["tracks"],
433
+ "expected_frames": params["frames"]
434
+ }
435
+ }
436
+
437
+
438
+ def create_multi_camera_data(num_cameras: int = 3) -> Dict[str, Any]:
439
+ """Create multi-camera test data."""
440
+ cameras = {}
441
+
442
+ for camera_id in range(1, num_cameras + 1):
443
+ cameras[f"camera_{camera_id}"] = {
444
+ "detection_data": create_detection_results(
445
+ num_detections=random.randint(10, 30),
446
+ image_size=(1920, 1080) if camera_id == 1 else (640, 480)
447
+ ),
448
+ "tracking_data": create_tracking_results(
449
+ num_tracks=random.randint(5, 15),
450
+ frames=random.randint(10, 25)
451
+ ),
452
+ "zones": create_zone_polygons([f"cam{camera_id}_zone_{i}" for i in range(3)]),
453
+ "metadata": {
454
+ "camera_id": camera_id,
455
+ "location": f"Location_{camera_id}",
456
+ "resolution": (1920, 1080) if camera_id == 1 else (640, 480)
457
+ }
458
+ }
459
+
460
+ return cameras
461
+
462
+
463
+ def create_temporal_data_series(duration_minutes: int = 60) -> List[Dict[str, Any]]:
464
+ """Create temporal data series for time-based analysis."""
465
+ data_series = []
466
+ frames_per_minute = 30 # Assuming 0.5 FPS for analysis
467
+ total_frames = duration_minutes * frames_per_minute
468
+
469
+ base_time = time.time()
470
+
471
+ for frame in range(total_frames):
472
+ timestamp = base_time + frame * 2 # 2 seconds per frame
473
+
474
+ # Simulate varying activity levels
475
+ hour = (frame // frames_per_minute) % 24
476
+ if 9 <= hour <= 17: # Business hours
477
+ activity_level = random.uniform(0.7, 1.0)
478
+ elif 6 <= hour <= 9 or 17 <= hour <= 20: # Rush hours
479
+ activity_level = random.uniform(0.5, 0.8)
480
+ else: # Off hours
481
+ activity_level = random.uniform(0.1, 0.4)
482
+
483
+ num_detections = int(20 * activity_level)
484
+
485
+ frame_data = {
486
+ "timestamp": timestamp,
487
+ "frame": frame,
488
+ "hour": hour,
489
+ "activity_level": activity_level,
490
+ "detections": create_detection_results(
491
+ num_detections=num_detections,
492
+ categories=["person", "vehicle"]
493
+ )
494
+ }
495
+
496
+ data_series.append(frame_data)
497
+
498
+ return data_series
499
+
500
+
501
+ def create_configuration_variants() -> Dict[str, Dict[str, Any]]:
502
+ """Create various configuration variants for testing."""
503
+ return {
504
+ "minimal_config": {
505
+ "confidence_threshold": 0.5
506
+ },
507
+ "full_people_counting": {
508
+ "confidence_threshold": 0.6,
509
+ "enable_tracking": True,
510
+ "enable_unique_counting": True,
511
+ "time_window_minutes": 30,
512
+ "person_categories": ["person", "people"],
513
+ "zone_config": {
514
+ "zones": create_zone_polygons(["entrance", "lobby", "exit"])
515
+ },
516
+ "alert_config": {
517
+ "count_thresholds": {"person": 50},
518
+ "occupancy_thresholds": {"lobby": 20}
519
+ }
520
+ },
521
+ "customer_service_config": {
522
+ "confidence_threshold": 0.7,
523
+ "enable_tracking": True,
524
+ "customer_categories": ["customer", "person"],
525
+ "staff_categories": ["staff", "employee"],
526
+ "service_proximity_threshold": 150.0,
527
+ "max_service_time": 600.0,
528
+ **create_customer_service_areas()
529
+ },
530
+ "high_performance_config": {
531
+ "confidence_threshold": 0.8,
532
+ "batch_size": 100,
533
+ "max_objects": 500,
534
+ "enable_analytics": False # Disable for performance
535
+ }
536
+ }
537
+
538
+
539
+ def create_result_format_variants() -> Dict[str, Dict[str, Any]]:
540
+ """Create test data in different result formats."""
541
+ base_detections = create_detection_results(10)
542
+ base_tracks = create_tracking_results(5, frames=8)
543
+
544
+ return {
545
+ "coco_format": {
546
+ "images": [{"id": 1, "width": 640, "height": 480, "file_name": "test.jpg"}],
547
+ "annotations": [
548
+ {
549
+ "id": i,
550
+ "image_id": 1,
551
+ "category_id": 1,
552
+ "bbox": det["bbox"],
553
+ "area": (det["bbox"][2] - det["bbox"][0]) * (det["bbox"][3] - det["bbox"][1]),
554
+ "iscrowd": 0,
555
+ "score": det["confidence"]
556
+ }
557
+ for i, det in enumerate(base_detections)
558
+ ],
559
+ "categories": [{"id": 1, "name": "person"}]
560
+ },
561
+ "yolo_format": [
562
+ {
563
+ "class": 0,
564
+ "confidence": det["confidence"],
565
+ "bbox": [
566
+ (det["bbox"][0] + det["bbox"][2]) / 2 / 640, # center_x normalized
567
+ (det["bbox"][1] + det["bbox"][3]) / 2 / 480, # center_y normalized
568
+ (det["bbox"][2] - det["bbox"][0]) / 640, # width normalized
569
+ (det["bbox"][3] - det["bbox"][1]) / 480 # height normalized
570
+ ]
571
+ }
572
+ for det in base_detections
573
+ ],
574
+ "tracking_format": base_tracks,
575
+ "custom_format": {
576
+ "detections": base_detections,
577
+ "metadata": {
578
+ "timestamp": time.time(),
579
+ "source": "test_camera",
580
+ "resolution": [640, 480]
581
+ }
582
+ }
583
+ }