matrice 1.0.99392__py3-none-any.whl → 1.0.99394__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matrice/deploy/utils/post_processing/usecases/vehicle_monitoring.py +159 -129
- {matrice-1.0.99392.dist-info → matrice-1.0.99394.dist-info}/METADATA +1 -1
- {matrice-1.0.99392.dist-info → matrice-1.0.99394.dist-info}/RECORD +6 -6
- {matrice-1.0.99392.dist-info → matrice-1.0.99394.dist-info}/WHEEL +0 -0
- {matrice-1.0.99392.dist-info → matrice-1.0.99394.dist-info}/licenses/LICENSE.txt +0 -0
- {matrice-1.0.99392.dist-info → matrice-1.0.99394.dist-info}/top_level.txt +0 -0
@@ -1,22 +1,24 @@
|
|
1
1
|
from typing import Any, Dict, List, Optional, Tuple
|
2
|
+
from dataclasses import asdict
|
2
3
|
import time
|
3
4
|
from datetime import datetime, timezone
|
4
5
|
|
5
|
-
from ..core.base import BaseProcessor, ProcessingContext, ProcessingResult, ConfigProtocol
|
6
|
+
from ..core.base import BaseProcessor, ProcessingContext, ProcessingResult, ConfigProtocol, ResultFormat
|
6
7
|
from ..utils import (
|
7
8
|
filter_by_confidence,
|
8
9
|
filter_by_categories,
|
9
10
|
apply_category_mapping,
|
10
11
|
count_objects_by_category,
|
11
12
|
count_objects_in_zones,
|
13
|
+
calculate_counting_summary,
|
12
14
|
match_results_structure,
|
13
15
|
bbox_smoothing,
|
14
16
|
BBoxSmoothingConfig,
|
15
17
|
BBoxSmoothingTracker
|
16
18
|
)
|
17
|
-
from ..utils.geometry_utils import point_in_polygon, get_bbox_bottom25_center
|
18
19
|
from dataclasses import dataclass, field
|
19
20
|
from ..core.config import BaseConfig, AlertConfig, ZoneConfig
|
21
|
+
from ..utils.geometry_utils import get_bbox_center, point_in_polygon, get_bbox_bottom25_center
|
20
22
|
|
21
23
|
@dataclass
|
22
24
|
class VehicleMonitoringConfig(BaseConfig):
|
@@ -30,24 +32,26 @@ class VehicleMonitoringConfig(BaseConfig):
|
|
30
32
|
zone_config: Optional[ZoneConfig] = None
|
31
33
|
usecase_categories: List[str] = field(
|
32
34
|
default_factory=lambda: [
|
33
|
-
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat"
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
,"baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
|
38
|
-
,"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich",
|
39
|
-
,"carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
|
40
|
-
,"dining table", "toilet", "tv", "laptop", "mouse", "remote",
|
41
|
-
|
42
|
-
,"teddy bear", "hair drier", "toothbrush"
|
35
|
+
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat",
|
36
|
+
"traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog",
|
37
|
+
"horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella",
|
38
|
+
"handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite",
|
39
|
+
"baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
|
40
|
+
"wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich",
|
41
|
+
"orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
|
42
|
+
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote",
|
43
|
+
"keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book",
|
44
|
+
"clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"
|
43
45
|
]
|
44
46
|
)
|
45
47
|
target_categories: List[str] = field(
|
46
|
-
default_factory=lambda: [
|
48
|
+
default_factory=lambda: [
|
49
|
+
'car', 'bicycle', 'bus', 'truck', 'motorcycle']
|
47
50
|
)
|
48
51
|
alert_config: Optional[AlertConfig] = None
|
49
52
|
index_to_category: Optional[Dict[int, str]] = field(
|
50
|
-
default_factory=lambda:{
|
53
|
+
default_factory=lambda: {
|
54
|
+
0: "person", 1: "bicycle", 2: "car", 3: "motorcycle", 4: "airplane", 5: "bus",
|
51
55
|
6: "train", 7: "truck", 8: "boat", 9: "traffic light", 10: "fire hydrant",
|
52
56
|
11: "stop sign", 12: "parking meter", 13: "bench", 14: "bird", 15: "cat",
|
53
57
|
16: "dog", 17: "horse", 18: "sheep", 19: "cow", 20: "elephant", 21: "bear",
|
@@ -62,7 +66,8 @@ class VehicleMonitoringConfig(BaseConfig):
|
|
62
66
|
62: "tv", 63: "laptop", 64: "mouse", 65: "remote", 66: "keyboard",
|
63
67
|
67: "cell phone", 68: "microwave", 69: "oven", 70: "toaster", 71: "sink",
|
64
68
|
72: "refrigerator", 73: "book", 74: "clock", 75: "vase", 76: "scissors",
|
65
|
-
77: "teddy bear", 78: "hair drier", 79: "toothbrush"
|
69
|
+
77: "teddy bear", 78: "hair drier", 79: "toothbrush"
|
70
|
+
}
|
66
71
|
)
|
67
72
|
|
68
73
|
class VehicleMonitoringUseCase(BaseProcessor):
|
@@ -82,7 +87,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
82
87
|
self.category = "traffic"
|
83
88
|
self.CASE_TYPE: Optional[str] = 'vehicle_monitoring'
|
84
89
|
self.CASE_VERSION: Optional[str] = '1.0'
|
85
|
-
self.target_categories = ['car', 'bicycle', 'bus', 'truck', '
|
90
|
+
self.target_categories = ['car', 'bicycle', 'bus', 'truck', 'motorcycle']
|
86
91
|
self.smoothing_tracker = None
|
87
92
|
self.tracker = None
|
88
93
|
self._total_frame_counter = 0
|
@@ -95,10 +100,22 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
95
100
|
self._ascending_alert_list: List[int] = []
|
96
101
|
self.current_incident_end_timestamp: str = "N/A"
|
97
102
|
self.start_timer = None
|
103
|
+
|
104
|
+
# Track ID storage for total count calculation
|
105
|
+
self._total_track_ids = set() # Store all unique track IDs seen across calls
|
106
|
+
self._current_frame_track_ids = set() # Store track IDs from current frame
|
107
|
+
self._total_count = 0 # Cached total count
|
108
|
+
self._last_update_time = time.time() # Track when last updated
|
109
|
+
|
110
|
+
# Zone-based tracking storage
|
111
|
+
self._zone_current_track_ids = {} # zone_name -> set of current track IDs in zone
|
112
|
+
self._zone_total_track_ids = {} # zone_name -> set of all track IDs that have been in zone
|
113
|
+
self._zone_current_counts = {} # zone_name -> current count in zone
|
114
|
+
self._zone_total_counts = {} # zone_name -> total count that have been in zone
|
98
115
|
|
99
116
|
def process(self, data: Any, config: ConfigProtocol, context: Optional[ProcessingContext] = None,
|
100
117
|
stream_info: Optional[Dict[str, Any]] = None) -> ProcessingResult:
|
101
|
-
|
118
|
+
start_time = time.time()
|
102
119
|
if not isinstance(config, VehicleMonitoringConfig):
|
103
120
|
return self.create_error_result("Invalid config type", usecase=self.name, category=self.category, context=context)
|
104
121
|
if context is None:
|
@@ -150,36 +167,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
150
167
|
except Exception as e:
|
151
168
|
self.logger.warning(f"AdvancedTracker failed: {e}")
|
152
169
|
|
153
|
-
|
154
|
-
detections_for_counting = processed_data
|
155
|
-
if getattr(config, 'zone_config', None) and getattr(config.zone_config, 'zones', None):
|
156
|
-
zones = config.zone_config.zones
|
157
|
-
in_zone_detections = []
|
158
|
-
for det in processed_data:
|
159
|
-
matched_zones = []
|
160
|
-
for zone_name, zone_polygon in zones.items():
|
161
|
-
if self._is_detection_in_zone(det, zone_polygon):
|
162
|
-
matched_zones.append(zone_name)
|
163
|
-
if matched_zones:
|
164
|
-
det_copy = dict(det)
|
165
|
-
det_copy['zones'] = matched_zones
|
166
|
-
in_zone_detections.append(det_copy)
|
167
|
-
detections_for_counting = in_zone_detections
|
168
|
-
|
169
|
-
self._update_tracking_state(detections_for_counting)
|
170
|
-
# Maintain cumulative per-zone unique track counts using canonicalized track_ids
|
171
|
-
if getattr(config, 'zone_config', None) and getattr(config.zone_config, 'zones', None):
|
172
|
-
if not hasattr(self, '_per_zone_total_track_ids'):
|
173
|
-
self._per_zone_total_track_ids = {}
|
174
|
-
for det in detections_for_counting:
|
175
|
-
track_id = det.get('track_id')
|
176
|
-
if track_id is None:
|
177
|
-
continue
|
178
|
-
category = det.get('category', 'unknown')
|
179
|
-
for zone_name in det.get('zones', []):
|
180
|
-
zone_map = self._per_zone_total_track_ids.setdefault(zone_name, {})
|
181
|
-
cat_set = zone_map.setdefault(category, set())
|
182
|
-
cat_set.add(track_id)
|
170
|
+
self._update_tracking_state(processed_data)
|
183
171
|
self._total_frame_counter += 1
|
184
172
|
|
185
173
|
frame_number = None
|
@@ -190,32 +178,41 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
190
178
|
if start_frame is not None and end_frame is not None and start_frame == end_frame:
|
191
179
|
frame_number = start_frame
|
192
180
|
|
193
|
-
|
194
|
-
|
195
|
-
if getattr(config, 'zone_config', None) and getattr(config.zone_config, 'zones', None):
|
196
|
-
try:
|
197
|
-
zone_counts = count_objects_in_zones(detections_for_counting, config.zone_config.zones)
|
198
|
-
except Exception as e:
|
199
|
-
self.logger.warning("Zone counting failed: %s", e)
|
200
|
-
counting_summary = self._count_categories(detections_for_counting, config)
|
181
|
+
general_counting_summary = calculate_counting_summary(data)
|
182
|
+
counting_summary = self._count_categories(processed_data, config)
|
201
183
|
total_counts = self.get_total_counts()
|
202
184
|
counting_summary['total_counts'] = total_counts
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
185
|
+
for detection in processed_data:
|
186
|
+
category = detection.get("category", "unknown")
|
187
|
+
counting_summary["categories"][category] = counting_summary["categories"].get(category, 0) + 1
|
188
|
+
|
189
|
+
zone_analysis = {}
|
190
|
+
if config.zone_config and config.zone_config.zones:
|
191
|
+
# Convert single frame to format expected by count_objects_in_zones
|
192
|
+
frame_data = processed_data #[frame_detections]
|
193
|
+
zone_analysis = count_objects_in_zones(frame_data, config.zone_config.zones)
|
194
|
+
|
195
|
+
# Update zone tracking with current frame data
|
196
|
+
if zone_analysis and config.enable_tracking:
|
197
|
+
enhanced_zone_analysis = self._update_zone_tracking(zone_analysis, processed_data, config)
|
198
|
+
# Merge enhanced zone analysis with original zone analysis
|
199
|
+
for zone_name, enhanced_data in enhanced_zone_analysis.items():
|
200
|
+
zone_analysis[zone_name] = enhanced_data
|
201
|
+
|
202
|
+
print("-----------------------------ZONEEEE-----------------------------------")
|
203
|
+
print(zone_analysis)
|
204
|
+
print("-----------------------------ZONEEEE-----------------------------------")
|
205
|
+
|
206
|
+
alerts = self._check_alerts(counting_summary,zone_analysis, frame_number, config)
|
207
|
+
predictions = self._extract_predictions(processed_data)
|
208
|
+
|
209
|
+
incidents_list = self._generate_incidents(counting_summary,zone_analysis, alerts, config, frame_number, stream_info)
|
210
|
+
tracking_stats_list = self._generate_tracking_stats(counting_summary,zone_analysis, alerts, config, frame_number, stream_info)
|
211
|
+
print("---------------------------TS--------------------------------------")
|
212
|
+
print(tracking_stats_list)
|
213
|
+
print("---------------------------TS--------------------------------------")
|
214
|
+
business_analytics_list = self._generate_business_analytics(counting_summary,zone_analysis, alerts, config, stream_info, is_empty=True)
|
215
|
+
summary_list = self._generate_summary(counting_summary,zone_analysis, incidents_list, tracking_stats_list, business_analytics_list, alerts)
|
219
216
|
|
220
217
|
incidents = incidents_list[0] if incidents_list else {}
|
221
218
|
tracking_stats = tracking_stats_list[0] if tracking_stats_list else {}
|
@@ -226,7 +223,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
226
223
|
"tracking_stats": tracking_stats,
|
227
224
|
"business_analytics": business_analytics,
|
228
225
|
"alerts": alerts,
|
229
|
-
"zone_analysis":
|
226
|
+
"zone_analysis": zone_analysis,
|
230
227
|
"human_text": summary}
|
231
228
|
}
|
232
229
|
|
@@ -239,6 +236,84 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
239
236
|
)
|
240
237
|
return result
|
241
238
|
|
239
|
+
def _update_zone_tracking(self, zone_analysis: Dict[str, Dict[str, int]], detections: List[Dict], config: VehicleMonitoringConfig) -> Dict[str, Dict[str, Any]]:
|
240
|
+
"""
|
241
|
+
Update zone tracking with current frame data.
|
242
|
+
|
243
|
+
Args:
|
244
|
+
zone_analysis: Current zone analysis results
|
245
|
+
detections: List of detections with track IDs
|
246
|
+
|
247
|
+
Returns:
|
248
|
+
Enhanced zone analysis with tracking information
|
249
|
+
"""
|
250
|
+
if not zone_analysis or not config.zone_config or not config.zone_config.zones:
|
251
|
+
return {}
|
252
|
+
|
253
|
+
enhanced_zone_analysis = {}
|
254
|
+
zones = config.zone_config.zones
|
255
|
+
|
256
|
+
# Get current frame track IDs in each zone
|
257
|
+
current_frame_zone_tracks = {}
|
258
|
+
|
259
|
+
# Initialize zone tracking for all zones
|
260
|
+
for zone_name in zones.keys():
|
261
|
+
current_frame_zone_tracks[zone_name] = set()
|
262
|
+
if zone_name not in self._zone_current_track_ids:
|
263
|
+
self._zone_current_track_ids[zone_name] = set()
|
264
|
+
if zone_name not in self._zone_total_track_ids:
|
265
|
+
self._zone_total_track_ids[zone_name] = set()
|
266
|
+
|
267
|
+
# Check each detection against each zone
|
268
|
+
for detection in detections:
|
269
|
+
track_id = detection.get("track_id")
|
270
|
+
if track_id is None:
|
271
|
+
continue
|
272
|
+
|
273
|
+
# Get detection bbox
|
274
|
+
bbox = detection.get("bounding_box", detection.get("bbox"))
|
275
|
+
if not bbox:
|
276
|
+
continue
|
277
|
+
|
278
|
+
# Get detection center point
|
279
|
+
center_point = get_bbox_bottom25_center(bbox) #get_bbox_center(bbox)
|
280
|
+
|
281
|
+
# Check which zone this detection is in using actual zone polygons
|
282
|
+
for zone_name, zone_polygon in zones.items():
|
283
|
+
# Convert polygon points to tuples for point_in_polygon function
|
284
|
+
# zone_polygon format: [[x1, y1], [x2, y2], [x3, y3], ...]
|
285
|
+
polygon_points = [(point[0], point[1]) for point in zone_polygon]
|
286
|
+
|
287
|
+
# Check if detection center is inside the zone polygon using ray casting algorithm
|
288
|
+
if point_in_polygon(center_point, polygon_points):
|
289
|
+
current_frame_zone_tracks[zone_name].add(track_id)
|
290
|
+
|
291
|
+
# Update zone tracking for each zone
|
292
|
+
for zone_name, zone_counts in zone_analysis.items():
|
293
|
+
# Get current frame tracks for this zone
|
294
|
+
current_tracks = current_frame_zone_tracks.get(zone_name, set())
|
295
|
+
|
296
|
+
# Update current zone tracks
|
297
|
+
self._zone_current_track_ids[zone_name] = current_tracks
|
298
|
+
|
299
|
+
# Update total zone tracks (accumulate all track IDs that have been in this zone)
|
300
|
+
self._zone_total_track_ids[zone_name].update(current_tracks)
|
301
|
+
|
302
|
+
# Update counts
|
303
|
+
self._zone_current_counts[zone_name] = len(current_tracks)
|
304
|
+
self._zone_total_counts[zone_name] = len(self._zone_total_track_ids[zone_name])
|
305
|
+
|
306
|
+
# Create enhanced zone analysis
|
307
|
+
enhanced_zone_analysis[zone_name] = {
|
308
|
+
"current_count": self._zone_current_counts[zone_name],
|
309
|
+
"total_count": self._zone_total_counts[zone_name],
|
310
|
+
"current_track_ids": list(current_tracks),
|
311
|
+
"total_track_ids": list(self._zone_total_track_ids[zone_name]),
|
312
|
+
"original_counts": zone_counts # Preserve original zone counts
|
313
|
+
}
|
314
|
+
|
315
|
+
return enhanced_zone_analysis
|
316
|
+
|
242
317
|
def _normalize_yolo_results(self, data: Any, index_to_category: Optional[Dict[int, str]] = None) -> Any:
|
243
318
|
"""
|
244
319
|
Normalize YOLO-style outputs to internal detection schema:
|
@@ -312,7 +387,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
312
387
|
return normalized_dict
|
313
388
|
return data
|
314
389
|
|
315
|
-
def _check_alerts(self, summary: dict, frame_number: Any, config: VehicleMonitoringConfig) -> List[Dict]:
|
390
|
+
def _check_alerts(self, summary: dict, zone_analysis: Dict, frame_number: Any, config: VehicleMonitoringConfig) -> List[Dict]:
|
316
391
|
def get_trend(data, lookback=900, threshold=0.6):
|
317
392
|
window = data[-lookback:] if len(data) >= lookback else data
|
318
393
|
if len(window) < 2:
|
@@ -345,7 +420,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
345
420
|
"threshold_level": threshold,
|
346
421
|
"ascending": get_trend(self._ascending_alert_list, lookback=900, threshold=0.8),
|
347
422
|
"settings": {t: v for t, v in zip(getattr(config.alert_config, 'alert_type', ['Default']),
|
348
|
-
|
423
|
+
getattr(config.alert_config, 'alert_value', ['JSON']))}
|
349
424
|
})
|
350
425
|
elif category in per_category_count and per_category_count[category] > threshold:
|
351
426
|
alerts.append({
|
@@ -355,12 +430,12 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
355
430
|
"threshold_level": threshold,
|
356
431
|
"ascending": get_trend(self._ascending_alert_list, lookback=900, threshold=0.8),
|
357
432
|
"settings": {t: v for t, v in zip(getattr(config.alert_config, 'alert_type', ['Default']),
|
358
|
-
|
433
|
+
getattr(config.alert_config, 'alert_value', ['JSON']))}
|
359
434
|
})
|
360
435
|
return alerts
|
361
436
|
|
362
|
-
def _generate_incidents(self, counting_summary: Dict, alerts: List, config: VehicleMonitoringConfig,
|
363
|
-
|
437
|
+
def _generate_incidents(self, counting_summary: Dict, zone_analysis: Dict, alerts: List, config: VehicleMonitoringConfig,
|
438
|
+
frame_number: Optional[int] = None, stream_info: Optional[Dict[str, Any]] = None) -> List[Dict]:
|
364
439
|
incidents = []
|
365
440
|
total_detections = counting_summary.get("total_count", 0)
|
366
441
|
current_timestamp = self._get_current_timestamp_str(stream_info)
|
@@ -446,7 +521,7 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
446
521
|
incidents.append({})
|
447
522
|
return incidents
|
448
523
|
|
449
|
-
def _generate_tracking_stats(self, counting_summary: Dict, alerts: List, config: VehicleMonitoringConfig,
|
524
|
+
def _generate_tracking_stats(self, counting_summary: Dict, zone_analysis: Dict, alerts: List, config: VehicleMonitoringConfig,
|
450
525
|
frame_number: Optional[int] = None, stream_info: Optional[Dict[str, Any]] = None) -> List[Dict]:
|
451
526
|
camera_info = self.get_camera_info_from_stream(stream_info)
|
452
527
|
tracking_stats = []
|
@@ -486,55 +561,17 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
486
561
|
"threshold_level": config.alert_config.count_thresholds if hasattr(config.alert_config, 'count_thresholds') else {},
|
487
562
|
"ascending": True,
|
488
563
|
"settings": {t: v for t, v in zip(getattr(config.alert_config, 'alert_type', ['Default']),
|
489
|
-
|
564
|
+
getattr(config.alert_config, 'alert_value', ['JSON']))}
|
490
565
|
})
|
491
566
|
|
492
567
|
human_text_lines = [f"Tracking Statistics:"]
|
493
568
|
human_text_lines.append(f"CURRENT FRAME @ {current_timestamp}")
|
494
569
|
for cat, count in per_category_count.items():
|
495
|
-
|
496
|
-
human_text_lines.append(f"\t{cat}: {count}")
|
497
|
-
else:
|
498
|
-
human_text_lines.append("No Detections in Frame")
|
499
|
-
# Append zone analysis for the current frame if available
|
500
|
-
zone_analysis = counting_summary.get("zone_analysis", {})
|
501
|
-
if zone_analysis:
|
502
|
-
human_text_lines.append("ZONE ANALYSIS (CURRENT FRAME):")
|
503
|
-
for zone_name, cat_counts in zone_analysis.items():
|
504
|
-
if isinstance(cat_counts, dict):
|
505
|
-
total_in_zone = sum(cat_counts.values())
|
506
|
-
car_count = (
|
507
|
-
cat_counts.get('car', 0)
|
508
|
-
+ cat_counts.get('truck', 0)
|
509
|
-
)
|
510
|
-
if car_count > 0:
|
511
|
-
human_text_lines.append(f"\t{zone_name}: total={total_in_zone} (car: {car_count})")
|
512
|
-
else:
|
513
|
-
human_text_lines.append(f"\t{zone_name}: total={total_in_zone}")
|
514
|
-
else:
|
515
|
-
human_text_lines.append(f"\t{zone_name}: total=0")
|
570
|
+
human_text_lines.append(f"\t{cat}: {count}")
|
516
571
|
human_text_lines.append(f"TOTAL SINCE {start_timestamp}")
|
517
572
|
for cat, count in total_counts_dict.items():
|
518
|
-
if
|
519
|
-
|
520
|
-
human_text_lines.append(f"\t{cat}: {count}")
|
521
|
-
# Append zone analysis totals across time if available
|
522
|
-
zone_analysis_total = counting_summary.get("zone_analysis_total", {})
|
523
|
-
if zone_analysis_total:
|
524
|
-
human_text_lines.append("ZONE ANALYSIS (TOTAL SINCE START):")
|
525
|
-
for zone_name, cat_counts in zone_analysis_total.items():
|
526
|
-
if isinstance(cat_counts, dict):
|
527
|
-
total_in_zone = sum(cat_counts.values())
|
528
|
-
car_count = (
|
529
|
-
cat_counts.get('car', 0)
|
530
|
-
+ cat_counts.get('truck', 0)
|
531
|
-
)
|
532
|
-
if car_count > 0:
|
533
|
-
human_text_lines.append(f"\t{zone_name}: total={total_in_zone} (car: {car_count})")
|
534
|
-
else:
|
535
|
-
human_text_lines.append(f"\t{zone_name}: total={total_in_zone}")
|
536
|
-
else:
|
537
|
-
human_text_lines.append(f"\t{zone_name}: total=0")
|
573
|
+
if count > 0:
|
574
|
+
human_text_lines.append(f"\t{cat}: {count}")
|
538
575
|
if alerts:
|
539
576
|
for alert in alerts:
|
540
577
|
human_text_lines.append(f"Alerts: {alert.get('settings', {})} sent @ {current_timestamp}")
|
@@ -558,12 +595,12 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
558
595
|
tracking_stats.append(tracking_stat)
|
559
596
|
return tracking_stats
|
560
597
|
|
561
|
-
def _generate_business_analytics(self, counting_summary: Dict, alerts: Any, config: VehicleMonitoringConfig,
|
598
|
+
def _generate_business_analytics(self, counting_summary: Dict, zone_analysis: Dict, alerts: Any, config: VehicleMonitoringConfig,
|
562
599
|
stream_info: Optional[Dict[str, Any]] = None, is_empty=False) -> List[Dict]:
|
563
600
|
if is_empty:
|
564
601
|
return []
|
565
602
|
|
566
|
-
def _generate_summary(self, summary: dict, incidents: List, tracking_stats: List, business_analytics: List, alerts: List) -> List[str]:
|
603
|
+
def _generate_summary(self, summary: dict, zone_analysis: Dict, incidents: List, tracking_stats: List, business_analytics: List, alerts: List) -> List[str]:
|
567
604
|
"""
|
568
605
|
Generate a human_text string for the tracking_stat, incident, business analytics and alerts.
|
569
606
|
"""
|
@@ -823,13 +860,6 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
823
860
|
union_area = area1 + area2 - inter_area
|
824
861
|
return (inter_area / union_area) if union_area > 0 else 0.0
|
825
862
|
|
826
|
-
def _is_detection_in_zone(self, detection: Dict[str, Any], zone_polygon: List[List[float]]) -> bool:
|
827
|
-
bbox = detection.get("bounding_box", detection.get("bbox"))
|
828
|
-
if not bbox:
|
829
|
-
return False
|
830
|
-
bottom25_center = get_bbox_bottom25_center(bbox)
|
831
|
-
return point_in_polygon(bottom25_center, [(p[0], p[1]) for p in zone_polygon])
|
832
|
-
|
833
863
|
def _merge_or_register_track(self, raw_id: Any, bbox: Any) -> Any:
|
834
864
|
if raw_id is None or bbox is None:
|
835
865
|
return raw_id
|
@@ -236,7 +236,7 @@ matrice/deploy/utils/post_processing/usecases/template_usecase.py,sha256=6NC-bTn
|
|
236
236
|
matrice/deploy/utils/post_processing/usecases/theft_detection.py,sha256=Rs_zKn2z9YM10fGzTHR44Q3m8TIO1s5UMdiPWA03rbA,28671
|
237
237
|
matrice/deploy/utils/post_processing/usecases/traffic_sign_monitoring.py,sha256=nDlEzHgMlUjy_VtJ7usnEzMcdSs-jouqaoJpJ8DYUMw,34351
|
238
238
|
matrice/deploy/utils/post_processing/usecases/underwater_pollution_detection.py,sha256=jqP1ZKfDZe2-56Lyvgb2DxnbqRfvxm6pPL0Ck3esfBk,40356
|
239
|
-
matrice/deploy/utils/post_processing/usecases/vehicle_monitoring.py,sha256
|
239
|
+
matrice/deploy/utils/post_processing/usecases/vehicle_monitoring.py,sha256=-TtvPEHShXlslhxpjSEGFEdeeP0zY-OYu635969K51I,45525
|
240
240
|
matrice/deploy/utils/post_processing/usecases/warehouse_object_segmentation.py,sha256=5uZXTJL_A3tUEN08T-_ZQpUoJ9gqbuuMc4z2mT4sMnQ,43753
|
241
241
|
matrice/deploy/utils/post_processing/usecases/waterbody_segmentation.py,sha256=JsCxDEMB8s4WDcezfJDr2zrjM-TCjB9hxOztzSvWmpY,45268
|
242
242
|
matrice/deploy/utils/post_processing/usecases/weapon_detection.py,sha256=gea-rjEHmP0hUjpcrcQIHOnhMMHQNqDI90cbpXHnlpI,31071
|
@@ -261,8 +261,8 @@ matrice/deployment/camera_manager.py,sha256=e1Lc81RJP5wUWRdTgHO6tMWF9BkBdHOSVyx3
|
|
261
261
|
matrice/deployment/deployment.py,sha256=HFt151eWq6iqIAMsQvurpV2WNxW6Cx_gIUVfnVy5SWE,48093
|
262
262
|
matrice/deployment/inference_pipeline.py,sha256=6b4Mm3-qt-Zy0BeiJfFQdImOn3FzdNCY-7ET7Rp8PMk,37911
|
263
263
|
matrice/deployment/streaming_gateway_manager.py,sha256=ifYGl3g25wyU39HwhPQyI2OgF3M6oIqKMWt8RXtMxY8,21401
|
264
|
-
matrice-1.0.
|
265
|
-
matrice-1.0.
|
266
|
-
matrice-1.0.
|
267
|
-
matrice-1.0.
|
268
|
-
matrice-1.0.
|
264
|
+
matrice-1.0.99394.dist-info/licenses/LICENSE.txt,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
265
|
+
matrice-1.0.99394.dist-info/METADATA,sha256=3bISm-l43QIoOwL2kjo_BTbUsV2TC-dCMaMPPNgRvdQ,14624
|
266
|
+
matrice-1.0.99394.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
267
|
+
matrice-1.0.99394.dist-info/top_level.txt,sha256=P97js8ur6o5ClRqMH3Cjoab_NqbJ6sOQ3rJmVzKBvMc,8
|
268
|
+
matrice-1.0.99394.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|