matrice-analytics 0.1.97__py3-none-any.whl → 0.1.124__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matrice_analytics/post_processing/__init__.py +22 -0
- matrice_analytics/post_processing/advanced_tracker/config.py +8 -4
- matrice_analytics/post_processing/advanced_tracker/track_class_aggregator.py +128 -0
- matrice_analytics/post_processing/advanced_tracker/tracker.py +22 -1
- matrice_analytics/post_processing/config.py +17 -2
- matrice_analytics/post_processing/core/config.py +107 -1
- matrice_analytics/post_processing/face_reg/face_recognition.py +706 -73
- matrice_analytics/post_processing/face_reg/people_activity_logging.py +25 -14
- matrice_analytics/post_processing/post_processor.py +16 -0
- matrice_analytics/post_processing/usecases/__init__.py +9 -0
- matrice_analytics/post_processing/usecases/crowdflow.py +1088 -0
- matrice_analytics/post_processing/usecases/footfall.py +170 -22
- matrice_analytics/post_processing/usecases/license_plate_monitoring.py +57 -38
- matrice_analytics/post_processing/usecases/parking_lot_analytics.py +1137 -0
- matrice_analytics/post_processing/usecases/vehicle_monitoring.py +30 -4
- matrice_analytics/post_processing/usecases/vehicle_monitoring_drone_view.py +246 -3
- matrice_analytics/post_processing/usecases/vehicle_monitoring_parking_lot.py +36 -3
- matrice_analytics/post_processing/usecases/vehicle_monitoring_wrong_way.py +1021 -0
- matrice_analytics/post_processing/utils/__init__.py +5 -0
- matrice_analytics/post_processing/utils/agnostic_nms.py +759 -0
- matrice_analytics/post_processing/utils/alert_instance_utils.py +55 -7
- matrice_analytics/post_processing/utils/business_metrics_manager_utils.py +25 -2
- matrice_analytics/post_processing/utils/incident_manager_utils.py +12 -1
- matrice_analytics/post_processing/utils/parking_analytics_tracker.py +359 -0
- matrice_analytics/post_processing/utils/wrong_way_tracker.py +670 -0
- {matrice_analytics-0.1.97.dist-info → matrice_analytics-0.1.124.dist-info}/METADATA +1 -1
- {matrice_analytics-0.1.97.dist-info → matrice_analytics-0.1.124.dist-info}/RECORD +30 -23
- {matrice_analytics-0.1.97.dist-info → matrice_analytics-0.1.124.dist-info}/WHEEL +0 -0
- {matrice_analytics-0.1.97.dist-info → matrice_analytics-0.1.124.dist-info}/licenses/LICENSE.txt +0 -0
- {matrice_analytics-0.1.97.dist-info → matrice_analytics-0.1.124.dist-info}/top_level.txt +0 -0
|
@@ -86,6 +86,7 @@ from .usecases.parking import ParkingConfig
|
|
|
86
86
|
from .usecases.abandoned_object_detection import AbandonedObjectConfig
|
|
87
87
|
from .usecases.footfall import FootFallConfig
|
|
88
88
|
from .usecases.vehicle_monitoring import VehicleMonitoringConfig
|
|
89
|
+
from .usecases.crowdflow import CrowdflowConfig
|
|
89
90
|
|
|
90
91
|
from .usecases.weld_defect_detection import WeldDefectConfig
|
|
91
92
|
from .usecases.weapon_detection import WeaponDetectionConfig
|
|
@@ -132,6 +133,9 @@ from .usecases.natural_disaster import NaturalDisasterConfig, NaturalDisasterUse
|
|
|
132
133
|
from .usecases.footfall import FootFallUseCase
|
|
133
134
|
from .usecases.vehicle_monitoring_parking_lot import VehicleMonitoringParkingLotUseCase, VehicleMonitoringParkingLotConfig
|
|
134
135
|
from .usecases.vehicle_monitoring_drone_view import VehicleMonitoringDroneViewUseCase, VehicleMonitoringDroneViewConfig
|
|
136
|
+
from .usecases.parking_lot_analytics import ParkingLotAnalyticsConfig, ParkingLotAnalyticsUseCase
|
|
137
|
+
from .usecases.vehicle_monitoring_wrong_way import VehicleMonitoringWrongWayConfig, VehicleMonitoringWrongWayUseCase
|
|
138
|
+
from .usecases.crowdflow import CrowdflowUseCase
|
|
135
139
|
|
|
136
140
|
#Put all IMAGE based usecases here
|
|
137
141
|
from .usecases.blood_cancer_detection_img import BloodCancerDetectionConfig, BloodCancerDetectionUseCase
|
|
@@ -212,6 +216,9 @@ from .usecases import (
|
|
|
212
216
|
FootFallUseCase,
|
|
213
217
|
VehicleMonitoringParkingLotUseCase,
|
|
214
218
|
VehicleMonitoringDroneViewUseCase,
|
|
219
|
+
ParkingLotAnalyticsUseCase,
|
|
220
|
+
VehicleMonitoringWrongWayUseCase,
|
|
221
|
+
CrowdflowUseCase,
|
|
215
222
|
|
|
216
223
|
#Put all IMAGE based usecases here
|
|
217
224
|
BloodCancerDetectionUseCase,
|
|
@@ -296,6 +303,9 @@ _natural_disaster = NaturalDisasterUseCase()
|
|
|
296
303
|
_footfall = FootFallUseCase()
|
|
297
304
|
_vehicle_monitoring_parking_lot = VehicleMonitoringParkingLotUseCase()
|
|
298
305
|
_vehicle_monitoring_drone_view = VehicleMonitoringDroneViewUseCase()
|
|
306
|
+
_parking_lot_analytics = ParkingLotAnalyticsUseCase()
|
|
307
|
+
_vehicle_monitoring_wrong_way = VehicleMonitoringWrongWayUseCase()
|
|
308
|
+
_crowdflow= CrowdflowUseCase()
|
|
299
309
|
|
|
300
310
|
# Face recognition with embeddings
|
|
301
311
|
_face_recognition = FaceRecognitionEmbeddingUseCase()
|
|
@@ -383,6 +393,9 @@ registry.register_use_case(_natural_disaster.category, _natural_disaster.name, N
|
|
|
383
393
|
registry.register_use_case(_footfall.category, _footfall.name, FaceEmotionUseCase)
|
|
384
394
|
registry.register_use_case(_vehicle_monitoring_parking_lot.category, _vehicle_monitoring_parking_lot.name, VehicleMonitoringParkingLotUseCase)
|
|
385
395
|
registry.register_use_case(_vehicle_monitoring_drone_view.category, _vehicle_monitoring_drone_view.name, VehicleMonitoringDroneViewUseCase)
|
|
396
|
+
registry.register_use_case(_parking_lot_analytics.category, _parking_lot_analytics.name, ParkingLotAnalyticsUseCase)
|
|
397
|
+
registry.register_use_case(_vehicle_monitoring_wrong_way.category, _vehicle_monitoring_wrong_way.name, VehicleMonitoringWrongWayUseCase)
|
|
398
|
+
registry.register_use_case(_crowdflow.category, _crowdflow.name, CrowdflowUseCase )
|
|
386
399
|
|
|
387
400
|
#Put all IMAGE based usecases here
|
|
388
401
|
registry.register_use_case(_blood_cancer_detection.category, _blood_cancer_detection.name, BloodCancerDetectionUseCase)
|
|
@@ -591,6 +604,10 @@ __all__ = [
|
|
|
591
604
|
'FootFallConfig',
|
|
592
605
|
'VehicleMonitoringParkingLotConfig',
|
|
593
606
|
'VehicleMonitoringDroneViewConfig',
|
|
607
|
+
'ParkingLotAnalyticsConfig',
|
|
608
|
+
'VehicleMonitoringWrongWayConfig',
|
|
609
|
+
|
|
610
|
+
'CrowdflowConfig'
|
|
594
611
|
#Put all IMAGE based usecase CONFIGS here
|
|
595
612
|
'BloodCancerDetectionConfig',
|
|
596
613
|
'SkinCancerClassificationConfig',
|
|
@@ -667,6 +684,9 @@ __all__ = [
|
|
|
667
684
|
'FootFallUseCase',
|
|
668
685
|
'VehicleMonitoringParkingLotUseCase',
|
|
669
686
|
'VehicleMonitoringDroneViewUseCase',
|
|
687
|
+
'ParkingLotAnalyticsUseCase',
|
|
688
|
+
'VehicleMonitoringWrongWayUseCase',
|
|
689
|
+
'CrowdflowUseCase'
|
|
670
690
|
|
|
671
691
|
#Put all IMAGE based usecases here
|
|
672
692
|
'BloodCancerDetectionUseCase',
|
|
@@ -729,6 +749,8 @@ __all__ = [
|
|
|
729
749
|
'detect_line_crossings',
|
|
730
750
|
'analyze_track_movements',
|
|
731
751
|
'filter_tracks_by_duration',
|
|
752
|
+
'ParkingAnalyticsTracker',
|
|
753
|
+
'WrongWayDetectionTracker',
|
|
732
754
|
|
|
733
755
|
# New utilities
|
|
734
756
|
'create_people_counting_config',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Configuration classes for advanced tracker.
|
|
3
|
-
|
|
4
3
|
This module provides configuration classes for the advanced tracker,
|
|
5
4
|
including parameters for tracking algorithms and thresholds.
|
|
6
5
|
"""
|
|
@@ -8,7 +7,6 @@ including parameters for tracking algorithms and thresholds.
|
|
|
8
7
|
from dataclasses import dataclass, field
|
|
9
8
|
from typing import Optional
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
@dataclass
|
|
13
11
|
class TrackerConfig:
|
|
14
12
|
"""
|
|
@@ -46,6 +44,10 @@ class TrackerConfig:
|
|
|
46
44
|
smoothing_window_size: int = 20
|
|
47
45
|
smoothing_cooldown_frames: int = 5
|
|
48
46
|
|
|
47
|
+
# Class aggregation settings
|
|
48
|
+
enable_class_aggregation: bool = False
|
|
49
|
+
class_aggregation_window_size: int = 30
|
|
50
|
+
|
|
49
51
|
def __post_init__(self):
|
|
50
52
|
"""Validate configuration parameters."""
|
|
51
53
|
if not 0.0 <= self.track_high_thresh <= 1.0:
|
|
@@ -72,6 +74,8 @@ class TrackerConfig:
|
|
|
72
74
|
if self.output_format not in ["tracking", "detection"]:
|
|
73
75
|
raise ValueError(f"Invalid output_format: {self.output_format}")
|
|
74
76
|
|
|
75
|
-
# Calculate max_time_lost if not explicitly set
|
|
76
77
|
if self.max_time_lost == 30: # Default value
|
|
77
|
-
self.max_time_lost = int(self.frame_rate / 30.0 * self.track_buffer)
|
|
78
|
+
self.max_time_lost = int(self.frame_rate / 30.0 * self.track_buffer)
|
|
79
|
+
|
|
80
|
+
if self.class_aggregation_window_size <= 0:
|
|
81
|
+
raise ValueError(f"class_aggregation_window_size must be positive, got {self.class_aggregation_window_size}")
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Track class aggregation for object tracking.
|
|
3
|
+
|
|
4
|
+
This module provides a sliding-window-based mechanism to aggregate class labels
|
|
5
|
+
across frames, reducing label flickering in tracking outputs through temporal voting.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict
|
|
9
|
+
from collections import deque, Counter
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TrackClassAggregator:
|
|
16
|
+
"""
|
|
17
|
+
Maintains per-track sliding windows of class labels and returns the most frequent.
|
|
18
|
+
|
|
19
|
+
This aggregator reduces class label flickering in tracking results by applying
|
|
20
|
+
temporal voting based on historical observations within a sliding window.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
window_size (int): Maximum number of frames to keep in the sliding window.
|
|
24
|
+
track_windows (Dict[int, deque]): Per-track sliding windows of class labels.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, window_size: int = 30):
|
|
28
|
+
"""
|
|
29
|
+
Initialize the TrackClassAggregator.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
window_size (int): Number of recent frames to consider for aggregation.
|
|
33
|
+
Must be positive. Larger windows provide more stability but slower
|
|
34
|
+
adaptation to genuine class changes.
|
|
35
|
+
"""
|
|
36
|
+
if window_size <= 0:
|
|
37
|
+
raise ValueError(f"window_size must be positive, got {window_size}")
|
|
38
|
+
|
|
39
|
+
self.window_size = window_size
|
|
40
|
+
self.track_windows: Dict[int, deque] = {}
|
|
41
|
+
|
|
42
|
+
def update_and_aggregate(self, track_id: int, observed_class: Any) -> Any:
|
|
43
|
+
"""
|
|
44
|
+
Update the sliding window for a track and return the aggregated class label.
|
|
45
|
+
|
|
46
|
+
This method:
|
|
47
|
+
1. Adds the new observation to the track's window
|
|
48
|
+
2. Maintains window size by removing oldest entries if needed
|
|
49
|
+
3. Returns the most frequent class in the window
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
track_id (int): Unique identifier for the track.
|
|
53
|
+
observed_class (Any): The class label observed in the current frame.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Any: The aggregated class label (most frequent in the window).
|
|
57
|
+
If there's a tie, returns the most recent among tied classes.
|
|
58
|
+
"""
|
|
59
|
+
# Initialize window for new tracks
|
|
60
|
+
if track_id not in self.track_windows:
|
|
61
|
+
self.track_windows[track_id] = deque(maxlen=self.window_size)
|
|
62
|
+
|
|
63
|
+
# Add current observation
|
|
64
|
+
window = self.track_windows[track_id]
|
|
65
|
+
window.append(observed_class)
|
|
66
|
+
|
|
67
|
+
# Return most frequent class
|
|
68
|
+
if len(window) == 0:
|
|
69
|
+
return observed_class
|
|
70
|
+
|
|
71
|
+
# Count frequencies and return most common
|
|
72
|
+
class_counts = Counter(window)
|
|
73
|
+
most_common = class_counts.most_common(1)[0][0]
|
|
74
|
+
|
|
75
|
+
return most_common
|
|
76
|
+
|
|
77
|
+
def get_aggregated_class(self, track_id: int, fallback_class: Any) -> Any:
|
|
78
|
+
"""
|
|
79
|
+
Get the aggregated class for a track without updating the window.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
track_id (int): Unique identifier for the track.
|
|
83
|
+
fallback_class (Any): Class to return if track has no history.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Any: The aggregated class label, or fallback_class if no history exists.
|
|
87
|
+
"""
|
|
88
|
+
if track_id not in self.track_windows:
|
|
89
|
+
return fallback_class
|
|
90
|
+
|
|
91
|
+
window = self.track_windows[track_id]
|
|
92
|
+
if len(window) == 0:
|
|
93
|
+
return fallback_class
|
|
94
|
+
|
|
95
|
+
class_counts = Counter(window)
|
|
96
|
+
return class_counts.most_common(1)[0][0]
|
|
97
|
+
|
|
98
|
+
def remove_track(self, track_id: int) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Remove a track's window from memory.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
track_id (int): Unique identifier for the track to remove.
|
|
104
|
+
"""
|
|
105
|
+
if track_id in self.track_windows:
|
|
106
|
+
del self.track_windows[track_id]
|
|
107
|
+
|
|
108
|
+
def remove_tracks(self, track_ids: list) -> None:
|
|
109
|
+
"""
|
|
110
|
+
Remove multiple tracks' windows from memory (batch operation).
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
track_ids (list): List of track IDs to remove.
|
|
114
|
+
"""
|
|
115
|
+
for track_id in track_ids:
|
|
116
|
+
self.remove_track(track_id)
|
|
117
|
+
|
|
118
|
+
def reset(self) -> None:
|
|
119
|
+
"""Clear all track windows."""
|
|
120
|
+
self.track_windows.clear()
|
|
121
|
+
|
|
122
|
+
def get_active_track_count(self) -> int:
|
|
123
|
+
"""Get the number of tracks currently being aggregated."""
|
|
124
|
+
return len(self.track_windows)
|
|
125
|
+
|
|
126
|
+
def __repr__(self) -> str:
|
|
127
|
+
"""String representation for debugging."""
|
|
128
|
+
return f"TrackClassAggregator(window_size={self.window_size}, active_tracks={len(self.track_windows)})"
|
|
@@ -34,6 +34,7 @@ class AdvancedTracker:
|
|
|
34
34
|
config (TrackerConfig): Tracker configuration.
|
|
35
35
|
max_time_lost (int): The maximum frames for a track to be considered as 'lost'.
|
|
36
36
|
kalman_filter (KalmanFilterXYAH): Kalman Filter object.
|
|
37
|
+
class_smoother (Optional[ClassSmoother]): Optional class smoother for class label smoothing over flicker.
|
|
37
38
|
"""
|
|
38
39
|
|
|
39
40
|
def __init__(self, config: TrackerConfig):
|
|
@@ -53,6 +54,11 @@ class AdvancedTracker:
|
|
|
53
54
|
self.kalman_filter = self.get_kalmanfilter()
|
|
54
55
|
self.reset_id()
|
|
55
56
|
|
|
57
|
+
self.class_aggregator = None
|
|
58
|
+
if config.enable_class_aggregation:
|
|
59
|
+
from .track_class_aggregator import TrackClassAggregator
|
|
60
|
+
self.class_aggregator = TrackClassAggregator(window_size=config.class_aggregation_window_size)
|
|
61
|
+
|
|
56
62
|
def update(self, detections: Union[List[Dict], Dict[str, List[Dict]]],
|
|
57
63
|
img: Optional[np.ndarray] = None) -> Union[List[Dict], Dict[str, List[Dict]]]:
|
|
58
64
|
"""
|
|
@@ -186,7 +192,15 @@ class AdvancedTracker:
|
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
detections.append(detection)
|
|
189
|
-
|
|
195
|
+
|
|
196
|
+
if self.class_aggregator is not None:
|
|
197
|
+
for detection in detections:
|
|
198
|
+
aggregated_class = self.class_aggregator.update_and_aggregate(
|
|
199
|
+
track_id=detection['track_id'],
|
|
200
|
+
observed_class=detection['category']
|
|
201
|
+
)
|
|
202
|
+
detection['category'] = aggregated_class
|
|
203
|
+
|
|
190
204
|
return detections
|
|
191
205
|
|
|
192
206
|
def _perform_tracking_update(self, detections: List[STrack],
|
|
@@ -296,6 +310,10 @@ class AdvancedTracker:
|
|
|
296
310
|
|
|
297
311
|
if len(self.removed_stracks) > 1000:
|
|
298
312
|
self.removed_stracks = self.removed_stracks[-999:]
|
|
313
|
+
|
|
314
|
+
# Clean up aggregator windows for removed tracks
|
|
315
|
+
if self.class_aggregator is not None and removed_stracks:
|
|
316
|
+
self.class_aggregator.remove_tracks([t.track_id for t in removed_stracks])
|
|
299
317
|
|
|
300
318
|
return [x for x in self.tracked_stracks if x.is_activated]
|
|
301
319
|
|
|
@@ -327,6 +345,9 @@ class AdvancedTracker:
|
|
|
327
345
|
self.frame_id = 0
|
|
328
346
|
self.kalman_filter = self.get_kalmanfilter()
|
|
329
347
|
self.reset_id()
|
|
348
|
+
|
|
349
|
+
if self.class_aggregator is not None:
|
|
350
|
+
self.class_aggregator.reset()
|
|
330
351
|
|
|
331
352
|
@staticmethod
|
|
332
353
|
def joint_stracks(tlista: List[STrack], tlistb: List[STrack]) -> List[STrack]:
|
|
@@ -7,6 +7,8 @@ APP_NAME_TO_USECASE = {
|
|
|
7
7
|
"pipeline_detection": "pipeline_detection",
|
|
8
8
|
"vehicle_monitoring": "vehicle_monitoring",
|
|
9
9
|
"Vehicle Type Monitoring": "vehicle_monitoring",
|
|
10
|
+
"Vehicle Monitoring": "vehicle_monitoring",
|
|
11
|
+
"vehicle-monitoring": "vehicle_monitoring",
|
|
10
12
|
"weapon_detection": "weapon_detection",
|
|
11
13
|
"traffic_sign_monitoring": "traffic_sign_monitoring",
|
|
12
14
|
"flare_analysis": "flare_analysis",
|
|
@@ -66,8 +68,14 @@ APP_NAME_TO_USECASE = {
|
|
|
66
68
|
"suspicious_activity_detection": "suspicious_activity_detection",
|
|
67
69
|
"natural_disaster_detection": "natural_disaster_detection",
|
|
68
70
|
"Foot Fall": "footfall",
|
|
71
|
+
"Crowdflow": "crowdflow",
|
|
72
|
+
"Parking Lot Vehicle Monitoring": "vehicle_monitoring_parking_lot",
|
|
69
73
|
"vehicle_monitoring_parking_lot": "vehicle_monitoring_parking_lot",
|
|
70
|
-
"
|
|
74
|
+
"Vehicle Monitoring Parking Lot": "vehicle_monitoring_parking_lot",
|
|
75
|
+
"Drone view vehicle monitoring": "vehicle_monitoring_drone_view",
|
|
76
|
+
"Parking Lot Analytics": "parking_lot_analytics",
|
|
77
|
+
"Vehicle Monitoring Wrong Way": "vehicle_monitoring_wrong_way",
|
|
78
|
+
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
APP_NAME_TO_CATEGORY = {
|
|
@@ -79,6 +87,8 @@ APP_NAME_TO_CATEGORY = {
|
|
|
79
87
|
"pipeline_detection": "pipeline_detection",
|
|
80
88
|
"vehicle_monitoring": "traffic",
|
|
81
89
|
"Vehicle Type Monitoring": "traffic",
|
|
90
|
+
"Vehicle Monitoring": "traffic",
|
|
91
|
+
"vehicle-monitoring": "traffic",
|
|
82
92
|
"weapon_detection": "security",
|
|
83
93
|
"traffic_sign_monitoring": "traffic",
|
|
84
94
|
"flare_analysis": "flare_detection",
|
|
@@ -139,8 +149,13 @@ APP_NAME_TO_CATEGORY = {
|
|
|
139
149
|
"suspicious_activity_detection": "security",
|
|
140
150
|
"natural_disaster_detection": "environmental",
|
|
141
151
|
"Foot Fall": "retail",
|
|
152
|
+
"Crowdflow": "retail",
|
|
153
|
+
"Parking Lot Vehicle Monitoring": "traffic",
|
|
142
154
|
"vehicle_monitoring_parking_lot": "traffic",
|
|
143
|
-
"
|
|
155
|
+
"Vehicle Monitoring Parking Lot": "traffic",
|
|
156
|
+
"Drone view vehicle monitoring": "traffic",
|
|
157
|
+
"Parking Lot Analytics": "traffic",
|
|
158
|
+
"Vehicle Monitoring Wrong Way": "traffic",
|
|
144
159
|
}
|
|
145
160
|
|
|
146
161
|
def get_usecase_from_app_name(app_name: str) -> str:
|
|
@@ -909,6 +909,9 @@ class ConfigManager:
|
|
|
909
909
|
'footfall': None,
|
|
910
910
|
'vehicle_monitoring_parking_lot': None,
|
|
911
911
|
'vehicle_monitoring_drone_view': None,
|
|
912
|
+
'parking_lot_analytics': None,
|
|
913
|
+
'vehicle_monitoring_wrong_way': None,
|
|
914
|
+
'crowdflow': None,
|
|
912
915
|
|
|
913
916
|
#Put all image based usecases here::
|
|
914
917
|
'blood_cancer_detection_img': None,
|
|
@@ -1438,6 +1441,31 @@ class ConfigManager:
|
|
|
1438
1441
|
except ImportError:
|
|
1439
1442
|
return None
|
|
1440
1443
|
|
|
1444
|
+
def parking_lot_analytics_config_class(self):
|
|
1445
|
+
"""Register a configuration class for a use case."""
|
|
1446
|
+
try:
|
|
1447
|
+
from ..usecases.parking_lot_analytics import ParkingLotAnalyticsConfig
|
|
1448
|
+
return ParkingLotAnalyticsConfig
|
|
1449
|
+
except ImportError:
|
|
1450
|
+
return None
|
|
1451
|
+
|
|
1452
|
+
def crowdflow_detection_config_class(self):
|
|
1453
|
+
"""Register a configuration class for a use case."""
|
|
1454
|
+
try:
|
|
1455
|
+
from ..usecases.crowdflow import CrowdflowConfig
|
|
1456
|
+
return CrowdflowConfig
|
|
1457
|
+
except ImportError:
|
|
1458
|
+
return None
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
def vehicle_monitoring_wrong_way_config_class(self):
|
|
1462
|
+
"""Register a configuration class for a use case."""
|
|
1463
|
+
try:
|
|
1464
|
+
from ..usecases.vehicle_monitoring_wrong_way import VehicleMonitoringWrongWayConfig
|
|
1465
|
+
return VehicleMonitoringWrongWayConfig
|
|
1466
|
+
except ImportError:
|
|
1467
|
+
return None
|
|
1468
|
+
|
|
1441
1469
|
#put all image based usecases here::
|
|
1442
1470
|
def blood_cancer_detection_config_class(self):
|
|
1443
1471
|
"""Register a configuration class for a use case."""
|
|
@@ -2041,15 +2069,27 @@ class ConfigManager:
|
|
|
2041
2069
|
from ..usecases.vehicle_monitoring import VehicleMonitoringConfig
|
|
2042
2070
|
|
|
2043
2071
|
# Handle nested configurations
|
|
2072
|
+
zone_config = kwargs.pop("zone_config", None)
|
|
2073
|
+
# VehicleMonitoringConfig expects zone_config as Dict, not ZoneConfig object
|
|
2074
|
+
# If it's a ZoneConfig object, convert it to dict
|
|
2075
|
+
if zone_config and hasattr(zone_config, 'to_dict'):
|
|
2076
|
+
zone_config = zone_config.to_dict()
|
|
2077
|
+
elif zone_config and isinstance(zone_config, ZoneConfig):
|
|
2078
|
+
zone_config = {"zones": zone_config.zones} if zone_config.zones else None
|
|
2079
|
+
|
|
2044
2080
|
alert_config = kwargs.pop("alert_config", None)
|
|
2045
2081
|
if alert_config and isinstance(alert_config, dict):
|
|
2046
2082
|
alert_config = AlertConfig(**alert_config)
|
|
2047
2083
|
|
|
2084
|
+
# Filter kwargs to only include valid parameters
|
|
2085
|
+
filtered_kwargs = self._filter_kwargs_for_config(VehicleMonitoringConfig, kwargs)
|
|
2086
|
+
|
|
2048
2087
|
config = VehicleMonitoringConfig(
|
|
2049
2088
|
category=category or "traffic",
|
|
2050
2089
|
usecase=usecase,
|
|
2090
|
+
zone_config=zone_config,
|
|
2051
2091
|
alert_config=alert_config,
|
|
2052
|
-
**
|
|
2092
|
+
**filtered_kwargs
|
|
2053
2093
|
)
|
|
2054
2094
|
|
|
2055
2095
|
elif usecase == "drone_traffic_monitoring":
|
|
@@ -2763,6 +2803,56 @@ class ConfigManager:
|
|
|
2763
2803
|
alert_config=alert_config,
|
|
2764
2804
|
**kwargs
|
|
2765
2805
|
)
|
|
2806
|
+
|
|
2807
|
+
elif usecase == "parking_lot_analytics":
|
|
2808
|
+
# Import here to avoid circular import
|
|
2809
|
+
from ..usecases.parking_lot_analytics import ParkingLotAnalyticsConfig
|
|
2810
|
+
|
|
2811
|
+
# Handle nested configurations
|
|
2812
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2813
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2814
|
+
alert_config = AlertConfig(**alert_config)
|
|
2815
|
+
|
|
2816
|
+
config = ParkingLotAnalyticsConfig(
|
|
2817
|
+
category=category or "traffic",
|
|
2818
|
+
usecase=usecase,
|
|
2819
|
+
alert_config=alert_config,
|
|
2820
|
+
**kwargs
|
|
2821
|
+
)
|
|
2822
|
+
|
|
2823
|
+
elif usecase == "crowdflow":
|
|
2824
|
+
# Import here to avoid circular import
|
|
2825
|
+
from ..usecases.crowdflow import CrowdflowConfig
|
|
2826
|
+
|
|
2827
|
+
# Handle nested configurations
|
|
2828
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2829
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2830
|
+
alert_config = AlertConfig(**alert_config)
|
|
2831
|
+
|
|
2832
|
+
config = CrowdflowConfig(
|
|
2833
|
+
category=category or "retail",
|
|
2834
|
+
usecase=usecase,
|
|
2835
|
+
alert_config=alert_config,
|
|
2836
|
+
**kwargs
|
|
2837
|
+
)
|
|
2838
|
+
|
|
2839
|
+
|
|
2840
|
+
elif usecase == "vehicle_monitoring_wrong_way":
|
|
2841
|
+
# Import here to avoid circular import
|
|
2842
|
+
from ..usecases.vehicle_monitoring_wrong_way import VehicleMonitoringWrongWayConfig
|
|
2843
|
+
|
|
2844
|
+
# Handle nested configurations
|
|
2845
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2846
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2847
|
+
alert_config = AlertConfig(**alert_config)
|
|
2848
|
+
|
|
2849
|
+
config = VehicleMonitoringWrongWayConfig(
|
|
2850
|
+
category=category or "traffic",
|
|
2851
|
+
usecase=usecase,
|
|
2852
|
+
alert_config=alert_config,
|
|
2853
|
+
**kwargs
|
|
2854
|
+
)
|
|
2855
|
+
|
|
2766
2856
|
|
|
2767
2857
|
#Add IMAGE based usecases here::
|
|
2768
2858
|
elif usecase == "blood_cancer_detection_img":
|
|
@@ -3333,6 +3423,22 @@ class ConfigManager:
|
|
|
3333
3423
|
default_config = VehicleMonitoringDroneViewConfig()
|
|
3334
3424
|
return default_config.to_dict()
|
|
3335
3425
|
|
|
3426
|
+
elif usecase == "parking_lot_analytics":
|
|
3427
|
+
# Import here to avoid circular import
|
|
3428
|
+
from ..usecases.parking_lot_analytics import ParkingLotAnalyticsConfig
|
|
3429
|
+
default_config = ParkingLotAnalyticsConfig()
|
|
3430
|
+
|
|
3431
|
+
elif usecase == "crowdflow":
|
|
3432
|
+
# Import here to avoid circular import
|
|
3433
|
+
from ..usecases.crowdflow import CrowdflowConfig
|
|
3434
|
+
default_config = CrowdflowConfig()
|
|
3435
|
+
return default_config.to_dict()
|
|
3436
|
+
|
|
3437
|
+
elif usecase == "vehicle_monitoring_wrong_way":
|
|
3438
|
+
# Import here to avoid circular import
|
|
3439
|
+
from ..usecases.vehicle_monitoring_wrong_way import VehicleMonitoringWrongWayConfig
|
|
3440
|
+
default_config = VehicleMonitoringWrongWayConfig()
|
|
3441
|
+
return default_config.to_dict()
|
|
3336
3442
|
|
|
3337
3443
|
elif usecase == "underground_pipeline_defect":
|
|
3338
3444
|
# Import here to avoid circular import
|