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.
- matrice_analytics/__init__.py +28 -0
- matrice_analytics/boundary_drawing_internal/README.md +305 -0
- matrice_analytics/boundary_drawing_internal/__init__.py +45 -0
- matrice_analytics/boundary_drawing_internal/boundary_drawing_internal.py +1207 -0
- matrice_analytics/boundary_drawing_internal/boundary_drawing_tool.py +429 -0
- matrice_analytics/boundary_drawing_internal/boundary_tool_template.html +1036 -0
- matrice_analytics/boundary_drawing_internal/data/.gitignore +12 -0
- matrice_analytics/boundary_drawing_internal/example_usage.py +206 -0
- matrice_analytics/boundary_drawing_internal/usage/README.md +110 -0
- matrice_analytics/boundary_drawing_internal/usage/boundary_drawer_launcher.py +102 -0
- matrice_analytics/boundary_drawing_internal/usage/simple_boundary_launcher.py +107 -0
- matrice_analytics/post_processing/README.md +455 -0
- matrice_analytics/post_processing/__init__.py +732 -0
- matrice_analytics/post_processing/advanced_tracker/README.md +650 -0
- matrice_analytics/post_processing/advanced_tracker/__init__.py +17 -0
- matrice_analytics/post_processing/advanced_tracker/base.py +99 -0
- matrice_analytics/post_processing/advanced_tracker/config.py +77 -0
- matrice_analytics/post_processing/advanced_tracker/kalman_filter.py +370 -0
- matrice_analytics/post_processing/advanced_tracker/matching.py +195 -0
- matrice_analytics/post_processing/advanced_tracker/strack.py +230 -0
- matrice_analytics/post_processing/advanced_tracker/tracker.py +367 -0
- matrice_analytics/post_processing/config.py +146 -0
- matrice_analytics/post_processing/core/__init__.py +63 -0
- matrice_analytics/post_processing/core/base.py +704 -0
- matrice_analytics/post_processing/core/config.py +3291 -0
- matrice_analytics/post_processing/core/config_utils.py +925 -0
- matrice_analytics/post_processing/face_reg/__init__.py +43 -0
- matrice_analytics/post_processing/face_reg/compare_similarity.py +556 -0
- matrice_analytics/post_processing/face_reg/embedding_manager.py +950 -0
- matrice_analytics/post_processing/face_reg/face_recognition.py +2234 -0
- matrice_analytics/post_processing/face_reg/face_recognition_client.py +606 -0
- matrice_analytics/post_processing/face_reg/people_activity_logging.py +321 -0
- matrice_analytics/post_processing/ocr/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/easyocr_extractor.py +250 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/__init__.py +9 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/__init__.py +4 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/cli.py +33 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/dataset_stats.py +139 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/export.py +398 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/train.py +447 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/utils.py +129 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/valid.py +93 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/validate_dataset.py +240 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_augmentation.py +176 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_predictions.py +96 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/__init__.py +3 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/process.py +246 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/types.py +60 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/utils.py +87 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/__init__.py +3 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/config.py +82 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/hub.py +141 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/plate_recognizer.py +323 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/py.typed +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/augmentation.py +101 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/dataset.py +97 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/config.py +114 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/layers.py +553 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/loss.py +55 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/metric.py +86 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_builders.py +95 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_schema.py +395 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/backend_utils.py +38 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/utils.py +214 -0
- matrice_analytics/post_processing/ocr/postprocessing.py +270 -0
- matrice_analytics/post_processing/ocr/preprocessing.py +52 -0
- matrice_analytics/post_processing/post_processor.py +1175 -0
- matrice_analytics/post_processing/test_cases/__init__.py +1 -0
- matrice_analytics/post_processing/test_cases/run_tests.py +143 -0
- matrice_analytics/post_processing/test_cases/test_advanced_customer_service.py +841 -0
- matrice_analytics/post_processing/test_cases/test_basic_counting_tracking.py +523 -0
- matrice_analytics/post_processing/test_cases/test_comprehensive.py +531 -0
- matrice_analytics/post_processing/test_cases/test_config.py +852 -0
- matrice_analytics/post_processing/test_cases/test_customer_service.py +585 -0
- matrice_analytics/post_processing/test_cases/test_data_generators.py +583 -0
- matrice_analytics/post_processing/test_cases/test_people_counting.py +510 -0
- matrice_analytics/post_processing/test_cases/test_processor.py +524 -0
- matrice_analytics/post_processing/test_cases/test_usecases.py +165 -0
- matrice_analytics/post_processing/test_cases/test_utilities.py +356 -0
- matrice_analytics/post_processing/test_cases/test_utils.py +743 -0
- matrice_analytics/post_processing/usecases/Histopathological_Cancer_Detection_img.py +604 -0
- matrice_analytics/post_processing/usecases/__init__.py +267 -0
- matrice_analytics/post_processing/usecases/abandoned_object_detection.py +797 -0
- matrice_analytics/post_processing/usecases/advanced_customer_service.py +1601 -0
- matrice_analytics/post_processing/usecases/age_detection.py +842 -0
- matrice_analytics/post_processing/usecases/age_gender_detection.py +1085 -0
- matrice_analytics/post_processing/usecases/anti_spoofing_detection.py +656 -0
- matrice_analytics/post_processing/usecases/assembly_line_detection.py +841 -0
- matrice_analytics/post_processing/usecases/banana_defect_detection.py +624 -0
- matrice_analytics/post_processing/usecases/basic_counting_tracking.py +667 -0
- matrice_analytics/post_processing/usecases/blood_cancer_detection_img.py +881 -0
- matrice_analytics/post_processing/usecases/car_damage_detection.py +834 -0
- matrice_analytics/post_processing/usecases/car_part_segmentation.py +946 -0
- matrice_analytics/post_processing/usecases/car_service.py +1601 -0
- matrice_analytics/post_processing/usecases/cardiomegaly_classification.py +864 -0
- matrice_analytics/post_processing/usecases/cell_microscopy_segmentation.py +897 -0
- matrice_analytics/post_processing/usecases/chicken_pose_detection.py +648 -0
- matrice_analytics/post_processing/usecases/child_monitoring.py +814 -0
- matrice_analytics/post_processing/usecases/color/clip.py +660 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/merges.txt +48895 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/preprocessor_config.json +28 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/special_tokens_map.json +30 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer.json +245079 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer_config.json +32 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/vocab.json +1 -0
- matrice_analytics/post_processing/usecases/color/color_map_utils.py +70 -0
- matrice_analytics/post_processing/usecases/color/color_mapper.py +468 -0
- matrice_analytics/post_processing/usecases/color_detection.py +1936 -0
- matrice_analytics/post_processing/usecases/color_map_utils.py +70 -0
- matrice_analytics/post_processing/usecases/concrete_crack_detection.py +827 -0
- matrice_analytics/post_processing/usecases/crop_weed_detection.py +781 -0
- matrice_analytics/post_processing/usecases/customer_service.py +1008 -0
- matrice_analytics/post_processing/usecases/defect_detection_products.py +936 -0
- matrice_analytics/post_processing/usecases/distracted_driver_detection.py +822 -0
- matrice_analytics/post_processing/usecases/drone_traffic_monitoring.py +585 -0
- matrice_analytics/post_processing/usecases/drowsy_driver_detection.py +829 -0
- matrice_analytics/post_processing/usecases/dwell_detection.py +829 -0
- matrice_analytics/post_processing/usecases/emergency_vehicle_detection.py +827 -0
- matrice_analytics/post_processing/usecases/face_emotion.py +813 -0
- matrice_analytics/post_processing/usecases/face_recognition.py +827 -0
- matrice_analytics/post_processing/usecases/fashion_detection.py +835 -0
- matrice_analytics/post_processing/usecases/field_mapping.py +902 -0
- matrice_analytics/post_processing/usecases/fire_detection.py +1146 -0
- matrice_analytics/post_processing/usecases/flare_analysis.py +836 -0
- matrice_analytics/post_processing/usecases/flower_segmentation.py +1006 -0
- matrice_analytics/post_processing/usecases/gas_leak_detection.py +837 -0
- matrice_analytics/post_processing/usecases/gender_detection.py +832 -0
- matrice_analytics/post_processing/usecases/human_activity_recognition.py +871 -0
- matrice_analytics/post_processing/usecases/intrusion_detection.py +1672 -0
- matrice_analytics/post_processing/usecases/leaf.py +821 -0
- matrice_analytics/post_processing/usecases/leaf_disease.py +840 -0
- matrice_analytics/post_processing/usecases/leak_detection.py +837 -0
- matrice_analytics/post_processing/usecases/license_plate_detection.py +1188 -0
- matrice_analytics/post_processing/usecases/license_plate_monitoring.py +1781 -0
- matrice_analytics/post_processing/usecases/litter_monitoring.py +717 -0
- matrice_analytics/post_processing/usecases/mask_detection.py +869 -0
- matrice_analytics/post_processing/usecases/natural_disaster.py +907 -0
- matrice_analytics/post_processing/usecases/parking.py +787 -0
- matrice_analytics/post_processing/usecases/parking_space_detection.py +822 -0
- matrice_analytics/post_processing/usecases/pcb_defect_detection.py +888 -0
- matrice_analytics/post_processing/usecases/pedestrian_detection.py +808 -0
- matrice_analytics/post_processing/usecases/people_counting.py +706 -0
- matrice_analytics/post_processing/usecases/people_counting_bckp.py +1683 -0
- matrice_analytics/post_processing/usecases/people_tracking.py +1842 -0
- matrice_analytics/post_processing/usecases/pipeline_detection.py +605 -0
- matrice_analytics/post_processing/usecases/plaque_segmentation_img.py +874 -0
- matrice_analytics/post_processing/usecases/pothole_segmentation.py +915 -0
- matrice_analytics/post_processing/usecases/ppe_compliance.py +645 -0
- matrice_analytics/post_processing/usecases/price_tag_detection.py +822 -0
- matrice_analytics/post_processing/usecases/proximity_detection.py +1901 -0
- matrice_analytics/post_processing/usecases/road_lane_detection.py +623 -0
- matrice_analytics/post_processing/usecases/road_traffic_density.py +832 -0
- matrice_analytics/post_processing/usecases/road_view_segmentation.py +915 -0
- matrice_analytics/post_processing/usecases/shelf_inventory_detection.py +583 -0
- matrice_analytics/post_processing/usecases/shoplifting_detection.py +822 -0
- matrice_analytics/post_processing/usecases/shopping_cart_analysis.py +899 -0
- matrice_analytics/post_processing/usecases/skin_cancer_classification_img.py +864 -0
- matrice_analytics/post_processing/usecases/smoker_detection.py +833 -0
- matrice_analytics/post_processing/usecases/solar_panel.py +810 -0
- matrice_analytics/post_processing/usecases/suspicious_activity_detection.py +1030 -0
- matrice_analytics/post_processing/usecases/template_usecase.py +380 -0
- matrice_analytics/post_processing/usecases/theft_detection.py +648 -0
- matrice_analytics/post_processing/usecases/traffic_sign_monitoring.py +724 -0
- matrice_analytics/post_processing/usecases/underground_pipeline_defect_detection.py +775 -0
- matrice_analytics/post_processing/usecases/underwater_pollution_detection.py +842 -0
- matrice_analytics/post_processing/usecases/vehicle_monitoring.py +1029 -0
- matrice_analytics/post_processing/usecases/warehouse_object_segmentation.py +899 -0
- matrice_analytics/post_processing/usecases/waterbody_segmentation.py +923 -0
- matrice_analytics/post_processing/usecases/weapon_detection.py +771 -0
- matrice_analytics/post_processing/usecases/weld_defect_detection.py +615 -0
- matrice_analytics/post_processing/usecases/wildlife_monitoring.py +898 -0
- matrice_analytics/post_processing/usecases/windmill_maintenance.py +834 -0
- matrice_analytics/post_processing/usecases/wound_segmentation.py +856 -0
- matrice_analytics/post_processing/utils/__init__.py +150 -0
- matrice_analytics/post_processing/utils/advanced_counting_utils.py +400 -0
- matrice_analytics/post_processing/utils/advanced_helper_utils.py +317 -0
- matrice_analytics/post_processing/utils/advanced_tracking_utils.py +461 -0
- matrice_analytics/post_processing/utils/alerting_utils.py +213 -0
- matrice_analytics/post_processing/utils/category_mapping_utils.py +94 -0
- matrice_analytics/post_processing/utils/color_utils.py +592 -0
- matrice_analytics/post_processing/utils/counting_utils.py +182 -0
- matrice_analytics/post_processing/utils/filter_utils.py +261 -0
- matrice_analytics/post_processing/utils/format_utils.py +293 -0
- matrice_analytics/post_processing/utils/geometry_utils.py +300 -0
- matrice_analytics/post_processing/utils/smoothing_utils.py +358 -0
- matrice_analytics/post_processing/utils/tracking_utils.py +234 -0
- matrice_analytics/py.typed +0 -0
- matrice_analytics-0.1.60.dist-info/METADATA +481 -0
- matrice_analytics-0.1.60.dist-info/RECORD +196 -0
- matrice_analytics-0.1.60.dist-info/WHEEL +5 -0
- matrice_analytics-0.1.60.dist-info/licenses/LICENSE.txt +21 -0
- matrice_analytics-0.1.60.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,3291 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration system for post-processing operations.
|
|
3
|
+
|
|
4
|
+
This module provides a clean, type-safe configuration system using dataclasses
|
|
5
|
+
with built-in validation, serialization support, and pythonic configuration management.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field, fields
|
|
9
|
+
from typing import Any, Dict, List, Optional, Union, get_type_hints
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import json
|
|
12
|
+
import yaml
|
|
13
|
+
import logging
|
|
14
|
+
from abc import ABC, abstractmethod
|
|
15
|
+
|
|
16
|
+
from .base import ConfigProtocol
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ConfigValidationError(Exception):
|
|
22
|
+
"""Raised when configuration validation fails."""
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class BaseConfig(ConfigProtocol):
|
|
28
|
+
"""Base configuration class with common functionality and validation."""
|
|
29
|
+
|
|
30
|
+
# Core identification
|
|
31
|
+
category: str = ""
|
|
32
|
+
usecase: str = ""
|
|
33
|
+
|
|
34
|
+
# Common processing parameters
|
|
35
|
+
confidence_threshold: Optional[float] = 0.5
|
|
36
|
+
enable_tracking: bool = False
|
|
37
|
+
enable_analytics: bool = True
|
|
38
|
+
|
|
39
|
+
# Performance settings
|
|
40
|
+
batch_size: Optional[int] = None
|
|
41
|
+
max_objects: Optional[int] = 1000
|
|
42
|
+
|
|
43
|
+
# Additional parameters
|
|
44
|
+
extra_params: Dict[str, Any] = field(default_factory=dict)
|
|
45
|
+
|
|
46
|
+
def validate(self) -> List[str]:
|
|
47
|
+
"""Validate configuration and return list of error messages."""
|
|
48
|
+
errors = []
|
|
49
|
+
|
|
50
|
+
# Validate confidence threshold
|
|
51
|
+
if self.confidence_threshold is not None:
|
|
52
|
+
if not 0.0 <= self.confidence_threshold <= 1.0:
|
|
53
|
+
errors.append("confidence_threshold must be between 0.0 and 1.0")
|
|
54
|
+
|
|
55
|
+
# Validate max_objects
|
|
56
|
+
if self.max_objects is not None and self.max_objects <= 0:
|
|
57
|
+
errors.append("max_objects must be positive")
|
|
58
|
+
|
|
59
|
+
# Validate batch_size
|
|
60
|
+
if self.batch_size is not None and self.batch_size <= 0:
|
|
61
|
+
errors.append("batch_size must be positive")
|
|
62
|
+
|
|
63
|
+
return errors
|
|
64
|
+
|
|
65
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
66
|
+
"""Convert to dictionary for serialization."""
|
|
67
|
+
result = {}
|
|
68
|
+
|
|
69
|
+
# Get all fields
|
|
70
|
+
for field_info in fields(self):
|
|
71
|
+
value = getattr(self, field_info.name)
|
|
72
|
+
if value is not None:
|
|
73
|
+
# Handle nested configs
|
|
74
|
+
if hasattr(value, 'to_dict'):
|
|
75
|
+
result[field_info.name] = value.to_dict()
|
|
76
|
+
elif isinstance(value, dict):
|
|
77
|
+
# Handle dictionaries with potential nested configs
|
|
78
|
+
nested_dict = {}
|
|
79
|
+
for k, v in value.items():
|
|
80
|
+
if hasattr(v, 'to_dict'):
|
|
81
|
+
nested_dict[k] = v.to_dict()
|
|
82
|
+
else:
|
|
83
|
+
nested_dict[k] = v
|
|
84
|
+
result[field_info.name] = nested_dict
|
|
85
|
+
else:
|
|
86
|
+
result[field_info.name] = value
|
|
87
|
+
|
|
88
|
+
# Merge extra_params at top level
|
|
89
|
+
if self.extra_params:
|
|
90
|
+
result.update(self.extra_params)
|
|
91
|
+
|
|
92
|
+
return result
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'BaseConfig':
|
|
96
|
+
"""Create config from dictionary with type conversion."""
|
|
97
|
+
# Get field names and types for this class
|
|
98
|
+
field_names = {f.name: f.type for f in fields(cls)}
|
|
99
|
+
|
|
100
|
+
# Separate known fields from extra parameters
|
|
101
|
+
known_params = {}
|
|
102
|
+
extra_params = {}
|
|
103
|
+
|
|
104
|
+
for k, v in data.items():
|
|
105
|
+
if k in field_names:
|
|
106
|
+
known_params[k] = v
|
|
107
|
+
else:
|
|
108
|
+
extra_params[k] = v
|
|
109
|
+
|
|
110
|
+
if extra_params:
|
|
111
|
+
known_params['extra_params'] = extra_params
|
|
112
|
+
|
|
113
|
+
return cls(**known_params)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class ZoneConfig:
|
|
118
|
+
"""Configuration for zone-based processing."""
|
|
119
|
+
|
|
120
|
+
# Zone definitions (name -> polygon points)
|
|
121
|
+
zones: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
122
|
+
|
|
123
|
+
# Zone-specific settings
|
|
124
|
+
zone_confidence_thresholds: Dict[str, float] = field(default_factory=dict)
|
|
125
|
+
zone_categories: Dict[str, List[str]] = field(default_factory=dict)
|
|
126
|
+
|
|
127
|
+
def validate(self) -> List[str]:
|
|
128
|
+
"""Validate zone configuration."""
|
|
129
|
+
errors = []
|
|
130
|
+
|
|
131
|
+
for zone_name, polygon in self.zones.items():
|
|
132
|
+
if len(polygon) < 3:
|
|
133
|
+
errors.append(f"Zone '{zone_name}' must have at least 3 points")
|
|
134
|
+
|
|
135
|
+
for i, point in enumerate(polygon):
|
|
136
|
+
if len(point) != 2:
|
|
137
|
+
errors.append(f"Zone '{zone_name}' point {i} must have exactly 2 coordinates")
|
|
138
|
+
|
|
139
|
+
# Validate zone confidence thresholds
|
|
140
|
+
for zone_name, threshold in self.zone_confidence_thresholds.items():
|
|
141
|
+
if zone_name not in self.zones:
|
|
142
|
+
errors.append(f"Zone confidence threshold defined for unknown zone '{zone_name}'")
|
|
143
|
+
if not 0.0 <= threshold <= 1.0:
|
|
144
|
+
errors.append(f"Zone '{zone_name}' confidence threshold must be between 0.0 and 1.0")
|
|
145
|
+
|
|
146
|
+
return errors
|
|
147
|
+
|
|
148
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
149
|
+
"""Convert to dictionary."""
|
|
150
|
+
return {
|
|
151
|
+
"zones": self.zones,
|
|
152
|
+
"zone_confidence_thresholds": self.zone_confidence_thresholds,
|
|
153
|
+
"zone_categories": self.zone_categories
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# --- Legacy/dict-like compatibility helpers ---
|
|
157
|
+
def _as_legacy_dict(self) -> Dict[str, Any]:
|
|
158
|
+
return {
|
|
159
|
+
"zones": self.zones,
|
|
160
|
+
"zone_confidence_thresholds": self.zone_confidence_thresholds,
|
|
161
|
+
"zone_categories": self.zone_categories,
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
def __getitem__(self, key: str) -> Any: # Support config.zone_config['zones']
|
|
165
|
+
return self._as_legacy_dict()[key]
|
|
166
|
+
|
|
167
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
168
|
+
return self._as_legacy_dict().get(key, default)
|
|
169
|
+
|
|
170
|
+
def keys(self):
|
|
171
|
+
return self._as_legacy_dict().keys()
|
|
172
|
+
|
|
173
|
+
def items(self):
|
|
174
|
+
return self._as_legacy_dict().items()
|
|
175
|
+
|
|
176
|
+
def __contains__(self, key: object) -> bool:
|
|
177
|
+
return key in self._as_legacy_dict()
|
|
178
|
+
|
|
179
|
+
def __iter__(self):
|
|
180
|
+
return iter(self._as_legacy_dict())
|
|
181
|
+
|
|
182
|
+
def __len__(self) -> int:
|
|
183
|
+
return len(self._as_legacy_dict())
|
|
184
|
+
|
|
185
|
+
@dataclass
|
|
186
|
+
class TrackingConfig:
|
|
187
|
+
"""Configuration for tracking operations."""
|
|
188
|
+
|
|
189
|
+
# Tracking method and parameters
|
|
190
|
+
tracking_method: str = "kalman"
|
|
191
|
+
max_age: int = 30
|
|
192
|
+
min_hits: int = 3
|
|
193
|
+
iou_threshold: float = 0.3
|
|
194
|
+
|
|
195
|
+
# Target classes for tracking
|
|
196
|
+
target_classes: List[str] = field(default_factory=list)
|
|
197
|
+
|
|
198
|
+
# Advanced tracking settings
|
|
199
|
+
use_appearance_features: bool = False
|
|
200
|
+
appearance_threshold: float = 0.7
|
|
201
|
+
|
|
202
|
+
def validate(self) -> List[str]:
|
|
203
|
+
"""Validate tracking configuration."""
|
|
204
|
+
errors = []
|
|
205
|
+
|
|
206
|
+
valid_methods = ["kalman", "sort", "deepsort", "bytetrack"]
|
|
207
|
+
if self.tracking_method not in valid_methods:
|
|
208
|
+
errors.append(f"tracking_method must be one of {valid_methods}")
|
|
209
|
+
|
|
210
|
+
if self.max_age <= 0:
|
|
211
|
+
errors.append("max_age must be positive")
|
|
212
|
+
|
|
213
|
+
if self.min_hits <= 0:
|
|
214
|
+
errors.append("min_hits must be positive")
|
|
215
|
+
|
|
216
|
+
if not 0.0 <= self.iou_threshold <= 1.0:
|
|
217
|
+
errors.append("iou_threshold must be between 0.0 and 1.0")
|
|
218
|
+
|
|
219
|
+
if not 0.0 <= self.appearance_threshold <= 1.0:
|
|
220
|
+
errors.append("appearance_threshold must be between 0.0 and 1.0")
|
|
221
|
+
|
|
222
|
+
return errors
|
|
223
|
+
|
|
224
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
225
|
+
"""Convert to dictionary."""
|
|
226
|
+
return {
|
|
227
|
+
"tracking_method": self.tracking_method,
|
|
228
|
+
"max_age": self.max_age,
|
|
229
|
+
"min_hits": self.min_hits,
|
|
230
|
+
"iou_threshold": self.iou_threshold,
|
|
231
|
+
"target_classes": self.target_classes,
|
|
232
|
+
"use_appearance_features": self.use_appearance_features,
|
|
233
|
+
"appearance_threshold": self.appearance_threshold
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@dataclass
|
|
238
|
+
class AlertConfig:
|
|
239
|
+
"""Configuration for alerting system."""
|
|
240
|
+
|
|
241
|
+
# Threshold-based alerts
|
|
242
|
+
count_thresholds: Dict[str, int] = field(default_factory=dict)
|
|
243
|
+
occupancy_thresholds: Dict[str, int] = field(default_factory=dict)
|
|
244
|
+
|
|
245
|
+
# Time-based alerts
|
|
246
|
+
dwell_time_threshold: Optional[float] = None
|
|
247
|
+
service_time_threshold: Optional[float] = None
|
|
248
|
+
|
|
249
|
+
# Alert settings
|
|
250
|
+
alert_cooldown: float = 60.0 # seconds
|
|
251
|
+
|
|
252
|
+
# enable_webhook_alerts: bool = False
|
|
253
|
+
# webhook_url: Optional[str] = None
|
|
254
|
+
# enable_email_alerts: bool = False
|
|
255
|
+
# email_recipients: List[str] = field(default_factory=list)
|
|
256
|
+
|
|
257
|
+
alert_type: List[str] = field(default_factory=lambda: ['Default']) #webhook, email, sms, slack, telegram, whatsapp, etc.
|
|
258
|
+
alert_value: List[str] = field(default_factory=lambda: ['JSON']) #webhook_url, email_recipients, etc.
|
|
259
|
+
alert_incident_category: List[str] = field(default_factory=lambda: ['Incident Alert'])
|
|
260
|
+
#alert_settings: Optional[Dict[str, Any]] = {alert_type: None}
|
|
261
|
+
|
|
262
|
+
def validate(self) -> List[str]:
|
|
263
|
+
"""Validate alert configuration."""
|
|
264
|
+
errors = []
|
|
265
|
+
|
|
266
|
+
# Validate thresholds are positive
|
|
267
|
+
for category, threshold in self.count_thresholds.items():
|
|
268
|
+
if threshold <= 0:
|
|
269
|
+
errors.append(f"Count threshold for '{category}' must be positive")
|
|
270
|
+
|
|
271
|
+
for zone, threshold in self.occupancy_thresholds.items():
|
|
272
|
+
if threshold <= 0:
|
|
273
|
+
errors.append(f"Occupancy threshold for zone '{zone}' must be positive")
|
|
274
|
+
|
|
275
|
+
# Validate time thresholds
|
|
276
|
+
if self.dwell_time_threshold is not None and self.dwell_time_threshold <= 0:
|
|
277
|
+
errors.append("dwell_time_threshold must be positive")
|
|
278
|
+
|
|
279
|
+
if self.service_time_threshold is not None and self.service_time_threshold <= 0:
|
|
280
|
+
errors.append("service_time_threshold must be positive")
|
|
281
|
+
|
|
282
|
+
if self.alert_cooldown <= 0:
|
|
283
|
+
errors.append("alert_cooldown must be positive")
|
|
284
|
+
|
|
285
|
+
if len(self.alert_incident_category)!=len(self.alert_type) or len(self.alert_incident_category)!=len(self.alert_value):
|
|
286
|
+
errors.append("Details for all alerts is required")
|
|
287
|
+
|
|
288
|
+
if self.alert_type[0]!='Default':
|
|
289
|
+
for i in range(len(self.alert_type)):
|
|
290
|
+
normalized = self.alert_type[i].lower()
|
|
291
|
+
# Validate webhook settings
|
|
292
|
+
if normalized=="webhook" and not self.alert_value:
|
|
293
|
+
errors.append("webhook_url is required")
|
|
294
|
+
|
|
295
|
+
elif normalized=="email" and not self.alert_value:
|
|
296
|
+
errors.append("email_recipients is required")
|
|
297
|
+
|
|
298
|
+
elif normalized=="phone" and not self.alert_value:
|
|
299
|
+
errors.append("phone_number is required")
|
|
300
|
+
if len(self.alert_type)==1 and self.alert_type[0]=='Default':
|
|
301
|
+
self.alert_value=["JSON"]
|
|
302
|
+
|
|
303
|
+
return errors
|
|
304
|
+
|
|
305
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
306
|
+
"""Convert to dictionary."""
|
|
307
|
+
return {
|
|
308
|
+
"count_thresholds": self.count_thresholds,
|
|
309
|
+
"occupancy_thresholds": self.occupancy_thresholds,
|
|
310
|
+
"dwell_time_threshold": self.dwell_time_threshold,
|
|
311
|
+
"service_time_threshold": self.service_time_threshold,
|
|
312
|
+
"alert_cooldown": self.alert_cooldown,
|
|
313
|
+
"alert_type": self.alert_type,
|
|
314
|
+
"alert_value": self.alert_value
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
# --- Legacy/dict-like compatibility helpers ---
|
|
318
|
+
def _as_legacy_dict(self) -> Dict[str, Any]:
|
|
319
|
+
return {
|
|
320
|
+
"count_thresholds": self.count_thresholds,
|
|
321
|
+
"occupancy_thresholds": self.occupancy_thresholds,
|
|
322
|
+
"dwell_time_threshold": self.dwell_time_threshold,
|
|
323
|
+
"service_time_threshold": self.service_time_threshold,
|
|
324
|
+
"alert_cooldown": self.alert_cooldown,
|
|
325
|
+
"alert_type": self.alert_type,
|
|
326
|
+
"alert_value": self.alert_value,
|
|
327
|
+
"alert_incident_category": self.alert_incident_category,
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
def __getitem__(self, key: str) -> Any:
|
|
331
|
+
return self._as_legacy_dict()[key]
|
|
332
|
+
|
|
333
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
334
|
+
return self._as_legacy_dict().get(key, default)
|
|
335
|
+
|
|
336
|
+
def keys(self):
|
|
337
|
+
return self._as_legacy_dict().keys()
|
|
338
|
+
|
|
339
|
+
def items(self):
|
|
340
|
+
return self._as_legacy_dict().items()
|
|
341
|
+
|
|
342
|
+
def __contains__(self, key: object) -> bool:
|
|
343
|
+
return key in self._as_legacy_dict()
|
|
344
|
+
|
|
345
|
+
def __iter__(self):
|
|
346
|
+
return iter(self._as_legacy_dict())
|
|
347
|
+
|
|
348
|
+
def __len__(self) -> int:
|
|
349
|
+
return len(self._as_legacy_dict())
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@dataclass
|
|
353
|
+
class PeopleCountingConfig(BaseConfig):
|
|
354
|
+
"""Configuration for people counting use case."""
|
|
355
|
+
|
|
356
|
+
# Smoothing configuration
|
|
357
|
+
enable_smoothing: bool = True
|
|
358
|
+
smoothing_algorithm: str = "observability" # "window" or "observability"
|
|
359
|
+
smoothing_window_size: int = 20
|
|
360
|
+
smoothing_cooldown_frames: int = 5
|
|
361
|
+
smoothing_confidence_range_factor: float = 0.5
|
|
362
|
+
|
|
363
|
+
# Zone configuration
|
|
364
|
+
zone_config: Optional[ZoneConfig] = None
|
|
365
|
+
|
|
366
|
+
# Counting parameters
|
|
367
|
+
enable_unique_counting: bool = True
|
|
368
|
+
time_window_minutes: int = 60
|
|
369
|
+
|
|
370
|
+
# Category mapping
|
|
371
|
+
person_categories: List[str] = field(default_factory=lambda: ["person", "people"])
|
|
372
|
+
index_to_category: Optional[Dict[int, str]] = None
|
|
373
|
+
|
|
374
|
+
# Alert configuration
|
|
375
|
+
alert_config: Optional[AlertConfig] = None
|
|
376
|
+
|
|
377
|
+
target_categories: List[str] = field(
|
|
378
|
+
default_factory=lambda: [
|
|
379
|
+
'person', 'people', 'human', 'man', 'woman', 'male', 'female']
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
def validate(self) -> List[str]:
|
|
383
|
+
"""Validate people counting configuration."""
|
|
384
|
+
errors = super().validate()
|
|
385
|
+
|
|
386
|
+
if self.time_window_minutes <= 0:
|
|
387
|
+
errors.append("time_window_minutes must be positive")
|
|
388
|
+
|
|
389
|
+
if not self.person_categories:
|
|
390
|
+
errors.append("person_categories cannot be empty")
|
|
391
|
+
|
|
392
|
+
# Validate nested configurations
|
|
393
|
+
if self.zone_config:
|
|
394
|
+
errors.extend(self.zone_config.validate())
|
|
395
|
+
|
|
396
|
+
if self.alert_config:
|
|
397
|
+
errors.extend(self.alert_config.validate())
|
|
398
|
+
|
|
399
|
+
return errors
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@dataclass
|
|
403
|
+
class IntrusionConfig(BaseConfig):
|
|
404
|
+
"""Configuration for intrusion detection use case."""
|
|
405
|
+
|
|
406
|
+
# Smoothing configuration
|
|
407
|
+
enable_smoothing: bool = True
|
|
408
|
+
smoothing_algorithm: str = "observability" # "window" or "observability"
|
|
409
|
+
smoothing_window_size: int = 20
|
|
410
|
+
smoothing_cooldown_frames: int = 5
|
|
411
|
+
smoothing_confidence_range_factor: float = 0.5
|
|
412
|
+
|
|
413
|
+
# Zone configuration
|
|
414
|
+
zone_config: Optional[ZoneConfig] = None
|
|
415
|
+
|
|
416
|
+
# Counting parameters
|
|
417
|
+
enable_unique_counting: bool = True
|
|
418
|
+
time_window_minutes: int = 60
|
|
419
|
+
|
|
420
|
+
# Category mapping
|
|
421
|
+
person_categories: List[str] = field(default_factory=lambda: ["person"])
|
|
422
|
+
index_to_category: Optional[Dict[int, str]] = None
|
|
423
|
+
|
|
424
|
+
# Alert configuration
|
|
425
|
+
alert_config: Optional[AlertConfig] = None
|
|
426
|
+
|
|
427
|
+
def validate(self) -> List[str]:
|
|
428
|
+
"""Validate intrusion detection configuration."""
|
|
429
|
+
errors = super().validate()
|
|
430
|
+
|
|
431
|
+
if self.time_window_minutes <= 0:
|
|
432
|
+
errors.append("time_window_minutes must be positive")
|
|
433
|
+
|
|
434
|
+
if not self.person_categories:
|
|
435
|
+
errors.append("person_categories cannot be empty")
|
|
436
|
+
|
|
437
|
+
# Validate nested configurations
|
|
438
|
+
if self.zone_config:
|
|
439
|
+
errors.extend(self.zone_config.validate())
|
|
440
|
+
|
|
441
|
+
if self.alert_config:
|
|
442
|
+
errors.extend(self.alert_config.validate())
|
|
443
|
+
|
|
444
|
+
return errors
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
@dataclass
|
|
448
|
+
class ProximityConfig(BaseConfig):
|
|
449
|
+
"""Configuration for intrusion detection use case."""
|
|
450
|
+
|
|
451
|
+
# Smoothing configuration
|
|
452
|
+
enable_smoothing: bool = True
|
|
453
|
+
smoothing_algorithm: str = "observability" # "window" or "observability"
|
|
454
|
+
smoothing_window_size: int = 20
|
|
455
|
+
smoothing_cooldown_frames: int = 5
|
|
456
|
+
smoothing_confidence_range_factor: float = 0.5
|
|
457
|
+
|
|
458
|
+
# Zone configuration
|
|
459
|
+
zone_config: Optional[ZoneConfig] = None
|
|
460
|
+
|
|
461
|
+
# Counting parameters
|
|
462
|
+
enable_unique_counting: bool = True
|
|
463
|
+
time_window_minutes: int = 60
|
|
464
|
+
|
|
465
|
+
proximity_threshold_meters: float = 1.0
|
|
466
|
+
proximity_threshold_pixels: float = 250.0
|
|
467
|
+
meters_per_pixel: float = 0.0028
|
|
468
|
+
scene_width_meters: float = 0.0
|
|
469
|
+
scene_height_meters: float = 0.0
|
|
470
|
+
|
|
471
|
+
# Category mapping
|
|
472
|
+
person_categories: List[str] = field(default_factory=lambda: ["person"])
|
|
473
|
+
index_to_category: Optional[Dict[int, str]] = None
|
|
474
|
+
|
|
475
|
+
# Alert configuration
|
|
476
|
+
alert_config: Optional[AlertConfig] = None
|
|
477
|
+
|
|
478
|
+
def validate(self) -> List[str]:
|
|
479
|
+
"""Validate proximity detection configuration."""
|
|
480
|
+
errors = super().validate()
|
|
481
|
+
|
|
482
|
+
if self.time_window_minutes <= 0:
|
|
483
|
+
errors.append("time_window_minutes must be positive")
|
|
484
|
+
|
|
485
|
+
if not self.person_categories:
|
|
486
|
+
errors.append("person_categories cannot be empty")
|
|
487
|
+
|
|
488
|
+
# Validate nested configurations
|
|
489
|
+
if self.zone_config:
|
|
490
|
+
errors.extend(self.zone_config.validate())
|
|
491
|
+
|
|
492
|
+
if self.alert_config:
|
|
493
|
+
errors.extend(self.alert_config.validate())
|
|
494
|
+
|
|
495
|
+
return errors
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
@dataclass
|
|
499
|
+
class CustomerServiceConfig(BaseConfig):
|
|
500
|
+
"""Configuration for customer service use case."""
|
|
501
|
+
|
|
502
|
+
# Area definitions
|
|
503
|
+
customer_areas: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
504
|
+
staff_areas: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
505
|
+
service_areas: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
506
|
+
|
|
507
|
+
# Category identification
|
|
508
|
+
staff_categories: List[str] = field(default_factory=lambda: ["staff", "employee"])
|
|
509
|
+
customer_categories: List[str] = field(default_factory=lambda: ["customer", "person"])
|
|
510
|
+
|
|
511
|
+
# Service parameters
|
|
512
|
+
service_proximity_threshold: float = 100.0
|
|
513
|
+
max_service_time: float = 1800.0 # 30 minutes
|
|
514
|
+
buffer_time: float = 2.0
|
|
515
|
+
|
|
516
|
+
# Tracking configuration
|
|
517
|
+
tracking_config: Optional[TrackingConfig] = None
|
|
518
|
+
|
|
519
|
+
# Alert configuration
|
|
520
|
+
alert_config: Optional[AlertConfig] = None
|
|
521
|
+
|
|
522
|
+
# Additional analytics options
|
|
523
|
+
enable_journey_analysis: bool = False
|
|
524
|
+
enable_queue_analytics: bool = False
|
|
525
|
+
|
|
526
|
+
def validate(self) -> List[str]:
|
|
527
|
+
"""Validate customer service configuration."""
|
|
528
|
+
errors = super().validate()
|
|
529
|
+
|
|
530
|
+
if self.service_proximity_threshold <= 0:
|
|
531
|
+
errors.append("service_proximity_threshold must be positive")
|
|
532
|
+
|
|
533
|
+
if self.max_service_time <= 0:
|
|
534
|
+
errors.append("max_service_time must be positive")
|
|
535
|
+
|
|
536
|
+
if self.buffer_time < 0:
|
|
537
|
+
errors.append("buffer_time must be non-negative")
|
|
538
|
+
|
|
539
|
+
# Validate category lists
|
|
540
|
+
if not self.staff_categories:
|
|
541
|
+
errors.append("staff_categories cannot be empty")
|
|
542
|
+
|
|
543
|
+
if not self.customer_categories:
|
|
544
|
+
errors.append("customer_categories cannot be empty")
|
|
545
|
+
|
|
546
|
+
# Validate area polygons
|
|
547
|
+
all_areas = {**self.customer_areas, **self.staff_areas, **self.service_areas}
|
|
548
|
+
for area_name, polygon in all_areas.items():
|
|
549
|
+
if len(polygon) < 3:
|
|
550
|
+
errors.append(f"Area '{area_name}' must have at least 3 points")
|
|
551
|
+
|
|
552
|
+
for i, point in enumerate(polygon):
|
|
553
|
+
if len(point) != 2:
|
|
554
|
+
errors.append(f"Area '{area_name}' point {i} must have exactly 2 coordinates")
|
|
555
|
+
|
|
556
|
+
# Validate nested configurations
|
|
557
|
+
if self.tracking_config:
|
|
558
|
+
errors.extend(self.tracking_config.validate())
|
|
559
|
+
|
|
560
|
+
if self.alert_config:
|
|
561
|
+
errors.extend(self.alert_config.validate())
|
|
562
|
+
|
|
563
|
+
return errors
|
|
564
|
+
|
|
565
|
+
@dataclass
|
|
566
|
+
class CarServiceConfig(BaseConfig):
|
|
567
|
+
"""Configuration for car service use case."""
|
|
568
|
+
|
|
569
|
+
# Area definitions
|
|
570
|
+
car_areas: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
571
|
+
staff_areas: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
572
|
+
service_areas: Dict[str, List[List[float]]] = field(default_factory=dict)
|
|
573
|
+
|
|
574
|
+
# Category identification
|
|
575
|
+
staff_categories: List[str] = field(default_factory=lambda: ["staff", "employee"])
|
|
576
|
+
car_categories: List[str] = field(default_factory=lambda: ["car"])
|
|
577
|
+
|
|
578
|
+
# Service parameters
|
|
579
|
+
service_proximity_threshold: float = 100.0
|
|
580
|
+
max_service_time: float = 1800.0 # 30 minutes
|
|
581
|
+
buffer_time: float = 2.0
|
|
582
|
+
|
|
583
|
+
# Tracking configuration
|
|
584
|
+
tracking_config: Optional[TrackingConfig] = None
|
|
585
|
+
|
|
586
|
+
# Alert configuration
|
|
587
|
+
alert_config: Optional[AlertConfig] = None
|
|
588
|
+
|
|
589
|
+
# Additional analytics options
|
|
590
|
+
enable_journey_analysis: bool = False
|
|
591
|
+
enable_queue_analytics: bool = False
|
|
592
|
+
|
|
593
|
+
def validate(self) -> List[str]:
|
|
594
|
+
"""Validate customer service configuration."""
|
|
595
|
+
errors = super().validate()
|
|
596
|
+
|
|
597
|
+
if self.service_proximity_threshold <= 0:
|
|
598
|
+
errors.append("service_proximity_threshold must be positive")
|
|
599
|
+
|
|
600
|
+
if self.max_service_time <= 0:
|
|
601
|
+
errors.append("max_service_time must be positive")
|
|
602
|
+
|
|
603
|
+
if self.buffer_time < 0:
|
|
604
|
+
errors.append("buffer_time must be non-negative")
|
|
605
|
+
|
|
606
|
+
# Validate category lists
|
|
607
|
+
if not self.staff_categories:
|
|
608
|
+
errors.append("staff_categories cannot be empty")
|
|
609
|
+
|
|
610
|
+
if not self.car_categories:
|
|
611
|
+
errors.append("car_categories cannot be empty")
|
|
612
|
+
|
|
613
|
+
# Validate area polygons
|
|
614
|
+
all_areas = {**self.car_categories, **self.staff_areas, **self.service_areas}
|
|
615
|
+
for area_name, polygon in all_areas.items():
|
|
616
|
+
if len(polygon) < 0:
|
|
617
|
+
errors.append(f"Area '{area_name}' must have at least 0 points")
|
|
618
|
+
|
|
619
|
+
for i, point in enumerate(polygon):
|
|
620
|
+
if len(point) != 2:
|
|
621
|
+
errors.append(f"Area '{area_name}' point {i} must have exactly 2 coordinates")
|
|
622
|
+
|
|
623
|
+
# Validate nested configurations
|
|
624
|
+
if self.tracking_config:
|
|
625
|
+
errors.extend(self.tracking_config.validate())
|
|
626
|
+
|
|
627
|
+
if self.alert_config:
|
|
628
|
+
errors.extend(self.alert_config.validate())
|
|
629
|
+
|
|
630
|
+
return errors
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
@dataclass
|
|
634
|
+
class LineConfig:
|
|
635
|
+
"""Configuration for line crossing detection."""
|
|
636
|
+
|
|
637
|
+
# Line definition
|
|
638
|
+
points: List[List[float]] = field(default_factory=list) # Two points defining the line [[x1, y1], [x2, y2]]
|
|
639
|
+
|
|
640
|
+
# Line-specific settings
|
|
641
|
+
side1_label: str = field(default_factory=lambda: "Side1") # Label for one side of the line
|
|
642
|
+
side2_label: str = field(default_factory=lambda: "Side2") # Label for the other side of the line
|
|
643
|
+
crossing_categories: List[str] = field(default_factory=list) # Categories to track for crossing
|
|
644
|
+
|
|
645
|
+
def validate(self) -> List[str]:
|
|
646
|
+
"""Validate line configuration."""
|
|
647
|
+
errors = []
|
|
648
|
+
|
|
649
|
+
# Validate line points
|
|
650
|
+
if len(self.points) != 2:
|
|
651
|
+
errors.append("points must contain exactly 2 points")
|
|
652
|
+
|
|
653
|
+
for i, point in enumerate(self.points):
|
|
654
|
+
if not isinstance(point, (list, tuple)) or len(point) != 2:
|
|
655
|
+
errors.append(f"Point {i} must have exactly 2 coordinates [x, y]")
|
|
656
|
+
for j, coord in enumerate(point):
|
|
657
|
+
if not isinstance(coord, (int, float)):
|
|
658
|
+
errors.append(f"Point {i} coordinate {j} must be a number")
|
|
659
|
+
|
|
660
|
+
# Validate side labels
|
|
661
|
+
if not self.side1_label:
|
|
662
|
+
errors.append("side1_label must be a non-empty string")
|
|
663
|
+
if not self.side2_label:
|
|
664
|
+
errors.append("side2_label must be a non-empty string")
|
|
665
|
+
if self.side1_label == self.side2_label:
|
|
666
|
+
errors.append("side1_label and side2_label must be different")
|
|
667
|
+
|
|
668
|
+
# Validate crossing categories
|
|
669
|
+
if not self.crossing_categories:
|
|
670
|
+
errors.append("crossing_categories cannot be empty")
|
|
671
|
+
|
|
672
|
+
return errors
|
|
673
|
+
|
|
674
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
675
|
+
"""Convert to dictionary."""
|
|
676
|
+
return {
|
|
677
|
+
"points": self.points,
|
|
678
|
+
"side1_label": self.side1_label,
|
|
679
|
+
"side2_label": self.side2_label,
|
|
680
|
+
"crossing_categories": self.crossing_categories
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
# --- Legacy/dict-like compatibility helpers ---
|
|
684
|
+
def _as_legacy_dict(self) -> Dict[str, Any]:
|
|
685
|
+
return {
|
|
686
|
+
"points": self.points,
|
|
687
|
+
"side1_label": self.side1_label,
|
|
688
|
+
"side2_label": self.side2_label,
|
|
689
|
+
"crossing_categories": self.crossing_categories
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
def __getitem__(self, key: str) -> Any: # Support config.line_config['points']
|
|
693
|
+
return self._as_legacy_dict()[key]
|
|
694
|
+
|
|
695
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
696
|
+
return self._as_legacy_dict().get(key, default)
|
|
697
|
+
|
|
698
|
+
def keys(self):
|
|
699
|
+
return self._as_legacy_dict().keys()
|
|
700
|
+
|
|
701
|
+
def items(self):
|
|
702
|
+
return self._as_legacy_dict().items()
|
|
703
|
+
|
|
704
|
+
def __contains__(self, key: object) -> bool:
|
|
705
|
+
return key in self._as_legacy_dict()
|
|
706
|
+
|
|
707
|
+
def __iter__(self):
|
|
708
|
+
return iter(self._as_legacy_dict())
|
|
709
|
+
|
|
710
|
+
def __len__(self) -> int:
|
|
711
|
+
return len(self._as_legacy_dict())
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
@dataclass
|
|
715
|
+
class PeopleTrackingConfig:
|
|
716
|
+
"""Configuration for the People Tracking Use Case."""
|
|
717
|
+
|
|
718
|
+
confidence_threshold: float = field(default_factory=lambda: 0.5) # Minimum confidence for detections
|
|
719
|
+
|
|
720
|
+
# Category identification
|
|
721
|
+
person_categories: List[str] = field(default_factory=lambda: []) # Categories representing people
|
|
722
|
+
|
|
723
|
+
# Zone configuration
|
|
724
|
+
zone_config: Optional[ZoneConfig] = None # Zone definitions and thresholds
|
|
725
|
+
|
|
726
|
+
# Line crossing configuration
|
|
727
|
+
line_config: Optional[LineConfig] = None # Line crossing definitions and labels
|
|
728
|
+
|
|
729
|
+
# Tracking configuration
|
|
730
|
+
tracking_config: Optional[TrackingConfig] = None # Tracking parameters
|
|
731
|
+
|
|
732
|
+
# Alert configuration
|
|
733
|
+
alert_config: Optional[AlertConfig] = None # Alert thresholds and settings
|
|
734
|
+
|
|
735
|
+
# Category mapping
|
|
736
|
+
index_to_category: Dict[int, str] = field(default_factory=dict) # Map model indices to categories
|
|
737
|
+
|
|
738
|
+
# Additional analytics options
|
|
739
|
+
enable_analytics: bool = field(default_factory=lambda: True) # Enable business analytics
|
|
740
|
+
enable_zone_analytics: bool = field(default_factory=lambda: False) # Enable zone-specific analytics
|
|
741
|
+
enable_crossing_analytics: bool = field(default_factory=lambda: False) # Enable line crossing analytics
|
|
742
|
+
|
|
743
|
+
def validate(self) -> List[str]:
|
|
744
|
+
"""Validate people tracking configuration."""
|
|
745
|
+
errors = []
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
# Validate person categories
|
|
749
|
+
if not self.person_categories:
|
|
750
|
+
errors.append("person_categories cannot be empty")
|
|
751
|
+
|
|
752
|
+
# Validate index_to_category
|
|
753
|
+
if self.index_to_category:
|
|
754
|
+
for index, category in self.index_to_category.items():
|
|
755
|
+
if not isinstance(index, int):
|
|
756
|
+
errors.append(f"index_to_category key '{index}' must be an integer")
|
|
757
|
+
if not isinstance(category, str) or not category:
|
|
758
|
+
errors.append(f"index_to_category value for key '{index}' must be a non-empty string")
|
|
759
|
+
|
|
760
|
+
# Validate nested configurations
|
|
761
|
+
if self.zone_config:
|
|
762
|
+
try:
|
|
763
|
+
zone_errors = self.zone_config.validate()
|
|
764
|
+
errors.extend(zone_errors)
|
|
765
|
+
except AttributeError:
|
|
766
|
+
errors.append("zone_config must have a validate method")
|
|
767
|
+
|
|
768
|
+
if self.line_config:
|
|
769
|
+
try:
|
|
770
|
+
line_errors = self.line_config.validate()
|
|
771
|
+
errors.extend(line_errors)
|
|
772
|
+
except AttributeError:
|
|
773
|
+
errors.append("line_config must have a validate method")
|
|
774
|
+
|
|
775
|
+
if self.tracking_config:
|
|
776
|
+
try:
|
|
777
|
+
tracking_errors = self.tracking_config.validate()
|
|
778
|
+
errors.extend(tracking_errors)
|
|
779
|
+
except AttributeError:
|
|
780
|
+
errors.append("tracking_config must have a validate method")
|
|
781
|
+
|
|
782
|
+
if self.alert_config:
|
|
783
|
+
try:
|
|
784
|
+
alert_errors = self.alert_config.validate()
|
|
785
|
+
errors.extend(alert_errors)
|
|
786
|
+
except AttributeError:
|
|
787
|
+
errors.append("alert_config must have a validate method")
|
|
788
|
+
|
|
789
|
+
return errors
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def filter_config_kwargs(config_class: type, kwargs: Dict[str, Any]) -> Dict[str, Any]:
|
|
793
|
+
"""
|
|
794
|
+
Filter kwargs to only include parameters that are valid for the config class.
|
|
795
|
+
|
|
796
|
+
Args:
|
|
797
|
+
config_class: The config class to create
|
|
798
|
+
kwargs: Dictionary of parameters to filter
|
|
799
|
+
|
|
800
|
+
Returns:
|
|
801
|
+
Dict[str, Any]: Filtered kwargs containing only valid parameters
|
|
802
|
+
"""
|
|
803
|
+
if not hasattr(config_class, '__dataclass_fields__'):
|
|
804
|
+
# Not a dataclass, return kwargs as-is
|
|
805
|
+
return kwargs
|
|
806
|
+
|
|
807
|
+
# Get valid field names from the dataclass
|
|
808
|
+
valid_fields = set(config_class.__dataclass_fields__.keys())
|
|
809
|
+
|
|
810
|
+
# Filter kwargs to only include valid fields
|
|
811
|
+
filtered_kwargs = {}
|
|
812
|
+
ignored_params = []
|
|
813
|
+
|
|
814
|
+
for key, value in kwargs.items():
|
|
815
|
+
if key in valid_fields:
|
|
816
|
+
filtered_kwargs[key] = value
|
|
817
|
+
else:
|
|
818
|
+
ignored_params.append(key)
|
|
819
|
+
|
|
820
|
+
# Log ignored parameters for debugging
|
|
821
|
+
if ignored_params:
|
|
822
|
+
logger.debug(
|
|
823
|
+
f"Ignoring non-config parameters for {config_class.__name__}: {ignored_params}"
|
|
824
|
+
)
|
|
825
|
+
|
|
826
|
+
return filtered_kwargs
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
class ConfigManager:
|
|
830
|
+
"""Centralized configuration management for post-processing operations."""
|
|
831
|
+
|
|
832
|
+
def __init__(self):
|
|
833
|
+
"""Initialize configuration manager."""
|
|
834
|
+
self._config_classes = {
|
|
835
|
+
"people_counting": PeopleCountingConfig,
|
|
836
|
+
"customer_service": CustomerServiceConfig,
|
|
837
|
+
"advanced_customer_service": CustomerServiceConfig,
|
|
838
|
+
"intrusion_detection": IntrusionConfig,
|
|
839
|
+
"proximity_detection": ProximityConfig,
|
|
840
|
+
"basic_counting_tracking": None, # Will be set later to avoid circular import
|
|
841
|
+
"license_plate_detection": None, # Will be set later to avoid circular import
|
|
842
|
+
"ppe_compliance_detection": None,
|
|
843
|
+
"color_detection": None, # Will be set later to avoid circular import
|
|
844
|
+
"video_color_classification": None, # Alias for color_detection
|
|
845
|
+
"drone_traffic_monitoring": None,
|
|
846
|
+
"vehicle_monitoring" : None,
|
|
847
|
+
"fire_smoke_detection": None,
|
|
848
|
+
"flare_analysis" : None,
|
|
849
|
+
"mask_detection": None,
|
|
850
|
+
"pipeline_detection": None,
|
|
851
|
+
"parking_space_detection": None,
|
|
852
|
+
"car_damage_detection":None,
|
|
853
|
+
"weld_defect_detection" : None,
|
|
854
|
+
"banana_defect_detection" : None,
|
|
855
|
+
"chicken_pose_detection" : None,
|
|
856
|
+
"traffic_sign_monitoring" : None,
|
|
857
|
+
"theft_detection" : None,
|
|
858
|
+
"gender_detection": None,
|
|
859
|
+
"solar_panel": None,
|
|
860
|
+
"crop_weed_detection": None,
|
|
861
|
+
"emergency_vehicle_detection": None,
|
|
862
|
+
"shoplifting_detection":None,
|
|
863
|
+
"price_tag_detection": None,
|
|
864
|
+
"child_monitoring": None,
|
|
865
|
+
"weapon_detection" : None,
|
|
866
|
+
"concrete_crack_detection": None,
|
|
867
|
+
"fashion_detection": None,
|
|
868
|
+
"pothole_segmentation": None,
|
|
869
|
+
"warehouse_object_segmentation": None,
|
|
870
|
+
"shopping_cart_analysis": None,
|
|
871
|
+
"defect_detection_products": None,
|
|
872
|
+
'assembly_line_detection': None,
|
|
873
|
+
'anti_spoofing_detection' : None,
|
|
874
|
+
'shelf_inventory' : None,
|
|
875
|
+
'wound_segmentation': None,
|
|
876
|
+
'leaf_disease_detection': None,
|
|
877
|
+
'field_mapping': None,
|
|
878
|
+
'car_part_segmentation': None,
|
|
879
|
+
'lane_detection' : None,
|
|
880
|
+
'windmill_maintenance': None,
|
|
881
|
+
'face_emotion': None,
|
|
882
|
+
'flower_segmentation': None,
|
|
883
|
+
'smoker_detection': None,
|
|
884
|
+
'road_traffic_density': None,
|
|
885
|
+
'road_view_segmentation': None,
|
|
886
|
+
'face_recognition': None,
|
|
887
|
+
'drowsy_driver_detection': None,
|
|
888
|
+
'waterbody_segmentation': None,
|
|
889
|
+
'litter_detection' :None,
|
|
890
|
+
'abandoned_object_detection' : None,
|
|
891
|
+
'litter_detection':None,
|
|
892
|
+
'leak_detection': None,
|
|
893
|
+
'human_activity_recognition': None,
|
|
894
|
+
'gas_leak_detection': None,
|
|
895
|
+
'license_plate_monitor' : None,
|
|
896
|
+
'dwell' : None,
|
|
897
|
+
'age_gender_detection': None,
|
|
898
|
+
'wildlife_monitoring': None,
|
|
899
|
+
'people_tracking' : PeopleTrackingConfig,
|
|
900
|
+
'pcb_defect_detection': None,
|
|
901
|
+
'underground_pipeline_defect' : None,
|
|
902
|
+
'suspicious_activity_detection': None,
|
|
903
|
+
'natural_disaster_detection': None,
|
|
904
|
+
|
|
905
|
+
#Put all image based usecases here::
|
|
906
|
+
'blood_cancer_detection_img': None,
|
|
907
|
+
'skin_cancer_classification_img': None,
|
|
908
|
+
'plaque_segmentation_img': None,
|
|
909
|
+
'cardiomegaly_classification': None,
|
|
910
|
+
'histopathological_cancer_detection' : None,
|
|
911
|
+
'cell_microscopy_segmentation': None,
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
def register_config_class(self, usecase: str, config_class: type) -> None:
|
|
915
|
+
"""Register a configuration class for a use case."""
|
|
916
|
+
self._config_classes[usecase] = config_class
|
|
917
|
+
|
|
918
|
+
def _get_license_plate_config_class(self):
|
|
919
|
+
"""Get LicensePlateConfig class to avoid circular imports."""
|
|
920
|
+
try:
|
|
921
|
+
from ..usecases.license_plate_detection import LicensePlateConfig
|
|
922
|
+
return LicensePlateConfig
|
|
923
|
+
except ImportError:
|
|
924
|
+
return None
|
|
925
|
+
def _get_wound_segmentation_config_class(self):
|
|
926
|
+
"""Get LicensePlateConfig class to avoid circular imports."""
|
|
927
|
+
try:
|
|
928
|
+
from ..usecases.wound_segmentation import WoundConfig
|
|
929
|
+
return WoundConfig
|
|
930
|
+
except ImportError:
|
|
931
|
+
return None
|
|
932
|
+
def _get_leaf_disease_config_class(self):
|
|
933
|
+
"""Get LicensePlateConfig class to avoid circular imports."""
|
|
934
|
+
try:
|
|
935
|
+
from ..usecases.leaf_disease import LeafDiseaseDetectionConfig
|
|
936
|
+
return LeafDiseaseDetectionConfig
|
|
937
|
+
except ImportError:
|
|
938
|
+
return None
|
|
939
|
+
def _get_field_mapping_config_class(self):
|
|
940
|
+
"""Get LicensePlateConfig class to avoid circular imports."""
|
|
941
|
+
try:
|
|
942
|
+
from ..usecases.field_mapping import FieldMappingConfig
|
|
943
|
+
return FieldMappingConfig
|
|
944
|
+
except ImportError:
|
|
945
|
+
return None
|
|
946
|
+
|
|
947
|
+
def vehicle_monitoring_config_class(self):
|
|
948
|
+
"""Get vehicle monitoring class to avoid circular imports."""
|
|
949
|
+
try:
|
|
950
|
+
from ..usecases.vehicle_monitoring import VehicleMonitoringConfig
|
|
951
|
+
return VehicleMonitoringConfig
|
|
952
|
+
except ImportError:
|
|
953
|
+
return None
|
|
954
|
+
|
|
955
|
+
def drone_traffic_monitoring_config_class(self):
|
|
956
|
+
"""Get drone traffic monitoring class to avoid circular imports."""
|
|
957
|
+
try:
|
|
958
|
+
from ..usecases.drone_traffic_monitoring import VehiclePeopleDroneMonitoringConfig
|
|
959
|
+
return VehiclePeopleDroneMonitoringConfig
|
|
960
|
+
except ImportError:
|
|
961
|
+
return None
|
|
962
|
+
|
|
963
|
+
def banana_defect_detection_config_class(self):
|
|
964
|
+
"""Get Banana monitoring class to avoid circular imports."""
|
|
965
|
+
try:
|
|
966
|
+
from ..usecases.banana_defect_detection import BananaMonitoringConfig
|
|
967
|
+
return BananaMonitoringConfig
|
|
968
|
+
except ImportError:
|
|
969
|
+
return None
|
|
970
|
+
|
|
971
|
+
def lane_detection_config_class(self):
|
|
972
|
+
"""Get road lane monitoring class to avoid circular imports."""
|
|
973
|
+
try:
|
|
974
|
+
from ..usecases.road_lane_detection import LaneDetectionConfig
|
|
975
|
+
return LaneDetectionConfig
|
|
976
|
+
except ImportError:
|
|
977
|
+
return None
|
|
978
|
+
|
|
979
|
+
def shelf_inventory_config_class(self):
|
|
980
|
+
"""Get inventory monitoring class to avoid circular imports."""
|
|
981
|
+
try:
|
|
982
|
+
from ..usecases.shelf_inventory_detection import ShelfInventoryUseCase
|
|
983
|
+
return ShelfInventoryUseCase
|
|
984
|
+
except ImportError:
|
|
985
|
+
return None
|
|
986
|
+
|
|
987
|
+
def anti_spoofing_detection_config_class(self):
|
|
988
|
+
"""Get Anti-Spoofing class to avoid circular imports."""
|
|
989
|
+
try:
|
|
990
|
+
from ..usecases.anti_spoofing_detection import AntiSpoofingDetectionConfig
|
|
991
|
+
return AntiSpoofingDetectionConfig
|
|
992
|
+
except ImportError:
|
|
993
|
+
return None
|
|
994
|
+
|
|
995
|
+
def theft_detection_config_class(self):
|
|
996
|
+
"""Get theft detection class to avoid circular imports."""
|
|
997
|
+
try:
|
|
998
|
+
from ..usecases.theft_detection import TheftDetectionConfig
|
|
999
|
+
return TheftDetectionConfig
|
|
1000
|
+
except ImportError:
|
|
1001
|
+
return None
|
|
1002
|
+
|
|
1003
|
+
def weapon_tracking_config_class(self):
|
|
1004
|
+
"""Get weapon detection class to avoid circular imports."""
|
|
1005
|
+
try:
|
|
1006
|
+
from ..usecases.weapon_detection import WeaponDetectionConfig
|
|
1007
|
+
return WeaponDetectionConfig
|
|
1008
|
+
except ImportError:
|
|
1009
|
+
return None
|
|
1010
|
+
|
|
1011
|
+
def traffic_sign_monitoring_config_class(self):
|
|
1012
|
+
"""Get traffic sign monitoring class to avoid circular imports."""
|
|
1013
|
+
try:
|
|
1014
|
+
from ..usecases.traffic_sign_monitoring import TrafficSignMonitoringConfig
|
|
1015
|
+
return TrafficSignMonitoringConfig
|
|
1016
|
+
except ImportError:
|
|
1017
|
+
return None
|
|
1018
|
+
|
|
1019
|
+
def chicken_pose_detection_config_class(self):
|
|
1020
|
+
"""Get Chicken pose monitoring class to avoid circular imports."""
|
|
1021
|
+
try:
|
|
1022
|
+
from ..usecases.chicken_pose_detection import ChickenPoseDetectionConfig
|
|
1023
|
+
return ChickenPoseDetectionConfig
|
|
1024
|
+
except ImportError:
|
|
1025
|
+
return None
|
|
1026
|
+
|
|
1027
|
+
def _get_fire_smoke_detection_config_class(self):
|
|
1028
|
+
"""Register a configuration class for a use case."""
|
|
1029
|
+
try:
|
|
1030
|
+
from ..usecases.fire_detection import FireSmokeConfig
|
|
1031
|
+
return FireSmokeConfig
|
|
1032
|
+
except ImportError:
|
|
1033
|
+
return None
|
|
1034
|
+
|
|
1035
|
+
def _get_shoplifting_detection_config_class(self):
|
|
1036
|
+
"""Register a configuration class for a use case."""
|
|
1037
|
+
try:
|
|
1038
|
+
from ..usecases.shoplifting_detection import ShopliftingDetectionConfig
|
|
1039
|
+
return ShopliftingDetectionConfig
|
|
1040
|
+
except ImportError:
|
|
1041
|
+
return None
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
def _get_car_damage_config_class(self):
|
|
1045
|
+
"""Register a configuration class for a use case."""
|
|
1046
|
+
try:
|
|
1047
|
+
from ..usecases.car_damage_detection import CarDamageConfig
|
|
1048
|
+
return CarDamageConfig
|
|
1049
|
+
except ImportError:
|
|
1050
|
+
return None
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
def _get_parking_space_detection_config_class(self):
|
|
1054
|
+
"""Register a configuration class for a use case."""
|
|
1055
|
+
try:
|
|
1056
|
+
from ..usecases.parking_space_detection import ParkingSpaceConfig
|
|
1057
|
+
return ParkingSpaceConfig
|
|
1058
|
+
except ImportError:
|
|
1059
|
+
return None
|
|
1060
|
+
|
|
1061
|
+
def _get_mask_detection_config_class(self):
|
|
1062
|
+
"""Register a configuration class for a use case."""
|
|
1063
|
+
try:
|
|
1064
|
+
from ..usecases.mask_detection import MaskDetectionConfig
|
|
1065
|
+
return MaskDetectionConfig
|
|
1066
|
+
except ImportError:
|
|
1067
|
+
return None
|
|
1068
|
+
|
|
1069
|
+
def _get_pipeline_detection_config_class(self):
|
|
1070
|
+
"""Register a configuration class for a use case."""
|
|
1071
|
+
try:
|
|
1072
|
+
from ..usecases.pipeline_detection import PipelineDetectionConfig
|
|
1073
|
+
return PipelineDetectionConfig
|
|
1074
|
+
except ImportError:
|
|
1075
|
+
return None
|
|
1076
|
+
|
|
1077
|
+
def _get_pothole_segmentation_config_class(self):
|
|
1078
|
+
"""Register a configuration class for a use case."""
|
|
1079
|
+
try:
|
|
1080
|
+
from ..usecases.pothole_segmentation import PotholeConfig
|
|
1081
|
+
return PotholeConfig
|
|
1082
|
+
except ImportError:
|
|
1083
|
+
return None
|
|
1084
|
+
|
|
1085
|
+
def flare_analysis_config_class(self):
|
|
1086
|
+
"""Register a configuration class for a use case."""
|
|
1087
|
+
try:
|
|
1088
|
+
from ..usecases.flare_analysis import FlareAnalysisConfig
|
|
1089
|
+
return FlareAnalysisConfig
|
|
1090
|
+
except ImportError:
|
|
1091
|
+
return None
|
|
1092
|
+
|
|
1093
|
+
def face_emotion_config_class(self):
|
|
1094
|
+
"""Register a configuration class for a use case."""
|
|
1095
|
+
try:
|
|
1096
|
+
from ..usecases.face_emotion import FaceEmotionConfig
|
|
1097
|
+
return FaceEmotionConfig
|
|
1098
|
+
except ImportError:
|
|
1099
|
+
return None
|
|
1100
|
+
|
|
1101
|
+
def underwater_pollution_detection_config_class(self):
|
|
1102
|
+
"""Register a configuration class for a use case."""
|
|
1103
|
+
try:
|
|
1104
|
+
from ..usecases.underwater_pollution_detection import UnderwaterPlasticConfig
|
|
1105
|
+
return UnderwaterPlasticConfig
|
|
1106
|
+
except ImportError:
|
|
1107
|
+
return None
|
|
1108
|
+
|
|
1109
|
+
def pedestrian_detection_config_class(self):
|
|
1110
|
+
"""Register a configuration class for a use case."""
|
|
1111
|
+
try:
|
|
1112
|
+
from ..usecases.pedestrian_detection import PedestrianDetectionConfig
|
|
1113
|
+
return PedestrianDetectionConfig
|
|
1114
|
+
except ImportError:
|
|
1115
|
+
return None
|
|
1116
|
+
|
|
1117
|
+
def age_detection_config_class(self):
|
|
1118
|
+
"""Register a configuration class for a use case."""
|
|
1119
|
+
try:
|
|
1120
|
+
from ..usecases.age_detection import AgeDetectionConfig
|
|
1121
|
+
return AgeDetectionConfig
|
|
1122
|
+
except ImportError:
|
|
1123
|
+
return None
|
|
1124
|
+
|
|
1125
|
+
def weld_defect_detection_config_class(self):
|
|
1126
|
+
"""Register a configuration class for a use case."""
|
|
1127
|
+
try:
|
|
1128
|
+
from ..usecases.weld_defect_detection import WeldDefectConfig
|
|
1129
|
+
return WeldDefectConfig
|
|
1130
|
+
except ImportError:
|
|
1131
|
+
return None
|
|
1132
|
+
|
|
1133
|
+
def price_tag_detection_config_class(self):
|
|
1134
|
+
"""Register a configuration class for a use case."""
|
|
1135
|
+
try:
|
|
1136
|
+
from ..usecases.price_tag_detection import PriceTagConfig
|
|
1137
|
+
return PriceTagConfig
|
|
1138
|
+
except ImportError:
|
|
1139
|
+
return None
|
|
1140
|
+
|
|
1141
|
+
def distracted_driver_detection_config_class(self):
|
|
1142
|
+
"""Register a configuration class for a use case."""
|
|
1143
|
+
try:
|
|
1144
|
+
from ..usecases.distracted_driver_detection import DistractedDriverConfig
|
|
1145
|
+
return DistractedDriverConfig
|
|
1146
|
+
except ImportError:
|
|
1147
|
+
return None
|
|
1148
|
+
|
|
1149
|
+
def emergency_vehicle_detection_config_class(self):
|
|
1150
|
+
"""Register a configuration class for a use case."""
|
|
1151
|
+
try:
|
|
1152
|
+
from ..usecases.emergency_vehicle_detection import EmergencyVehicleConfig
|
|
1153
|
+
return EmergencyVehicleConfig
|
|
1154
|
+
except ImportError:
|
|
1155
|
+
return None
|
|
1156
|
+
|
|
1157
|
+
def solar_panel_config_class(self):
|
|
1158
|
+
"""Register a configuration class for a use case."""
|
|
1159
|
+
try:
|
|
1160
|
+
from ..usecases.solar_panel import SolarPanelConfig
|
|
1161
|
+
return SolarPanelConfig
|
|
1162
|
+
except ImportError:
|
|
1163
|
+
return None
|
|
1164
|
+
|
|
1165
|
+
def crop_weed_detection_config_class(self):
|
|
1166
|
+
"""Register a configuration class for a use case."""
|
|
1167
|
+
try:
|
|
1168
|
+
from ..usecases.crop_weed_detection import CropWeedDetectionConfig
|
|
1169
|
+
return CropWeedDetectionConfig
|
|
1170
|
+
except ImportError:
|
|
1171
|
+
return None
|
|
1172
|
+
|
|
1173
|
+
def child_monitoring_config_class(self):
|
|
1174
|
+
"""Register a configuration class for a use case."""
|
|
1175
|
+
try:
|
|
1176
|
+
from ..usecases.child_monitoring import ChildMonitoringConfig
|
|
1177
|
+
return ChildMonitoringConfig
|
|
1178
|
+
except ImportError:
|
|
1179
|
+
return None
|
|
1180
|
+
|
|
1181
|
+
def gender_detection_config_class(self):
|
|
1182
|
+
"""Register a configuration class for a use case."""
|
|
1183
|
+
try:
|
|
1184
|
+
from ..usecases.gender_detection import GenderDetectionConfig
|
|
1185
|
+
return GenderDetectionConfig
|
|
1186
|
+
except ImportError:
|
|
1187
|
+
return None
|
|
1188
|
+
|
|
1189
|
+
def concrete_crack_detection_config_class(self):
|
|
1190
|
+
"""Register a configuration class for a use case."""
|
|
1191
|
+
try:
|
|
1192
|
+
from ..usecases.concrete_crack_detection import ConcreteCrackConfig
|
|
1193
|
+
return ConcreteCrackConfig
|
|
1194
|
+
except ImportError:
|
|
1195
|
+
return None
|
|
1196
|
+
|
|
1197
|
+
def fashion_detection_config_class(self):
|
|
1198
|
+
"""Register a configuration class for a use case."""
|
|
1199
|
+
try:
|
|
1200
|
+
from ..usecases.fashion_detection import FashionDetectionConfig
|
|
1201
|
+
return FashionDetectionConfig
|
|
1202
|
+
except ImportError:
|
|
1203
|
+
return None
|
|
1204
|
+
|
|
1205
|
+
def warehouse_object_segmentation_config_class(self):
|
|
1206
|
+
"""Register a configuration class for a use case."""
|
|
1207
|
+
try:
|
|
1208
|
+
from ..usecases.warehouse_object_segmentation import WarehouseObjectConfig
|
|
1209
|
+
return WarehouseObjectConfig
|
|
1210
|
+
except ImportError:
|
|
1211
|
+
return None
|
|
1212
|
+
|
|
1213
|
+
def shopping_cart_analysis_config_class(self):
|
|
1214
|
+
"""Register a configuration class for a use case."""
|
|
1215
|
+
try:
|
|
1216
|
+
from ..usecases.shopping_cart_analysis import ShoppingCartAnalysisConfig
|
|
1217
|
+
return ShoppingCartAnalysisConfig
|
|
1218
|
+
except ImportError:
|
|
1219
|
+
return None
|
|
1220
|
+
|
|
1221
|
+
def defect_detection_products_config_class(self):
|
|
1222
|
+
"""Register a configuration class for a use case."""
|
|
1223
|
+
try:
|
|
1224
|
+
from ..usecases.defect_detection_products import BottleDefectConfig
|
|
1225
|
+
return BottleDefectConfig
|
|
1226
|
+
except ImportError:
|
|
1227
|
+
return None
|
|
1228
|
+
|
|
1229
|
+
def assembly_line_detection_config_class(self):
|
|
1230
|
+
"""Register a configuration class for a use case."""
|
|
1231
|
+
try:
|
|
1232
|
+
from ..usecases.assembly_line_detection import AssemblyLineConfig
|
|
1233
|
+
return AssemblyLineConfig
|
|
1234
|
+
except ImportError:
|
|
1235
|
+
return None
|
|
1236
|
+
|
|
1237
|
+
def car_part_segmentation_config_class(self):
|
|
1238
|
+
"""Register a configuration class for a use case."""
|
|
1239
|
+
try:
|
|
1240
|
+
from ..usecases.car_part_segmentation import CarPartSegmentationConfig
|
|
1241
|
+
return CarPartSegmentationConfig
|
|
1242
|
+
except ImportError:
|
|
1243
|
+
return None
|
|
1244
|
+
|
|
1245
|
+
def windmill_maintenance_config_class(self):
|
|
1246
|
+
"""Register a configuration class for a use case."""
|
|
1247
|
+
try:
|
|
1248
|
+
from ..usecases.windmill_maintenance import WindmillMaintenanceConfig
|
|
1249
|
+
return WindmillMaintenanceConfig
|
|
1250
|
+
except ImportError:
|
|
1251
|
+
return None
|
|
1252
|
+
|
|
1253
|
+
def flower_segmentation_config_class(self):
|
|
1254
|
+
"""Register a configuration class for a use case."""
|
|
1255
|
+
try:
|
|
1256
|
+
from ..usecases.flower_segmentation import FlowerConfig
|
|
1257
|
+
return FlowerConfig
|
|
1258
|
+
except ImportError:
|
|
1259
|
+
return None
|
|
1260
|
+
|
|
1261
|
+
def smoker_detection_config_class(self):
|
|
1262
|
+
"""Register a configuration class for a use case."""
|
|
1263
|
+
try:
|
|
1264
|
+
from ..usecases.smoker_detection import SmokerDetectionConfig
|
|
1265
|
+
return SmokerDetectionConfig
|
|
1266
|
+
except ImportError:
|
|
1267
|
+
return None
|
|
1268
|
+
|
|
1269
|
+
def road_traffic_density_config_class(self):
|
|
1270
|
+
"""Register a configuration class for a use case."""
|
|
1271
|
+
try:
|
|
1272
|
+
from ..usecases.road_traffic_density import RoadTrafficConfig
|
|
1273
|
+
return RoadTrafficConfig
|
|
1274
|
+
except ImportError:
|
|
1275
|
+
return None
|
|
1276
|
+
|
|
1277
|
+
def road_view_segmentation_config_class(self):
|
|
1278
|
+
"""Register a configuration class for a use case."""
|
|
1279
|
+
try:
|
|
1280
|
+
from ..usecases.road_view_segmentation import RoadViewSegmentationConfig
|
|
1281
|
+
return RoadViewSegmentationConfig
|
|
1282
|
+
except ImportError:
|
|
1283
|
+
return None
|
|
1284
|
+
|
|
1285
|
+
def face_recognition_config_class(self):
|
|
1286
|
+
"""Register a configuration class for a use case."""
|
|
1287
|
+
try:
|
|
1288
|
+
# from ..usecases.face_recognition import FaceRecognitionConfig
|
|
1289
|
+
# return FaceRecognitionConfig
|
|
1290
|
+
from ..face_reg.face_recognition import FaceRecognitionEmbeddingConfig
|
|
1291
|
+
|
|
1292
|
+
return FaceRecognitionEmbeddingConfig
|
|
1293
|
+
except ImportError:
|
|
1294
|
+
return None
|
|
1295
|
+
|
|
1296
|
+
def drowsy_driver_detection_config_class(self):
|
|
1297
|
+
"""Register a configuration class for a use case."""
|
|
1298
|
+
try:
|
|
1299
|
+
from ..usecases.drowsy_driver_detection import DrowsyDriverConfig
|
|
1300
|
+
return DrowsyDriverConfig
|
|
1301
|
+
except ImportError:
|
|
1302
|
+
return None
|
|
1303
|
+
|
|
1304
|
+
def waterbody_segmentation_config_class(self):
|
|
1305
|
+
"""Register a configuration class for a use case."""
|
|
1306
|
+
try:
|
|
1307
|
+
from ..usecases.waterbody_segmentation import WaterBodyConfig
|
|
1308
|
+
return WaterBodyConfig
|
|
1309
|
+
except ImportError:
|
|
1310
|
+
return None
|
|
1311
|
+
|
|
1312
|
+
def litter_detection_config_class(self):
|
|
1313
|
+
"""Get Litter monitoring class to avoid circular imports."""
|
|
1314
|
+
try:
|
|
1315
|
+
from ..usecases.litter_monitoring import LitterDetectionConfig
|
|
1316
|
+
return LitterDetectionConfig
|
|
1317
|
+
except ImportError:
|
|
1318
|
+
return None
|
|
1319
|
+
|
|
1320
|
+
|
|
1321
|
+
def abandoned_object_detection_config_class(self):
|
|
1322
|
+
"""Get monitoring class to avoid circular imports."""
|
|
1323
|
+
try:
|
|
1324
|
+
from ..usecases.abandoned_object_detection import AbandonedObjectConfig
|
|
1325
|
+
return AbandonedObjectConfig
|
|
1326
|
+
except ImportError:
|
|
1327
|
+
return None
|
|
1328
|
+
|
|
1329
|
+
def leak_detection_config_class(self):
|
|
1330
|
+
"""Get Leak detection class to avoid circular imports."""
|
|
1331
|
+
try:
|
|
1332
|
+
from ..usecases.leak_detection import LeakDetectionConfig
|
|
1333
|
+
return LeakDetectionConfig
|
|
1334
|
+
except ImportError:
|
|
1335
|
+
return None
|
|
1336
|
+
|
|
1337
|
+
def human_activity_recognition_config_class(self):
|
|
1338
|
+
"""Register a configuration class for a use case."""
|
|
1339
|
+
try:
|
|
1340
|
+
from ..usecases.human_activity_recognition import HumanActivityConfig
|
|
1341
|
+
return HumanActivityConfig
|
|
1342
|
+
except ImportError:
|
|
1343
|
+
return None
|
|
1344
|
+
|
|
1345
|
+
def license_plate_monitor_config_class(self):
|
|
1346
|
+
"""Register a configuration class for a use case."""
|
|
1347
|
+
try:
|
|
1348
|
+
from ..usecases.license_plate_monitoring import LicensePlateMonitorConfig
|
|
1349
|
+
return LicensePlateMonitorConfig
|
|
1350
|
+
except ImportError:
|
|
1351
|
+
return None
|
|
1352
|
+
|
|
1353
|
+
def dwell_config_class(self):
|
|
1354
|
+
"""Register a configuration class for a use case."""
|
|
1355
|
+
try:
|
|
1356
|
+
from ..usecases.dwell_detection import DwellConfig
|
|
1357
|
+
return DwellConfig
|
|
1358
|
+
except ImportError:
|
|
1359
|
+
return None
|
|
1360
|
+
|
|
1361
|
+
def gas_leak_detection_config_class(self):
|
|
1362
|
+
"""Register a configuration class for a use case."""
|
|
1363
|
+
try:
|
|
1364
|
+
from ..usecases.gas_leak_detection import GasLeakDetectionConfig
|
|
1365
|
+
return GasLeakDetectionConfig
|
|
1366
|
+
except ImportError:
|
|
1367
|
+
return None
|
|
1368
|
+
|
|
1369
|
+
def age_gender_detection_config_class(self):
|
|
1370
|
+
"""Register a configuration class for a use case."""
|
|
1371
|
+
try:
|
|
1372
|
+
from ..usecases.age_gender_detection import AgeGenderConfig
|
|
1373
|
+
return AgeGenderConfig
|
|
1374
|
+
except ImportError:
|
|
1375
|
+
return None
|
|
1376
|
+
|
|
1377
|
+
def wildlife_monitoring_config_class(self):
|
|
1378
|
+
"""Register a configuration class for a use case."""
|
|
1379
|
+
try:
|
|
1380
|
+
from ..usecases.wildlife_monitoring import WildLifeMonitoringConfig
|
|
1381
|
+
return WildLifeMonitoringConfig
|
|
1382
|
+
except ImportError:
|
|
1383
|
+
return None
|
|
1384
|
+
|
|
1385
|
+
def pcb_defect_detection_config_class(self):
|
|
1386
|
+
"""Register a configuration class for a use case."""
|
|
1387
|
+
try:
|
|
1388
|
+
from ..usecases.pcb_defect_detection import PCBDefectConfig
|
|
1389
|
+
return PCBDefectConfig
|
|
1390
|
+
except ImportError:
|
|
1391
|
+
return None
|
|
1392
|
+
|
|
1393
|
+
def suspicious_activity_detection_config_class(self):
|
|
1394
|
+
"""Register a configuration class for a use case."""
|
|
1395
|
+
try:
|
|
1396
|
+
from ..usecases.suspicious_activity_detection import SusActivityConfig
|
|
1397
|
+
return SusActivityConfig
|
|
1398
|
+
except ImportError:
|
|
1399
|
+
return None
|
|
1400
|
+
|
|
1401
|
+
def natural_disaster_detection_config_class(self):
|
|
1402
|
+
"""Register a configuration class for a use case."""
|
|
1403
|
+
try:
|
|
1404
|
+
from ..usecases.natural_disaster import NaturalDisasterConfig
|
|
1405
|
+
return NaturalDisasterConfig
|
|
1406
|
+
except ImportError:
|
|
1407
|
+
return None
|
|
1408
|
+
|
|
1409
|
+
#put all image based usecases here::
|
|
1410
|
+
def blood_cancer_detection_config_class(self):
|
|
1411
|
+
"""Register a configuration class for a use case."""
|
|
1412
|
+
try:
|
|
1413
|
+
from ..usecases.blood_cancer_detection_img import BloodCancerDetectionConfig
|
|
1414
|
+
return BloodCancerDetectionConfig
|
|
1415
|
+
except ImportError:
|
|
1416
|
+
return None
|
|
1417
|
+
|
|
1418
|
+
def plaque_segmentation_config_class(self):
|
|
1419
|
+
"""Register a configuration class for a use case."""
|
|
1420
|
+
try:
|
|
1421
|
+
from ..usecases.plaque_segmentation_img import PlaqueSegmentationConfig
|
|
1422
|
+
return PlaqueSegmentationConfig
|
|
1423
|
+
except ImportError:
|
|
1424
|
+
return None
|
|
1425
|
+
|
|
1426
|
+
def skin_cancer_classification_config_class(self):
|
|
1427
|
+
"""Register a configuration class for a use case."""
|
|
1428
|
+
try:
|
|
1429
|
+
from ..usecases.skin_cancer_classification_img import SkinCancerClassificationConfig
|
|
1430
|
+
return SkinCancerClassificationConfig
|
|
1431
|
+
except ImportError:
|
|
1432
|
+
return None
|
|
1433
|
+
|
|
1434
|
+
def cardiomegaly_classification_config_class(self):
|
|
1435
|
+
"""Register a configuration class for a use case."""
|
|
1436
|
+
try:
|
|
1437
|
+
from ..usecases.cardiomegaly_classification import CardiomegalyConfig
|
|
1438
|
+
return CardiomegalyConfig
|
|
1439
|
+
except ImportError:
|
|
1440
|
+
return None
|
|
1441
|
+
|
|
1442
|
+
def histopathological_cancer_detection_config_class(self):
|
|
1443
|
+
"""Register a configuration class for a use case."""
|
|
1444
|
+
try:
|
|
1445
|
+
from ..usecases.Histopathological_Cancer_Detection_img import HistopathologicalCancerDetectionConfig
|
|
1446
|
+
return HistopathologicalCancerDetectionConfig
|
|
1447
|
+
except ImportError:
|
|
1448
|
+
return None
|
|
1449
|
+
|
|
1450
|
+
def cell_microscopy_segmentation_config_class(self):
|
|
1451
|
+
"""Register a configuration class for a use case."""
|
|
1452
|
+
try:
|
|
1453
|
+
from ..usecases.cell_microscopy_segmentation import CellMicroscopyConfig
|
|
1454
|
+
return CellMicroscopyConfig
|
|
1455
|
+
except ImportError:
|
|
1456
|
+
return None
|
|
1457
|
+
|
|
1458
|
+
def underground_pipeline_defect_config_class(self):
|
|
1459
|
+
"""Register a configuration class for a use case."""
|
|
1460
|
+
try:
|
|
1461
|
+
from ..usecases.underground_pipeline_defect_detection import UndergroundPipelineDefectConfig
|
|
1462
|
+
return UndergroundPipelineDefectConfig
|
|
1463
|
+
except ImportError:
|
|
1464
|
+
return None
|
|
1465
|
+
|
|
1466
|
+
def _filter_kwargs_for_config(self, config_class: type, kwargs: Dict[str, Any]) -> Dict[str, Any]:
|
|
1467
|
+
"""
|
|
1468
|
+
Filter kwargs to only include valid parameters for the config class.
|
|
1469
|
+
|
|
1470
|
+
Args:
|
|
1471
|
+
config_class: The config class
|
|
1472
|
+
kwargs: Dictionary of parameters
|
|
1473
|
+
|
|
1474
|
+
Returns:
|
|
1475
|
+
Filtered kwargs
|
|
1476
|
+
"""
|
|
1477
|
+
return filter_config_kwargs(config_class, kwargs)
|
|
1478
|
+
|
|
1479
|
+
def create_config(self, usecase: str, category: Optional[str] = None, **kwargs) -> BaseConfig:
|
|
1480
|
+
"""
|
|
1481
|
+
Create configuration for a specific use case.
|
|
1482
|
+
|
|
1483
|
+
Args:
|
|
1484
|
+
usecase: Use case name
|
|
1485
|
+
category: Optional category override
|
|
1486
|
+
**kwargs: Configuration parameters
|
|
1487
|
+
|
|
1488
|
+
Returns:
|
|
1489
|
+
BaseConfig: Created configuration
|
|
1490
|
+
|
|
1491
|
+
Raises:
|
|
1492
|
+
ConfigValidationError: If configuration is invalid
|
|
1493
|
+
"""
|
|
1494
|
+
# Filter out common non-config parameters that should never be passed to configs
|
|
1495
|
+
common_non_config_params = [
|
|
1496
|
+
'deployment_id', 'stream_key', 'stream_id', 'camera_id', 'server_id',
|
|
1497
|
+
'inference_id', 'timestamp', 'frame_id', 'frame_number', 'request_id',
|
|
1498
|
+
'user_id', 'tenant_id', 'organization_id', 'app_name', 'app_id'
|
|
1499
|
+
]
|
|
1500
|
+
for param in common_non_config_params:
|
|
1501
|
+
if param in kwargs:
|
|
1502
|
+
logger.debug(f"Removing non-config parameter '{param}' from config creation")
|
|
1503
|
+
kwargs.pop(param, None)
|
|
1504
|
+
|
|
1505
|
+
if usecase == "people_counting":
|
|
1506
|
+
# Handle nested configurations
|
|
1507
|
+
zone_config = kwargs.pop("zone_config", None)
|
|
1508
|
+
if zone_config and isinstance(zone_config, dict):
|
|
1509
|
+
zone_config = ZoneConfig(**zone_config)
|
|
1510
|
+
|
|
1511
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1512
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1513
|
+
alert_config = AlertConfig(**alert_config)
|
|
1514
|
+
|
|
1515
|
+
# Filter kwargs to only include valid parameters
|
|
1516
|
+
filtered_kwargs = self._filter_kwargs_for_config(PeopleCountingConfig, kwargs)
|
|
1517
|
+
|
|
1518
|
+
config = PeopleCountingConfig(
|
|
1519
|
+
category=category or "general",
|
|
1520
|
+
usecase=usecase,
|
|
1521
|
+
zone_config=zone_config,
|
|
1522
|
+
alert_config=alert_config,
|
|
1523
|
+
**filtered_kwargs
|
|
1524
|
+
)
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
elif usecase == "people_tracking":
|
|
1528
|
+
# Handle nested configurations
|
|
1529
|
+
zone_config = kwargs.pop("zone_config", None)
|
|
1530
|
+
if zone_config and isinstance(zone_config, dict):
|
|
1531
|
+
zone_config = ZoneConfig(**zone_config)
|
|
1532
|
+
|
|
1533
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1534
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1535
|
+
alert_config = AlertConfig(**alert_config)
|
|
1536
|
+
|
|
1537
|
+
# Filter kwargs to only include valid parameters
|
|
1538
|
+
filtered_kwargs = self._filter_kwargs_for_config(PeopleTrackingConfig, kwargs)
|
|
1539
|
+
|
|
1540
|
+
config = PeopleTrackingConfig(
|
|
1541
|
+
category=category or "general",
|
|
1542
|
+
usecase=usecase,
|
|
1543
|
+
zone_config=zone_config,
|
|
1544
|
+
alert_config=alert_config,
|
|
1545
|
+
**filtered_kwargs
|
|
1546
|
+
)
|
|
1547
|
+
|
|
1548
|
+
elif usecase == "intrusion_detection":
|
|
1549
|
+
# Handle nested configurations
|
|
1550
|
+
zone_config = kwargs.pop("zone_config", None)
|
|
1551
|
+
if zone_config and isinstance(zone_config, dict):
|
|
1552
|
+
zone_config = ZoneConfig(**zone_config)
|
|
1553
|
+
|
|
1554
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1555
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1556
|
+
alert_config = AlertConfig(**alert_config)
|
|
1557
|
+
|
|
1558
|
+
# Filter kwargs to only include valid parameters
|
|
1559
|
+
filtered_kwargs = self._filter_kwargs_for_config(IntrusionConfig, kwargs)
|
|
1560
|
+
|
|
1561
|
+
config = IntrusionConfig(
|
|
1562
|
+
category=category or "security",
|
|
1563
|
+
usecase=usecase,
|
|
1564
|
+
zone_config=zone_config,
|
|
1565
|
+
alert_config=alert_config,
|
|
1566
|
+
**filtered_kwargs
|
|
1567
|
+
)
|
|
1568
|
+
|
|
1569
|
+
elif usecase == "proximity_detection":
|
|
1570
|
+
# Handle nested configurations
|
|
1571
|
+
zone_config = kwargs.pop("zone_config", None)
|
|
1572
|
+
if zone_config and isinstance(zone_config, dict):
|
|
1573
|
+
zone_config = ZoneConfig(**zone_config)
|
|
1574
|
+
|
|
1575
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1576
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1577
|
+
alert_config = AlertConfig(**alert_config)
|
|
1578
|
+
|
|
1579
|
+
# Filter kwargs to only include valid parameters
|
|
1580
|
+
filtered_kwargs = self._filter_kwargs_for_config(ProximityConfig, kwargs)
|
|
1581
|
+
|
|
1582
|
+
config = ProximityConfig(
|
|
1583
|
+
category=category or "security",
|
|
1584
|
+
usecase=usecase,
|
|
1585
|
+
zone_config=zone_config,
|
|
1586
|
+
alert_config=alert_config,
|
|
1587
|
+
**filtered_kwargs
|
|
1588
|
+
)
|
|
1589
|
+
|
|
1590
|
+
elif usecase in ["customer_service", "advanced_customer_service"]:
|
|
1591
|
+
# Handle nested configurations
|
|
1592
|
+
tracking_config = kwargs.pop("tracking_config", None)
|
|
1593
|
+
if tracking_config and isinstance(tracking_config, dict):
|
|
1594
|
+
tracking_config = TrackingConfig(**tracking_config)
|
|
1595
|
+
|
|
1596
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1597
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1598
|
+
alert_config = AlertConfig(**alert_config)
|
|
1599
|
+
|
|
1600
|
+
# Filter kwargs to only include valid parameters
|
|
1601
|
+
filtered_kwargs = self._filter_kwargs_for_config(CustomerServiceConfig, kwargs)
|
|
1602
|
+
|
|
1603
|
+
config = CustomerServiceConfig(
|
|
1604
|
+
category=category or "sales",
|
|
1605
|
+
usecase=usecase,
|
|
1606
|
+
tracking_config=tracking_config,
|
|
1607
|
+
alert_config=alert_config,
|
|
1608
|
+
**filtered_kwargs
|
|
1609
|
+
)
|
|
1610
|
+
elif usecase == "basic_counting_tracking":
|
|
1611
|
+
# Import here to avoid circular import
|
|
1612
|
+
from ..usecases.basic_counting_tracking import BasicCountingTrackingConfig
|
|
1613
|
+
|
|
1614
|
+
# Handle nested configurations
|
|
1615
|
+
tracking_config = kwargs.pop("tracking_config", None)
|
|
1616
|
+
if tracking_config and isinstance(tracking_config, dict):
|
|
1617
|
+
tracking_config = TrackingConfig(**tracking_config)
|
|
1618
|
+
|
|
1619
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1620
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1621
|
+
alert_config = AlertConfig(**alert_config)
|
|
1622
|
+
|
|
1623
|
+
# Extract basic counting tracking specific parameters
|
|
1624
|
+
target_categories = kwargs.pop("target_categories", None)
|
|
1625
|
+
zones = kwargs.pop("zones", None)
|
|
1626
|
+
tracking_method = kwargs.pop("tracking_method", "kalman")
|
|
1627
|
+
max_age = kwargs.pop("max_age", 30)
|
|
1628
|
+
min_hits = kwargs.pop("min_hits", 3)
|
|
1629
|
+
count_thresholds = kwargs.pop("count_thresholds", None)
|
|
1630
|
+
zone_thresholds = kwargs.pop("zone_thresholds", None)
|
|
1631
|
+
alert_cooldown = kwargs.pop("alert_cooldown", 60.0)
|
|
1632
|
+
enable_unique_counting = kwargs.pop("enable_unique_counting", True)
|
|
1633
|
+
|
|
1634
|
+
# Filter kwargs to only include valid parameters
|
|
1635
|
+
filtered_kwargs = self._filter_kwargs_for_config(BasicCountingTrackingConfig, kwargs)
|
|
1636
|
+
|
|
1637
|
+
config = BasicCountingTrackingConfig(
|
|
1638
|
+
category=category or "general",
|
|
1639
|
+
usecase=usecase,
|
|
1640
|
+
target_categories=target_categories,
|
|
1641
|
+
zones=zones,
|
|
1642
|
+
tracking_method=tracking_method,
|
|
1643
|
+
max_age=max_age,
|
|
1644
|
+
min_hits=min_hits,
|
|
1645
|
+
count_thresholds=count_thresholds,
|
|
1646
|
+
zone_thresholds=zone_thresholds,
|
|
1647
|
+
alert_cooldown=alert_cooldown,
|
|
1648
|
+
enable_unique_counting=enable_unique_counting,
|
|
1649
|
+
**filtered_kwargs
|
|
1650
|
+
)
|
|
1651
|
+
elif usecase == "license_plate_detection":
|
|
1652
|
+
# Import here to avoid circular import
|
|
1653
|
+
from ..usecases.license_plate_detection import LicensePlateConfig
|
|
1654
|
+
|
|
1655
|
+
# Handle nested configurations
|
|
1656
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1657
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1658
|
+
alert_config = AlertConfig(**alert_config)
|
|
1659
|
+
|
|
1660
|
+
# Filter kwargs to only include valid parameters
|
|
1661
|
+
filtered_kwargs = self._filter_kwargs_for_config(LicensePlateConfig, kwargs)
|
|
1662
|
+
|
|
1663
|
+
config = LicensePlateConfig(
|
|
1664
|
+
category=category or "vehicle",
|
|
1665
|
+
usecase=usecase,
|
|
1666
|
+
alert_config=alert_config,
|
|
1667
|
+
**filtered_kwargs
|
|
1668
|
+
)
|
|
1669
|
+
elif usecase == "parking_space_detection":
|
|
1670
|
+
# Import here to avoid circular import
|
|
1671
|
+
from ..usecases.parking_space_detection import ParkingSpaceConfig
|
|
1672
|
+
|
|
1673
|
+
# Handle nested configurations
|
|
1674
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1675
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1676
|
+
alert_config = AlertConfig(**alert_config)
|
|
1677
|
+
|
|
1678
|
+
# Filter kwargs to only include valid parameters
|
|
1679
|
+
filtered_kwargs = self._filter_kwargs_for_config(ParkingSpaceConfig, kwargs)
|
|
1680
|
+
|
|
1681
|
+
config = ParkingSpaceConfig(
|
|
1682
|
+
category=category or "parking_space",
|
|
1683
|
+
usecase=usecase,
|
|
1684
|
+
alert_config=alert_config,
|
|
1685
|
+
**filtered_kwargs
|
|
1686
|
+
)
|
|
1687
|
+
elif usecase == "field_mapping":
|
|
1688
|
+
# Import here to avoid circular import
|
|
1689
|
+
from ..usecases.field_mapping import FieldMappingConfig
|
|
1690
|
+
|
|
1691
|
+
# Handle nested configurations
|
|
1692
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1693
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1694
|
+
alert_config = AlertConfig(**alert_config)
|
|
1695
|
+
|
|
1696
|
+
# Filter kwargs to only include valid parameters
|
|
1697
|
+
filtered_kwargs = self._filter_kwargs_for_config(FieldMappingConfig, kwargs)
|
|
1698
|
+
|
|
1699
|
+
config = FieldMappingConfig(
|
|
1700
|
+
category=category or "infrastructure",
|
|
1701
|
+
usecase=usecase,
|
|
1702
|
+
alert_config=alert_config,
|
|
1703
|
+
**filtered_kwargs
|
|
1704
|
+
)
|
|
1705
|
+
|
|
1706
|
+
elif usecase == "leaf_disease_detection":
|
|
1707
|
+
# Import here to avoid circular import
|
|
1708
|
+
from ..usecases.leaf_disease import LeafDiseaseDetectionConfig
|
|
1709
|
+
|
|
1710
|
+
# Handle nested configurations
|
|
1711
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1712
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1713
|
+
alert_config = AlertConfig(**alert_config)
|
|
1714
|
+
|
|
1715
|
+
# Filter kwargs to only include valid parameters
|
|
1716
|
+
filtered_kwargs = self._filter_kwargs_for_config(LeafDiseaseDetectionConfig, kwargs)
|
|
1717
|
+
|
|
1718
|
+
config = LeafDiseaseDetectionConfig(
|
|
1719
|
+
category=category or "agriculture",
|
|
1720
|
+
usecase=usecase,
|
|
1721
|
+
alert_config=alert_config,
|
|
1722
|
+
**kwargs
|
|
1723
|
+
)
|
|
1724
|
+
elif usecase == "mask_detection":
|
|
1725
|
+
# Import here to avoid circular import
|
|
1726
|
+
from ..usecases.mask_detection import MaskDetectionConfig
|
|
1727
|
+
|
|
1728
|
+
# Handle nested configurations
|
|
1729
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1730
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1731
|
+
alert_config = AlertConfig(**alert_config)
|
|
1732
|
+
|
|
1733
|
+
config = MaskDetectionConfig(
|
|
1734
|
+
category=category or "mask_detection",
|
|
1735
|
+
usecase=usecase,
|
|
1736
|
+
alert_config=alert_config,
|
|
1737
|
+
**kwargs
|
|
1738
|
+
)
|
|
1739
|
+
elif usecase == "pipeline_detection":
|
|
1740
|
+
from ..usecases.pipeline_detection import PipelineDetectionConfig
|
|
1741
|
+
|
|
1742
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1743
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1744
|
+
alert_config = AlertConfig(**alert_config)
|
|
1745
|
+
|
|
1746
|
+
config = PipelineDetectionConfig(
|
|
1747
|
+
category=category or "pipeline_detection",
|
|
1748
|
+
usecase=usecase,
|
|
1749
|
+
alert_config=alert_config,
|
|
1750
|
+
**kwargs
|
|
1751
|
+
)
|
|
1752
|
+
elif usecase == "shoplifting_detection":
|
|
1753
|
+
# Import here to avoid circular import
|
|
1754
|
+
from ..usecases.shoplifting_detection import ShopliftingDetectionConfig
|
|
1755
|
+
|
|
1756
|
+
# Handle nested configurations
|
|
1757
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1758
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1759
|
+
alert_config = AlertConfig(**alert_config)
|
|
1760
|
+
|
|
1761
|
+
config = ShopliftingDetectionConfig(
|
|
1762
|
+
category=category or "mask_detection",
|
|
1763
|
+
usecase=usecase,
|
|
1764
|
+
alert_config=alert_config,
|
|
1765
|
+
**kwargs
|
|
1766
|
+
)
|
|
1767
|
+
|
|
1768
|
+
elif usecase == "fire_smoke_detection":
|
|
1769
|
+
# Import here to avoid circular import
|
|
1770
|
+
from ..usecases.fire_detection import FireSmokeConfig
|
|
1771
|
+
|
|
1772
|
+
# Handle nested configurations
|
|
1773
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1774
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1775
|
+
alert_config = AlertConfig(**alert_config)
|
|
1776
|
+
|
|
1777
|
+
config = FireSmokeConfig(
|
|
1778
|
+
category=category or "normal",
|
|
1779
|
+
usecase=usecase,
|
|
1780
|
+
alert_config=alert_config,
|
|
1781
|
+
**kwargs
|
|
1782
|
+
)
|
|
1783
|
+
|
|
1784
|
+
elif usecase == "solar_panel":
|
|
1785
|
+
# Import here to avoid circular import
|
|
1786
|
+
from ..usecases.solar_panel import SolarPanelConfig
|
|
1787
|
+
|
|
1788
|
+
# Handle nested configurations
|
|
1789
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1790
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1791
|
+
alert_config = AlertConfig(**alert_config)
|
|
1792
|
+
|
|
1793
|
+
config = SolarPanelConfig(
|
|
1794
|
+
category=category or "energy",
|
|
1795
|
+
usecase=usecase,
|
|
1796
|
+
alert_config=alert_config,
|
|
1797
|
+
**kwargs
|
|
1798
|
+
)
|
|
1799
|
+
elif usecase == "wound_segmentation":
|
|
1800
|
+
# Import here to avoid circular import
|
|
1801
|
+
from ..usecases.wound_segmentation import WoundConfig
|
|
1802
|
+
|
|
1803
|
+
# Handle nested configurations
|
|
1804
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1805
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1806
|
+
alert_config = AlertConfig(**alert_config)
|
|
1807
|
+
|
|
1808
|
+
config = WoundConfig(
|
|
1809
|
+
category=category or "energy",
|
|
1810
|
+
usecase=usecase,
|
|
1811
|
+
alert_config=alert_config,
|
|
1812
|
+
**kwargs
|
|
1813
|
+
)
|
|
1814
|
+
|
|
1815
|
+
elif usecase == "car_damage_detection":
|
|
1816
|
+
# Import here to avoid circular import
|
|
1817
|
+
from ..usecases.car_damage_detection import CarDamageConfig
|
|
1818
|
+
|
|
1819
|
+
# Handle nested configurations
|
|
1820
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1821
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1822
|
+
alert_config = AlertConfig(**alert_config)
|
|
1823
|
+
|
|
1824
|
+
config = CarDamageConfig(
|
|
1825
|
+
category=category or "normal",
|
|
1826
|
+
usecase=usecase,
|
|
1827
|
+
alert_config=alert_config,
|
|
1828
|
+
**kwargs
|
|
1829
|
+
)
|
|
1830
|
+
|
|
1831
|
+
elif usecase == "pothole_segmentation":
|
|
1832
|
+
# Import here to avoid circular import
|
|
1833
|
+
from ..usecases.pothole_segmentation import PotholeConfig
|
|
1834
|
+
|
|
1835
|
+
# Handle nested configurations
|
|
1836
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1837
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1838
|
+
alert_config = AlertConfig(**alert_config)
|
|
1839
|
+
|
|
1840
|
+
config = PotholeConfig(
|
|
1841
|
+
category=category or "normal",
|
|
1842
|
+
usecase=usecase,
|
|
1843
|
+
alert_config=alert_config,
|
|
1844
|
+
**kwargs
|
|
1845
|
+
)
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
elif usecase == "flare_analysis":
|
|
1849
|
+
# Import here to avoid circular import
|
|
1850
|
+
from ..usecases.flare_analysis import FlareAnalysisConfig
|
|
1851
|
+
|
|
1852
|
+
# Handle nested configurations
|
|
1853
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1854
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1855
|
+
alert_config = AlertConfig(**alert_config)
|
|
1856
|
+
|
|
1857
|
+
config = FlareAnalysisConfig(
|
|
1858
|
+
category=category or "normal",
|
|
1859
|
+
usecase=usecase,
|
|
1860
|
+
alert_config=alert_config,
|
|
1861
|
+
**kwargs
|
|
1862
|
+
)
|
|
1863
|
+
|
|
1864
|
+
elif usecase == "chicken_pose_detection":
|
|
1865
|
+
# Import here to avoid circular import
|
|
1866
|
+
from ..usecases.chicken_pose_detection import ChickenPoseDetectionConfig
|
|
1867
|
+
|
|
1868
|
+
# Handle nested configurations
|
|
1869
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1870
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1871
|
+
alert_config = AlertConfig(**alert_config)
|
|
1872
|
+
|
|
1873
|
+
config = ChickenPoseDetectionConfig(
|
|
1874
|
+
category=category or "agriculture",
|
|
1875
|
+
usecase=usecase,
|
|
1876
|
+
alert_config=alert_config,
|
|
1877
|
+
**kwargs
|
|
1878
|
+
)
|
|
1879
|
+
|
|
1880
|
+
elif usecase == "fruit_monitoring":
|
|
1881
|
+
# Import here to avoid circular import
|
|
1882
|
+
from ..usecases.banana_defect_detection import BananaMonitoringConfig
|
|
1883
|
+
|
|
1884
|
+
# Handle nested configurations
|
|
1885
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1886
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1887
|
+
alert_config = AlertConfig(**alert_config)
|
|
1888
|
+
|
|
1889
|
+
config = BananaMonitoringConfig(
|
|
1890
|
+
category=category or "agriculture",
|
|
1891
|
+
usecase=usecase,
|
|
1892
|
+
alert_config=alert_config,
|
|
1893
|
+
**kwargs
|
|
1894
|
+
)
|
|
1895
|
+
elif usecase == "abandoned_object_detection":
|
|
1896
|
+
# Import here to avoid circular import
|
|
1897
|
+
from ..usecases.abandoned_object_detection import AbandonedObjectConfig
|
|
1898
|
+
|
|
1899
|
+
# Handle nested configurations
|
|
1900
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1901
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1902
|
+
alert_config = AlertConfig(**alert_config)
|
|
1903
|
+
|
|
1904
|
+
config = AbandonedObjectConfig(
|
|
1905
|
+
category=category or "security",
|
|
1906
|
+
usecase=usecase,
|
|
1907
|
+
alert_config=alert_config,
|
|
1908
|
+
**kwargs
|
|
1909
|
+
)
|
|
1910
|
+
|
|
1911
|
+
elif usecase == "lane_detection":
|
|
1912
|
+
# Import here to avoid circular import
|
|
1913
|
+
from ..usecases.road_lane_detection import LaneDetectionConfig
|
|
1914
|
+
|
|
1915
|
+
# Handle nested configurations
|
|
1916
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1917
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1918
|
+
alert_config = AlertConfig(**alert_config)
|
|
1919
|
+
|
|
1920
|
+
config = LaneDetectionConfig(
|
|
1921
|
+
category=category or "traffic",
|
|
1922
|
+
usecase=usecase,
|
|
1923
|
+
alert_config=alert_config,
|
|
1924
|
+
**kwargs
|
|
1925
|
+
)
|
|
1926
|
+
|
|
1927
|
+
elif usecase == "shelf_inventory":
|
|
1928
|
+
# Import here to avoid circular import
|
|
1929
|
+
from ..usecases.shelf_inventory_detection import ShelfInventoryConfig
|
|
1930
|
+
|
|
1931
|
+
# Handle nested configurations
|
|
1932
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1933
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1934
|
+
alert_config = AlertConfig(**alert_config)
|
|
1935
|
+
|
|
1936
|
+
config = ShelfInventoryConfig(
|
|
1937
|
+
category=category or "retail",
|
|
1938
|
+
usecase=usecase,
|
|
1939
|
+
alert_config=alert_config,
|
|
1940
|
+
**kwargs
|
|
1941
|
+
)
|
|
1942
|
+
|
|
1943
|
+
elif usecase == "anti_spoofing_detection":
|
|
1944
|
+
# Import here to avoid circular import
|
|
1945
|
+
from ..usecases.anti_spoofing_detection import AntiSpoofingDetectionConfig
|
|
1946
|
+
|
|
1947
|
+
# Handle nested configurations
|
|
1948
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1949
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1950
|
+
alert_config = AlertConfig(**alert_config)
|
|
1951
|
+
|
|
1952
|
+
config = AntiSpoofingDetectionConfig(
|
|
1953
|
+
category=category or "security",
|
|
1954
|
+
usecase=usecase,
|
|
1955
|
+
alert_config=alert_config,
|
|
1956
|
+
**kwargs
|
|
1957
|
+
)
|
|
1958
|
+
|
|
1959
|
+
elif usecase == "theft_detection":
|
|
1960
|
+
# Import here to avoid circular import
|
|
1961
|
+
from ..usecases.theft_detection import TheftDetectionConfig
|
|
1962
|
+
|
|
1963
|
+
# Handle nested configurations
|
|
1964
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1965
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1966
|
+
alert_config = AlertConfig(**alert_config)
|
|
1967
|
+
|
|
1968
|
+
config = TheftDetectionConfig(
|
|
1969
|
+
category=category or "security",
|
|
1970
|
+
usecase=usecase,
|
|
1971
|
+
alert_config=alert_config,
|
|
1972
|
+
**kwargs
|
|
1973
|
+
)
|
|
1974
|
+
|
|
1975
|
+
elif usecase == "weapon_detection":
|
|
1976
|
+
# Import here to avoid circular import
|
|
1977
|
+
from ..usecases.weapon_detection import WeaponDetectionConfig
|
|
1978
|
+
|
|
1979
|
+
# Handle nested configurations
|
|
1980
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1981
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1982
|
+
alert_config = AlertConfig(**alert_config)
|
|
1983
|
+
|
|
1984
|
+
config = WeaponDetectionConfig(
|
|
1985
|
+
category=category or "security",
|
|
1986
|
+
usecase=usecase,
|
|
1987
|
+
alert_config=alert_config,
|
|
1988
|
+
**kwargs
|
|
1989
|
+
)
|
|
1990
|
+
|
|
1991
|
+
elif usecase == "traffic_sign_monitoring":
|
|
1992
|
+
# Import here to avoid circular import
|
|
1993
|
+
from ..usecases.traffic_sign_monitoring import TrafficSignMonitoringConfig
|
|
1994
|
+
|
|
1995
|
+
# Handle nested configurations
|
|
1996
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
1997
|
+
if alert_config and isinstance(alert_config, dict):
|
|
1998
|
+
alert_config = AlertConfig(**alert_config)
|
|
1999
|
+
|
|
2000
|
+
config = TrafficSignMonitoringConfig(
|
|
2001
|
+
category=category or "traffic",
|
|
2002
|
+
usecase=usecase,
|
|
2003
|
+
alert_config=alert_config,
|
|
2004
|
+
**kwargs
|
|
2005
|
+
)
|
|
2006
|
+
|
|
2007
|
+
elif usecase == "vehicle_monitoring":
|
|
2008
|
+
# Import here to avoid circular import
|
|
2009
|
+
from ..usecases.vehicle_monitoring import VehicleMonitoringConfig
|
|
2010
|
+
|
|
2011
|
+
# Handle nested configurations
|
|
2012
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2013
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2014
|
+
alert_config = AlertConfig(**alert_config)
|
|
2015
|
+
|
|
2016
|
+
config = VehicleMonitoringConfig(
|
|
2017
|
+
category=category or "traffic",
|
|
2018
|
+
usecase=usecase,
|
|
2019
|
+
alert_config=alert_config,
|
|
2020
|
+
**kwargs
|
|
2021
|
+
)
|
|
2022
|
+
|
|
2023
|
+
elif usecase == "drone_traffic_monitoring":
|
|
2024
|
+
# Import here to avoid circular import
|
|
2025
|
+
from ..usecases.drone_traffic_monitoring import VehiclePeopleDroneMonitoringConfig
|
|
2026
|
+
|
|
2027
|
+
# Handle nested configurations
|
|
2028
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2029
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2030
|
+
alert_config = AlertConfig(**alert_config)
|
|
2031
|
+
|
|
2032
|
+
config = VehiclePeopleDroneMonitoringConfig(
|
|
2033
|
+
category=category or "traffic",
|
|
2034
|
+
usecase=usecase,
|
|
2035
|
+
alert_config=alert_config,
|
|
2036
|
+
**kwargs
|
|
2037
|
+
)
|
|
2038
|
+
|
|
2039
|
+
elif usecase == "ppe_compliance_detection":
|
|
2040
|
+
# Import here to avoid circular import
|
|
2041
|
+
from ..usecases.ppe_compliance import PPEComplianceConfig
|
|
2042
|
+
# Handle nested configurations
|
|
2043
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2044
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2045
|
+
alert_config = AlertConfig(**alert_config)
|
|
2046
|
+
config = PPEComplianceConfig(
|
|
2047
|
+
category=category or "ppe",
|
|
2048
|
+
usecase=usecase,
|
|
2049
|
+
alert_config=alert_config,
|
|
2050
|
+
**kwargs
|
|
2051
|
+
)
|
|
2052
|
+
elif usecase == "color_detection":
|
|
2053
|
+
# Import here to avoid circular import
|
|
2054
|
+
from ..usecases.color_detection import ColorDetectionConfig
|
|
2055
|
+
|
|
2056
|
+
# Handle nested configurations
|
|
2057
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2058
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2059
|
+
alert_config = AlertConfig(**alert_config)
|
|
2060
|
+
|
|
2061
|
+
# Filter kwargs to only include valid parameters
|
|
2062
|
+
filtered_kwargs = self._filter_kwargs_for_config(ColorDetectionConfig, kwargs)
|
|
2063
|
+
|
|
2064
|
+
config = ColorDetectionConfig(
|
|
2065
|
+
category=category or "visual_appearance",
|
|
2066
|
+
usecase=usecase,
|
|
2067
|
+
alert_config=alert_config,
|
|
2068
|
+
**filtered_kwargs
|
|
2069
|
+
)
|
|
2070
|
+
elif usecase == "video_color_classification":
|
|
2071
|
+
# Alias for color_detection - Import here to avoid circular import
|
|
2072
|
+
from ..usecases.color_detection import ColorDetectionConfig
|
|
2073
|
+
|
|
2074
|
+
# Handle nested configurations
|
|
2075
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2076
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2077
|
+
alert_config = AlertConfig(**alert_config)
|
|
2078
|
+
|
|
2079
|
+
# Filter kwargs to only include valid parameters
|
|
2080
|
+
filtered_kwargs = self._filter_kwargs_for_config(ColorDetectionConfig, kwargs)
|
|
2081
|
+
|
|
2082
|
+
config = ColorDetectionConfig(
|
|
2083
|
+
category=category or "visual_appearance",
|
|
2084
|
+
usecase="color_detection", # Use canonical name internally
|
|
2085
|
+
alert_config=alert_config,
|
|
2086
|
+
**filtered_kwargs
|
|
2087
|
+
)
|
|
2088
|
+
elif usecase == "ppe_compliance_detection":
|
|
2089
|
+
# Import here to avoid circular import
|
|
2090
|
+
from ..usecases.ppe_compliance import PPEComplianceConfig
|
|
2091
|
+
# Handle nested configurations
|
|
2092
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2093
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2094
|
+
alert_config = AlertConfig(**alert_config)
|
|
2095
|
+
config = PPEComplianceConfig(
|
|
2096
|
+
category=category or "ppe",
|
|
2097
|
+
usecase=usecase,
|
|
2098
|
+
alert_config=alert_config,
|
|
2099
|
+
**kwargs
|
|
2100
|
+
)
|
|
2101
|
+
elif usecase == "face_emotion":
|
|
2102
|
+
# Import here to avoid circular import
|
|
2103
|
+
from ..usecases.face_emotion import FaceEmotionConfig
|
|
2104
|
+
|
|
2105
|
+
# Handle nested configurations
|
|
2106
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2107
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2108
|
+
alert_config = AlertConfig(**alert_config)
|
|
2109
|
+
|
|
2110
|
+
config = FaceEmotionConfig(
|
|
2111
|
+
category=category or "general",
|
|
2112
|
+
usecase=usecase,
|
|
2113
|
+
alert_config=alert_config,
|
|
2114
|
+
**kwargs
|
|
2115
|
+
)
|
|
2116
|
+
|
|
2117
|
+
elif usecase == "pedestrian_detection":
|
|
2118
|
+
# Import here to avoid circular import
|
|
2119
|
+
from ..usecases.pedestrian_detection import PedestrianDetectionConfig
|
|
2120
|
+
|
|
2121
|
+
# Handle nested configurations
|
|
2122
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2123
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2124
|
+
alert_config = AlertConfig(**alert_config)
|
|
2125
|
+
config = PedestrianDetectionConfig(
|
|
2126
|
+
category=category or "pedestrian",
|
|
2127
|
+
usecase=usecase,
|
|
2128
|
+
alert_config=alert_config,
|
|
2129
|
+
**kwargs
|
|
2130
|
+
)
|
|
2131
|
+
|
|
2132
|
+
|
|
2133
|
+
elif usecase == "underwater_pollution_detection":
|
|
2134
|
+
# Import here to avoid circular import
|
|
2135
|
+
from ..usecases.underwater_pollution_detection import UnderwaterPlasticConfig
|
|
2136
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2137
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2138
|
+
alert_config = AlertConfig(**alert_config)
|
|
2139
|
+
config = UnderwaterPlasticConfig(
|
|
2140
|
+
category=category or "pollution",
|
|
2141
|
+
usecase=usecase,
|
|
2142
|
+
alert_config=alert_config,
|
|
2143
|
+
**kwargs
|
|
2144
|
+
)
|
|
2145
|
+
elif usecase == "weld_defect_detection":
|
|
2146
|
+
# Import here to avoid circular import
|
|
2147
|
+
from ..usecases.weld_defect_detection import WeldDefectConfig
|
|
2148
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2149
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2150
|
+
alert_config = AlertConfig(**alert_config)
|
|
2151
|
+
config = WeldDefectConfig(
|
|
2152
|
+
category=category or "weld",
|
|
2153
|
+
usecase=usecase,
|
|
2154
|
+
alert_config=alert_config,
|
|
2155
|
+
**kwargs
|
|
2156
|
+
)
|
|
2157
|
+
|
|
2158
|
+
elif usecase == "age_detection":
|
|
2159
|
+
# Import here to avoid circular import
|
|
2160
|
+
from ..usecases.age_detection import AgeDetectionConfig
|
|
2161
|
+
|
|
2162
|
+
# Handle nested configurations
|
|
2163
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2164
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2165
|
+
alert_config = AlertConfig(**alert_config)
|
|
2166
|
+
|
|
2167
|
+
config = AgeDetectionConfig(
|
|
2168
|
+
category=category or "general",
|
|
2169
|
+
usecase=usecase,
|
|
2170
|
+
alert_config=alert_config,
|
|
2171
|
+
**kwargs
|
|
2172
|
+
)
|
|
2173
|
+
|
|
2174
|
+
elif usecase == "price_tag_detection":
|
|
2175
|
+
# Import here to avoid circular import
|
|
2176
|
+
from ..usecases.price_tag_detection import PriceTagConfig
|
|
2177
|
+
|
|
2178
|
+
# Handle nested configurations
|
|
2179
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2180
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2181
|
+
alert_config = AlertConfig(**alert_config)
|
|
2182
|
+
|
|
2183
|
+
config = PriceTagConfig(
|
|
2184
|
+
category=category or "retail",
|
|
2185
|
+
usecase=usecase,
|
|
2186
|
+
alert_config=alert_config,
|
|
2187
|
+
**kwargs
|
|
2188
|
+
)
|
|
2189
|
+
elif usecase == "distracted_driver_detection":
|
|
2190
|
+
# Import here to avoid circular import
|
|
2191
|
+
from ..usecases.distracted_driver_detection import DistractedDriverConfig
|
|
2192
|
+
|
|
2193
|
+
# Handle nested configurations
|
|
2194
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2195
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2196
|
+
alert_config = AlertConfig(**alert_config)
|
|
2197
|
+
|
|
2198
|
+
config = DistractedDriverConfig(
|
|
2199
|
+
category=category or "automobile",
|
|
2200
|
+
usecase=usecase,
|
|
2201
|
+
alert_config=alert_config,
|
|
2202
|
+
**kwargs
|
|
2203
|
+
)
|
|
2204
|
+
|
|
2205
|
+
elif usecase == "emergency_vehicle_detection":
|
|
2206
|
+
# Import here to avoid circular import
|
|
2207
|
+
from ..usecases.emergency_vehicle_detection import EmergencyVehicleConfig
|
|
2208
|
+
|
|
2209
|
+
# Handle nested configurations
|
|
2210
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2211
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2212
|
+
alert_config = AlertConfig(**alert_config)
|
|
2213
|
+
|
|
2214
|
+
config = EmergencyVehicleConfig(
|
|
2215
|
+
category=category or "traffic",
|
|
2216
|
+
usecase=usecase,
|
|
2217
|
+
alert_config=alert_config,
|
|
2218
|
+
**kwargs
|
|
2219
|
+
)
|
|
2220
|
+
|
|
2221
|
+
elif usecase == "crop_weed_detection":
|
|
2222
|
+
# Import here to avoid circular import
|
|
2223
|
+
from ..usecases.crop_weed_detection import CropWeedDetectionConfig
|
|
2224
|
+
|
|
2225
|
+
# Handle nested configurations
|
|
2226
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2227
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2228
|
+
alert_config = AlertConfig(**alert_config)
|
|
2229
|
+
|
|
2230
|
+
config = CropWeedDetectionConfig(
|
|
2231
|
+
category=category or "agriculture",
|
|
2232
|
+
usecase=usecase,
|
|
2233
|
+
alert_config=alert_config,
|
|
2234
|
+
**kwargs
|
|
2235
|
+
)
|
|
2236
|
+
|
|
2237
|
+
elif usecase == "child_monitoring":
|
|
2238
|
+
# Import here to avoid circular import
|
|
2239
|
+
from ..usecases.child_monitoring import ChildMonitoringConfig
|
|
2240
|
+
|
|
2241
|
+
# Handle nested configurations
|
|
2242
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2243
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2244
|
+
alert_config = AlertConfig(**alert_config)
|
|
2245
|
+
|
|
2246
|
+
config = ChildMonitoringConfig(
|
|
2247
|
+
category=category or "security",
|
|
2248
|
+
usecase=usecase,
|
|
2249
|
+
alert_config=alert_config,
|
|
2250
|
+
**kwargs
|
|
2251
|
+
)
|
|
2252
|
+
|
|
2253
|
+
elif usecase == "gender_detection":
|
|
2254
|
+
# Import here to avoid circular import
|
|
2255
|
+
from ..usecases.gender_detection import GenderDetectionConfig
|
|
2256
|
+
|
|
2257
|
+
# Handle nested configurations
|
|
2258
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2259
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2260
|
+
alert_config = AlertConfig(**alert_config)
|
|
2261
|
+
|
|
2262
|
+
config = GenderDetectionConfig(
|
|
2263
|
+
category=category or "general",
|
|
2264
|
+
usecase=usecase,
|
|
2265
|
+
alert_config=alert_config,
|
|
2266
|
+
**kwargs
|
|
2267
|
+
)
|
|
2268
|
+
|
|
2269
|
+
elif usecase == "concrete_crack_detection":
|
|
2270
|
+
# Import here to avoid circular import
|
|
2271
|
+
from ..usecases.concrete_crack_detection import ConcreteCrackConfig
|
|
2272
|
+
|
|
2273
|
+
# Handle nested configurations
|
|
2274
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2275
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2276
|
+
alert_config = AlertConfig(**alert_config)
|
|
2277
|
+
|
|
2278
|
+
config = ConcreteCrackConfig(
|
|
2279
|
+
category=category or "general",
|
|
2280
|
+
usecase=usecase,
|
|
2281
|
+
alert_config=alert_config,
|
|
2282
|
+
**kwargs
|
|
2283
|
+
)
|
|
2284
|
+
|
|
2285
|
+
elif usecase == "fashion_detection":
|
|
2286
|
+
# Import here to avoid circular import
|
|
2287
|
+
from ..usecases.fashion_detection import FashionDetectionConfig
|
|
2288
|
+
|
|
2289
|
+
# Handle nested configurations
|
|
2290
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2291
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2292
|
+
alert_config = AlertConfig(**alert_config)
|
|
2293
|
+
|
|
2294
|
+
config = FashionDetectionConfig(
|
|
2295
|
+
category=category or "retail",
|
|
2296
|
+
usecase=usecase,
|
|
2297
|
+
alert_config=alert_config,
|
|
2298
|
+
**kwargs
|
|
2299
|
+
)
|
|
2300
|
+
|
|
2301
|
+
elif usecase == "warehouse_object_segmentation":
|
|
2302
|
+
# Import here to avoid circular import
|
|
2303
|
+
from ..usecases.warehouse_object_segmentation import WarehouseObjectConfig
|
|
2304
|
+
|
|
2305
|
+
# Handle nested configurations
|
|
2306
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2307
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2308
|
+
alert_config = AlertConfig(**alert_config)
|
|
2309
|
+
|
|
2310
|
+
config = WarehouseObjectConfig(
|
|
2311
|
+
category=category or "retail",
|
|
2312
|
+
usecase=usecase,
|
|
2313
|
+
alert_config=alert_config,
|
|
2314
|
+
**kwargs
|
|
2315
|
+
)
|
|
2316
|
+
|
|
2317
|
+
elif usecase == "shopping_cart_analysis":
|
|
2318
|
+
# Import here to avoid circular import
|
|
2319
|
+
from ..usecases.shopping_cart_analysis import ShoppingCartConfig
|
|
2320
|
+
|
|
2321
|
+
# Handle nested configurations
|
|
2322
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2323
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2324
|
+
alert_config = AlertConfig(**alert_config)
|
|
2325
|
+
|
|
2326
|
+
config = ShoppingCartConfig(
|
|
2327
|
+
category=category or "retail",
|
|
2328
|
+
usecase=usecase,
|
|
2329
|
+
alert_config=alert_config,
|
|
2330
|
+
**kwargs
|
|
2331
|
+
)
|
|
2332
|
+
|
|
2333
|
+
elif usecase == "defect_detection_products":
|
|
2334
|
+
# Import here to avoid circular import
|
|
2335
|
+
from ..usecases.defect_detection_products import BottleDefectConfig
|
|
2336
|
+
|
|
2337
|
+
# Handle nested configurations
|
|
2338
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2339
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2340
|
+
alert_config = AlertConfig(**alert_config)
|
|
2341
|
+
|
|
2342
|
+
config = BottleDefectConfig(
|
|
2343
|
+
category=category or "retail",
|
|
2344
|
+
usecase=usecase,
|
|
2345
|
+
alert_config=alert_config,
|
|
2346
|
+
**kwargs
|
|
2347
|
+
)
|
|
2348
|
+
|
|
2349
|
+
elif usecase == "assembly_line_detection":
|
|
2350
|
+
# Import here to avoid circular import
|
|
2351
|
+
from ..usecases.assembly_line_detection import AssemblyLineConfig
|
|
2352
|
+
|
|
2353
|
+
# Handle nested configurations
|
|
2354
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2355
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2356
|
+
alert_config = AlertConfig(**alert_config)
|
|
2357
|
+
|
|
2358
|
+
config = AssemblyLineConfig(
|
|
2359
|
+
category=category or "manufacturing",
|
|
2360
|
+
usecase=usecase,
|
|
2361
|
+
alert_config=alert_config,
|
|
2362
|
+
**kwargs
|
|
2363
|
+
)
|
|
2364
|
+
|
|
2365
|
+
elif usecase == "car_part_segmentation":
|
|
2366
|
+
# Import here to avoid circular import
|
|
2367
|
+
from ..usecases.car_part_segmentation import CarPartSegmentationConfig
|
|
2368
|
+
|
|
2369
|
+
# Handle nested configurations
|
|
2370
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2371
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2372
|
+
alert_config = AlertConfig(**alert_config)
|
|
2373
|
+
|
|
2374
|
+
config = CarPartSegmentationConfig(
|
|
2375
|
+
category=category or "automobile",
|
|
2376
|
+
usecase=usecase,
|
|
2377
|
+
alert_config=alert_config,
|
|
2378
|
+
**kwargs
|
|
2379
|
+
)
|
|
2380
|
+
|
|
2381
|
+
elif usecase == "windmill_maintenance":
|
|
2382
|
+
# Import here to avoid circular import
|
|
2383
|
+
from ..usecases.windmill_maintenance import WindmillMaintenanceConfig
|
|
2384
|
+
|
|
2385
|
+
# Handle nested configurations
|
|
2386
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2387
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2388
|
+
alert_config = AlertConfig(**alert_config)
|
|
2389
|
+
|
|
2390
|
+
config = WindmillMaintenanceConfig(
|
|
2391
|
+
category=category or "manufacturing",
|
|
2392
|
+
usecase=usecase,
|
|
2393
|
+
alert_config=alert_config,
|
|
2394
|
+
**kwargs
|
|
2395
|
+
)
|
|
2396
|
+
|
|
2397
|
+
elif usecase == "flower_segmentation":
|
|
2398
|
+
# Import here to avoid circular import
|
|
2399
|
+
from ..usecases.flower_segmentation import FlowerConfig
|
|
2400
|
+
|
|
2401
|
+
# Handle nested configurations
|
|
2402
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2403
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2404
|
+
alert_config = AlertConfig(**alert_config)
|
|
2405
|
+
|
|
2406
|
+
config = FlowerConfig(
|
|
2407
|
+
category=category or "agriculture",
|
|
2408
|
+
usecase=usecase,
|
|
2409
|
+
alert_config=alert_config,
|
|
2410
|
+
**kwargs
|
|
2411
|
+
)
|
|
2412
|
+
|
|
2413
|
+
elif usecase == "smoker_detection":
|
|
2414
|
+
# Import here to avoid circular import
|
|
2415
|
+
from ..usecases.smoker_detection import SmokerDetectionConfig
|
|
2416
|
+
|
|
2417
|
+
# Handle nested configurations
|
|
2418
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2419
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2420
|
+
alert_config = AlertConfig(**alert_config)
|
|
2421
|
+
|
|
2422
|
+
config = SmokerDetectionConfig(
|
|
2423
|
+
category=category or "general",
|
|
2424
|
+
usecase=usecase,
|
|
2425
|
+
alert_config=alert_config,
|
|
2426
|
+
**kwargs
|
|
2427
|
+
)
|
|
2428
|
+
|
|
2429
|
+
elif usecase == "road_traffic_density":
|
|
2430
|
+
# Import here to avoid circular import
|
|
2431
|
+
from ..usecases.road_traffic_density import RoadTrafficConfig
|
|
2432
|
+
|
|
2433
|
+
# Handle nested configurations
|
|
2434
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2435
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2436
|
+
alert_config = AlertConfig(**alert_config)
|
|
2437
|
+
|
|
2438
|
+
config = RoadTrafficConfig(
|
|
2439
|
+
category=category or "automobile",
|
|
2440
|
+
usecase=usecase,
|
|
2441
|
+
alert_config=alert_config,
|
|
2442
|
+
**kwargs
|
|
2443
|
+
)
|
|
2444
|
+
|
|
2445
|
+
elif usecase == "road_view_segmentation":
|
|
2446
|
+
# Import here to avoid circular import
|
|
2447
|
+
from ..usecases.road_view_segmentation import RoadViewSegmentationConfig
|
|
2448
|
+
|
|
2449
|
+
# Handle nested configurations
|
|
2450
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2451
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2452
|
+
alert_config = AlertConfig(**alert_config)
|
|
2453
|
+
|
|
2454
|
+
config = RoadViewSegmentationConfig(
|
|
2455
|
+
category=category or "automobile",
|
|
2456
|
+
usecase=usecase,
|
|
2457
|
+
alert_config=alert_config,
|
|
2458
|
+
**kwargs
|
|
2459
|
+
)
|
|
2460
|
+
|
|
2461
|
+
elif usecase == "face_recognition":
|
|
2462
|
+
# Import here to avoid circular import
|
|
2463
|
+
from ..face_reg.face_recognition import FaceRecognitionEmbeddingConfig
|
|
2464
|
+
|
|
2465
|
+
# Handle nested configurations
|
|
2466
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2467
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2468
|
+
alert_config = AlertConfig(**alert_config)
|
|
2469
|
+
|
|
2470
|
+
config = FaceRecognitionEmbeddingConfig(
|
|
2471
|
+
category=category or "security",
|
|
2472
|
+
usecase=usecase,
|
|
2473
|
+
alert_config=alert_config,
|
|
2474
|
+
**kwargs
|
|
2475
|
+
)
|
|
2476
|
+
return config
|
|
2477
|
+
elif usecase == "drowsy_driver_detection":
|
|
2478
|
+
# Import here to avoid circular import
|
|
2479
|
+
from ..usecases.drowsy_driver_detection import DrowsyDriverConfig
|
|
2480
|
+
|
|
2481
|
+
# Handle nested configurations
|
|
2482
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2483
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2484
|
+
alert_config = AlertConfig(**alert_config)
|
|
2485
|
+
|
|
2486
|
+
config = DrowsyDriverConfig(
|
|
2487
|
+
category=category or "automobile",
|
|
2488
|
+
usecase=usecase,
|
|
2489
|
+
alert_config=alert_config,
|
|
2490
|
+
**kwargs
|
|
2491
|
+
)
|
|
2492
|
+
|
|
2493
|
+
elif usecase == "waterbody_segmentation":
|
|
2494
|
+
# Import here to avoid circular import
|
|
2495
|
+
from ..usecases.waterbody_segmentation import WaterBodyConfig
|
|
2496
|
+
|
|
2497
|
+
# Handle nested configurations
|
|
2498
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2499
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2500
|
+
alert_config = AlertConfig(**alert_config)
|
|
2501
|
+
|
|
2502
|
+
config = WaterBodyConfig(
|
|
2503
|
+
category=category or "agriculture",
|
|
2504
|
+
usecase=usecase,
|
|
2505
|
+
alert_config=alert_config,
|
|
2506
|
+
**kwargs
|
|
2507
|
+
)
|
|
2508
|
+
|
|
2509
|
+
elif usecase == "litter_detection":
|
|
2510
|
+
# Import here to avoid circular import
|
|
2511
|
+
from ..usecases.litter_monitoring import LitterDetectionConfig
|
|
2512
|
+
|
|
2513
|
+
# Handle nested configurations
|
|
2514
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2515
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2516
|
+
alert_config = AlertConfig(**alert_config)
|
|
2517
|
+
|
|
2518
|
+
config = LitterDetectionConfig(
|
|
2519
|
+
category=category or "litter_detection",
|
|
2520
|
+
usecase=usecase,
|
|
2521
|
+
alert_config=alert_config,
|
|
2522
|
+
**kwargs
|
|
2523
|
+
)
|
|
2524
|
+
|
|
2525
|
+
elif usecase == "leak_detection":
|
|
2526
|
+
# Import here to avoid circular import
|
|
2527
|
+
from ..usecases.leak_detection import LeakDetectionConfig
|
|
2528
|
+
|
|
2529
|
+
# Handle nested configurations
|
|
2530
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2531
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2532
|
+
alert_config = AlertConfig(**alert_config)
|
|
2533
|
+
|
|
2534
|
+
config = LeakDetectionConfig(
|
|
2535
|
+
category=category or "oil_gas",
|
|
2536
|
+
usecase=usecase,
|
|
2537
|
+
alert_config=alert_config,
|
|
2538
|
+
**kwargs
|
|
2539
|
+
)
|
|
2540
|
+
|
|
2541
|
+
elif usecase == "human_activity_recognition":
|
|
2542
|
+
# Import here to avoid circular import
|
|
2543
|
+
from ..usecases.human_activity_recognition import HumanActivityConfig
|
|
2544
|
+
|
|
2545
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2546
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2547
|
+
alert_config = AlertConfig(**alert_config)
|
|
2548
|
+
|
|
2549
|
+
config = HumanActivityConfig(
|
|
2550
|
+
category=category or "general",
|
|
2551
|
+
usecase=usecase,
|
|
2552
|
+
alert_config=alert_config,
|
|
2553
|
+
**kwargs
|
|
2554
|
+
)
|
|
2555
|
+
|
|
2556
|
+
elif usecase == "gas_leak_detection":
|
|
2557
|
+
# Import here to avoid circular import
|
|
2558
|
+
from ..usecases.gas_leak_detection import GasLeakDetectionConfig
|
|
2559
|
+
|
|
2560
|
+
# Handle nested configurations
|
|
2561
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2562
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2563
|
+
alert_config = AlertConfig(**alert_config)
|
|
2564
|
+
|
|
2565
|
+
config = GasLeakDetectionConfig(
|
|
2566
|
+
category=category or "oil_gas",
|
|
2567
|
+
usecase=usecase,
|
|
2568
|
+
alert_config=alert_config,
|
|
2569
|
+
**kwargs
|
|
2570
|
+
)
|
|
2571
|
+
|
|
2572
|
+
elif usecase == "license_plate_monitor":
|
|
2573
|
+
# Import here to avoid circular import
|
|
2574
|
+
from ..usecases.license_plate_monitoring import LicensePlateMonitorConfig
|
|
2575
|
+
|
|
2576
|
+
# Handle nested configurations
|
|
2577
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2578
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2579
|
+
alert_config = AlertConfig(**alert_config)
|
|
2580
|
+
|
|
2581
|
+
# Filter kwargs to only include valid parameters
|
|
2582
|
+
filtered_kwargs = self._filter_kwargs_for_config(LicensePlateMonitorConfig, kwargs)
|
|
2583
|
+
|
|
2584
|
+
config = LicensePlateMonitorConfig(
|
|
2585
|
+
category=category or "license_plate_monitor",
|
|
2586
|
+
usecase=usecase,
|
|
2587
|
+
alert_config=alert_config,
|
|
2588
|
+
**filtered_kwargs
|
|
2589
|
+
)
|
|
2590
|
+
|
|
2591
|
+
elif usecase == "dwell":
|
|
2592
|
+
# Import here to avoid circular import
|
|
2593
|
+
from ..usecases.dwell_detection import DwellConfig
|
|
2594
|
+
|
|
2595
|
+
# Handle nested configurations
|
|
2596
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2597
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2598
|
+
alert_config = AlertConfig(**alert_config)
|
|
2599
|
+
|
|
2600
|
+
config = DwellConfig(
|
|
2601
|
+
category=category or "general",
|
|
2602
|
+
usecase=usecase,
|
|
2603
|
+
alert_config=alert_config,
|
|
2604
|
+
**kwargs
|
|
2605
|
+
)
|
|
2606
|
+
|
|
2607
|
+
elif usecase == "age_gender_detection":
|
|
2608
|
+
# Import here to avoid circular import
|
|
2609
|
+
from ..usecases.age_gender_detection import AgeGenderConfig
|
|
2610
|
+
|
|
2611
|
+
# Handle nested configurations
|
|
2612
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2613
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2614
|
+
alert_config = AlertConfig(**alert_config)
|
|
2615
|
+
|
|
2616
|
+
config = AgeGenderConfig(
|
|
2617
|
+
category=category or "age_gender_detection",
|
|
2618
|
+
usecase=usecase,
|
|
2619
|
+
alert_config=alert_config,
|
|
2620
|
+
**kwargs
|
|
2621
|
+
)
|
|
2622
|
+
|
|
2623
|
+
elif usecase == "wildlife_monitoring":
|
|
2624
|
+
# Import here to avoid circular import
|
|
2625
|
+
from ..usecases.wildlife_monitoring import WildLifeMonitoringConfig
|
|
2626
|
+
|
|
2627
|
+
# Handle nested configurations
|
|
2628
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2629
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2630
|
+
alert_config = AlertConfig(**alert_config)
|
|
2631
|
+
|
|
2632
|
+
config = WildLifeMonitoringConfig(
|
|
2633
|
+
category=category or "environmental",
|
|
2634
|
+
usecase=usecase,
|
|
2635
|
+
alert_config=alert_config,
|
|
2636
|
+
**kwargs
|
|
2637
|
+
)
|
|
2638
|
+
|
|
2639
|
+
elif usecase == "pcb_defect_detection":
|
|
2640
|
+
# Import here to avoid circular import
|
|
2641
|
+
from ..usecases.pcb_defect_detection import PCBDefectConfig
|
|
2642
|
+
|
|
2643
|
+
# Handle nested configurations
|
|
2644
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2645
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2646
|
+
alert_config = AlertConfig(**alert_config)
|
|
2647
|
+
|
|
2648
|
+
config = PCBDefectConfig(
|
|
2649
|
+
category=category or "manufacturing",
|
|
2650
|
+
usecase=usecase,
|
|
2651
|
+
alert_config=alert_config,
|
|
2652
|
+
**kwargs
|
|
2653
|
+
)
|
|
2654
|
+
|
|
2655
|
+
elif usecase == "suspicious_activity_detection":
|
|
2656
|
+
# Import here to avoid circular import
|
|
2657
|
+
from ..usecases.suspicious_activity_detection import SusActivityConfig
|
|
2658
|
+
|
|
2659
|
+
# Handle nested configurations
|
|
2660
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2661
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2662
|
+
alert_config = AlertConfig(**alert_config)
|
|
2663
|
+
|
|
2664
|
+
config = SusActivityConfig(
|
|
2665
|
+
category=category or "security",
|
|
2666
|
+
usecase=usecase,
|
|
2667
|
+
alert_config=alert_config,
|
|
2668
|
+
**kwargs
|
|
2669
|
+
)
|
|
2670
|
+
|
|
2671
|
+
elif usecase == "natural_disaster_detection":
|
|
2672
|
+
# Import here to avoid circular import
|
|
2673
|
+
from ..usecases.natural_disaster import NaturalDisasterConfig
|
|
2674
|
+
|
|
2675
|
+
# Handle nested configurations
|
|
2676
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2677
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2678
|
+
alert_config = AlertConfig(**alert_config)
|
|
2679
|
+
|
|
2680
|
+
config = NaturalDisasterConfig(
|
|
2681
|
+
category=category or "environmental",
|
|
2682
|
+
usecase=usecase,
|
|
2683
|
+
alert_config=alert_config,
|
|
2684
|
+
**kwargs
|
|
2685
|
+
)
|
|
2686
|
+
|
|
2687
|
+
#Add IMAGE based usecases here::
|
|
2688
|
+
elif usecase == "blood_cancer_detection_img":
|
|
2689
|
+
# Import here to avoid circular import
|
|
2690
|
+
from ..usecases.blood_cancer_detection_img import BloodCancerDetectionConfig
|
|
2691
|
+
|
|
2692
|
+
# Handle nested configurations
|
|
2693
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2694
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2695
|
+
alert_config = AlertConfig(**alert_config)
|
|
2696
|
+
|
|
2697
|
+
config = BloodCancerDetectionConfig(
|
|
2698
|
+
category=category or "healthcare",
|
|
2699
|
+
usecase=usecase,
|
|
2700
|
+
alert_config=alert_config,
|
|
2701
|
+
**kwargs
|
|
2702
|
+
)
|
|
2703
|
+
elif usecase == "skin_cancer_classification_img":
|
|
2704
|
+
# Import here to avoid circular import
|
|
2705
|
+
from ..usecases.skin_cancer_classification_img import SkinCancerClassificationConfig
|
|
2706
|
+
|
|
2707
|
+
# Handle nested configurations
|
|
2708
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2709
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2710
|
+
alert_config = AlertConfig(**alert_config)
|
|
2711
|
+
|
|
2712
|
+
config = SkinCancerClassificationConfig(
|
|
2713
|
+
category=category or "healthcare",
|
|
2714
|
+
usecase=usecase,
|
|
2715
|
+
alert_config=alert_config,
|
|
2716
|
+
**kwargs
|
|
2717
|
+
)
|
|
2718
|
+
elif usecase == "plaque_segmentation_img":
|
|
2719
|
+
# Import here to avoid circular import
|
|
2720
|
+
from ..usecases.plaque_segmentation_img import PlaqueSegmentationConfig
|
|
2721
|
+
|
|
2722
|
+
# Handle nested configurations
|
|
2723
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2724
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2725
|
+
alert_config = AlertConfig(**alert_config)
|
|
2726
|
+
|
|
2727
|
+
config = PlaqueSegmentationConfig(
|
|
2728
|
+
category=category or "healthcare",
|
|
2729
|
+
usecase=usecase,
|
|
2730
|
+
alert_config=alert_config,
|
|
2731
|
+
**kwargs
|
|
2732
|
+
)
|
|
2733
|
+
elif usecase == "cardiomegaly_classification":
|
|
2734
|
+
# Import here to avoid circular import
|
|
2735
|
+
from ..usecases.cardiomegaly_classification import CardiomegalyConfig
|
|
2736
|
+
|
|
2737
|
+
# Handle nested configurations
|
|
2738
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2739
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2740
|
+
alert_config = AlertConfig(**alert_config)
|
|
2741
|
+
|
|
2742
|
+
config = CardiomegalyConfig(
|
|
2743
|
+
category=category or "healthcare",
|
|
2744
|
+
usecase=usecase,
|
|
2745
|
+
alert_config=alert_config,
|
|
2746
|
+
**kwargs
|
|
2747
|
+
)
|
|
2748
|
+
elif usecase == "histopathological_cancer_detection":
|
|
2749
|
+
# Import here to avoid circular import
|
|
2750
|
+
from ..usecases.Histopathological_Cancer_Detection_img import HistopathologicalCancerDetectionConfig
|
|
2751
|
+
|
|
2752
|
+
# Handle nested configurations
|
|
2753
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2754
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2755
|
+
alert_config = AlertConfig(**alert_config)
|
|
2756
|
+
|
|
2757
|
+
config = HistopathologicalCancerDetectionConfig(
|
|
2758
|
+
category=category or "healthcare",
|
|
2759
|
+
usecase=usecase,
|
|
2760
|
+
alert_config=alert_config,
|
|
2761
|
+
**kwargs
|
|
2762
|
+
)
|
|
2763
|
+
elif usecase == "cell_microscopy_segmentation":
|
|
2764
|
+
# Import here to avoid circular import
|
|
2765
|
+
from ..usecases.cell_microscopy_segmentation import CellMicroscopyConfig
|
|
2766
|
+
|
|
2767
|
+
# Handle nested configurations
|
|
2768
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2769
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2770
|
+
alert_config = AlertConfig(**alert_config)
|
|
2771
|
+
|
|
2772
|
+
config = CellMicroscopyConfig(
|
|
2773
|
+
category=category or "healthcare",
|
|
2774
|
+
usecase=usecase,
|
|
2775
|
+
alert_config=alert_config,
|
|
2776
|
+
**kwargs
|
|
2777
|
+
)
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
elif usecase == "underground_pipeline_defect":
|
|
2781
|
+
# Import here to avoid circular import
|
|
2782
|
+
from ..usecases.underground_pipeline_defect_detection import UndergroundPipelineDefectConfig
|
|
2783
|
+
|
|
2784
|
+
# Handle nested configurations
|
|
2785
|
+
alert_config = kwargs.pop("alert_config", None)
|
|
2786
|
+
if alert_config and isinstance(alert_config, dict):
|
|
2787
|
+
alert_config = AlertConfig(**alert_config)
|
|
2788
|
+
|
|
2789
|
+
config = UndergroundPipelineDefectConfig(
|
|
2790
|
+
category=category or "underground_pipeline_defect",
|
|
2791
|
+
usecase=usecase,
|
|
2792
|
+
alert_config=alert_config,
|
|
2793
|
+
**kwargs
|
|
2794
|
+
)
|
|
2795
|
+
|
|
2796
|
+
else:
|
|
2797
|
+
raise ConfigValidationError(f"Unknown use case: {usecase}")
|
|
2798
|
+
|
|
2799
|
+
# Validate configuration
|
|
2800
|
+
errors = config.validate()
|
|
2801
|
+
if errors:
|
|
2802
|
+
raise ConfigValidationError(f"Configuration validation failed: {errors}")
|
|
2803
|
+
|
|
2804
|
+
return config
|
|
2805
|
+
|
|
2806
|
+
def load_from_file(self, file_path: Union[str, Path]) -> BaseConfig:
|
|
2807
|
+
"""
|
|
2808
|
+
Load configuration from file.
|
|
2809
|
+
|
|
2810
|
+
Args:
|
|
2811
|
+
file_path: Path to configuration file (JSON or YAML)
|
|
2812
|
+
|
|
2813
|
+
Returns:
|
|
2814
|
+
BaseConfig: Configuration object
|
|
2815
|
+
|
|
2816
|
+
Raises:
|
|
2817
|
+
ConfigValidationError: If file cannot be loaded or validation fails
|
|
2818
|
+
"""
|
|
2819
|
+
file_path = Path(file_path)
|
|
2820
|
+
|
|
2821
|
+
if not file_path.exists():
|
|
2822
|
+
raise ConfigValidationError(f"Configuration file not found: {file_path}")
|
|
2823
|
+
|
|
2824
|
+
try:
|
|
2825
|
+
# Load data based on file extension
|
|
2826
|
+
if file_path.suffix.lower() == '.json':
|
|
2827
|
+
with open(file_path, 'r') as f:
|
|
2828
|
+
data = json.load(f)
|
|
2829
|
+
elif file_path.suffix.lower() in ['.yml', '.yaml']:
|
|
2830
|
+
with open(file_path, 'r') as f:
|
|
2831
|
+
data = yaml.safe_load(f)
|
|
2832
|
+
else:
|
|
2833
|
+
raise ConfigValidationError(f"Unsupported file format: {file_path.suffix}")
|
|
2834
|
+
|
|
2835
|
+
# Extract usecase and category
|
|
2836
|
+
usecase = data.get('usecase')
|
|
2837
|
+
if not usecase:
|
|
2838
|
+
raise ConfigValidationError("Configuration file must specify 'usecase'")
|
|
2839
|
+
|
|
2840
|
+
category = data.get('category', 'general')
|
|
2841
|
+
|
|
2842
|
+
# Remove category and usecase from data to avoid duplication
|
|
2843
|
+
data_copy = data.copy()
|
|
2844
|
+
data_copy.pop('category', None)
|
|
2845
|
+
data_copy.pop('usecase', None)
|
|
2846
|
+
|
|
2847
|
+
# Create config
|
|
2848
|
+
return self.create_config(usecase, category, **data_copy)
|
|
2849
|
+
|
|
2850
|
+
except (json.JSONDecodeError, yaml.YAMLError) as e:
|
|
2851
|
+
raise ConfigValidationError(f"Failed to parse configuration file: {str(e)}")
|
|
2852
|
+
except Exception as e:
|
|
2853
|
+
raise ConfigValidationError(f"Failed to load configuration: {str(e)}")
|
|
2854
|
+
|
|
2855
|
+
def save_to_file(self, config: BaseConfig, file_path: Union[str, Path], format: str = "json") -> None:
|
|
2856
|
+
"""
|
|
2857
|
+
Save configuration to file.
|
|
2858
|
+
|
|
2859
|
+
Args:
|
|
2860
|
+
config: Configuration object
|
|
2861
|
+
file_path: Output file path
|
|
2862
|
+
format: Output format ('json' or 'yaml')
|
|
2863
|
+
|
|
2864
|
+
Raises:
|
|
2865
|
+
ConfigValidationError: If format is unsupported or saving fails
|
|
2866
|
+
"""
|
|
2867
|
+
file_path = Path(file_path)
|
|
2868
|
+
|
|
2869
|
+
try:
|
|
2870
|
+
data = config.to_dict()
|
|
2871
|
+
|
|
2872
|
+
if format.lower() == 'json':
|
|
2873
|
+
with open(file_path, 'w') as f:
|
|
2874
|
+
json.dump(data, f, indent=2)
|
|
2875
|
+
elif format.lower() in ['yml', 'yaml']:
|
|
2876
|
+
with open(file_path, 'w') as f:
|
|
2877
|
+
yaml.dump(data, f, default_flow_style=False, indent=2)
|
|
2878
|
+
else:
|
|
2879
|
+
raise ConfigValidationError(f"Unsupported format: {format}")
|
|
2880
|
+
|
|
2881
|
+
except Exception as e:
|
|
2882
|
+
raise ConfigValidationError(f"Failed to save configuration: {str(e)}")
|
|
2883
|
+
|
|
2884
|
+
def get_config_template(self, usecase: str) -> Dict[str, Any]:
|
|
2885
|
+
"""Get configuration template for a use case."""
|
|
2886
|
+
if usecase == "basic_counting_tracking":
|
|
2887
|
+
# Import here to avoid circular import
|
|
2888
|
+
from ..usecases.basic_counting_tracking import BasicCountingTrackingConfig
|
|
2889
|
+
default_config = BasicCountingTrackingConfig()
|
|
2890
|
+
return default_config.to_dict()
|
|
2891
|
+
elif usecase == "license_plate_detection":
|
|
2892
|
+
# Import here to avoid circular import
|
|
2893
|
+
from ..usecases.license_plate_detection import LicensePlateConfig
|
|
2894
|
+
default_config = LicensePlateConfig()
|
|
2895
|
+
return default_config.to_dict()
|
|
2896
|
+
elif usecase == "field_mapping":
|
|
2897
|
+
# Import here to avoid circular import
|
|
2898
|
+
from ..usecases.field_mapping import FieldMappingConfig
|
|
2899
|
+
default_config = FieldMappingConfig()
|
|
2900
|
+
return default_config.to_dict()
|
|
2901
|
+
elif usecase == "parking_space_detection":
|
|
2902
|
+
# Import here to avoid circular import
|
|
2903
|
+
from ..usecases.parking_space_detection import ParkingSpaceConfig
|
|
2904
|
+
default_config = ParkingSpaceConfig()
|
|
2905
|
+
return default_config.to_dict()
|
|
2906
|
+
elif usecase == "mask_detection":
|
|
2907
|
+
# Import here to avoid circular import
|
|
2908
|
+
from ..usecases.mask_detection import MaskDetectionConfig
|
|
2909
|
+
default_config = MaskDetectionConfig()
|
|
2910
|
+
return default_config.to_dict()
|
|
2911
|
+
|
|
2912
|
+
elif usecase == "pipeline_detection":
|
|
2913
|
+
from ..usecases.pipeline_detection import PipelineDetectionConfig
|
|
2914
|
+
default_config = PipelineDetectionConfig()
|
|
2915
|
+
return default_config.to_dict()
|
|
2916
|
+
|
|
2917
|
+
elif usecase == "fire_smoke_detection":
|
|
2918
|
+
# Import here to avoid circular import
|
|
2919
|
+
from ..usecases.fire_detection import FireSmokeConfig
|
|
2920
|
+
default_config = FireSmokeConfig()
|
|
2921
|
+
return default_config.to_dict()
|
|
2922
|
+
|
|
2923
|
+
elif usecase == "wound_segmentation":
|
|
2924
|
+
# Import here to avoid circular import
|
|
2925
|
+
from ..usecases.wound_segmentation import WoundConfig
|
|
2926
|
+
default_config = WoundConfig()
|
|
2927
|
+
return default_config.to_dict()
|
|
2928
|
+
|
|
2929
|
+
elif usecase == "shoplifting_detection":
|
|
2930
|
+
# Import here to avoid circular import
|
|
2931
|
+
from ..usecases.shoplifting_detection import ShopliftingDetectionConfig
|
|
2932
|
+
default_config = ShopliftingDetectionConfig()
|
|
2933
|
+
return default_config.to_dict()
|
|
2934
|
+
|
|
2935
|
+
elif usecase == "solar_panel":
|
|
2936
|
+
# Import here to avoid circular import
|
|
2937
|
+
from ..usecases.solar_panel import SolarPanelConfig
|
|
2938
|
+
default_config = SolarPanelConfig()
|
|
2939
|
+
return default_config.to_dict()
|
|
2940
|
+
|
|
2941
|
+
elif usecase == "car_damage_detection":
|
|
2942
|
+
# Import here to avoid circular import
|
|
2943
|
+
from ..usecases.car_damage_detection import CarDamageConfig
|
|
2944
|
+
default_config = CarDamageConfig()
|
|
2945
|
+
return default_config.to_dict()
|
|
2946
|
+
|
|
2947
|
+
elif usecase == "pothole_segmentation":
|
|
2948
|
+
# Import here to avoid circular import
|
|
2949
|
+
from ..usecases.pothole_segmentation import PotholeConfig
|
|
2950
|
+
default_config = PotholeConfig()
|
|
2951
|
+
return default_config.to_dict()
|
|
2952
|
+
|
|
2953
|
+
elif usecase == "leaf_disease_detection":
|
|
2954
|
+
# Import here to avoid circular import
|
|
2955
|
+
from ..usecases.leaf_disease import LeafDiseaseDetectionConfig
|
|
2956
|
+
default_config = LeafDiseaseDetectionConfig()
|
|
2957
|
+
return default_config.to_dict()
|
|
2958
|
+
|
|
2959
|
+
elif usecase == "vehicle_monitoring":
|
|
2960
|
+
# Import here to avoid circular import
|
|
2961
|
+
from ..usecases.vehicle_monitoring import VehicleMonitoringConfig
|
|
2962
|
+
default_config = VehicleMonitoringConfig()
|
|
2963
|
+
return default_config.to_dict()
|
|
2964
|
+
|
|
2965
|
+
elif usecase == "drone_traffic_monitoring":
|
|
2966
|
+
# Import here to avoid circular import
|
|
2967
|
+
from ..usecases.drone_traffic_monitoring import VehiclePeopleDroneMonitoringConfig
|
|
2968
|
+
default_config = VehiclePeopleDroneMonitoringConfig()
|
|
2969
|
+
return default_config.to_dict()
|
|
2970
|
+
|
|
2971
|
+
elif usecase == "chicken_pose_detection":
|
|
2972
|
+
# Import here to avoid circular import
|
|
2973
|
+
from ..usecases.chicken_pose_detection import ChickenPoseDetectionConfig
|
|
2974
|
+
default_config = ChickenPoseDetectionConfig()
|
|
2975
|
+
return default_config.to_dict()
|
|
2976
|
+
|
|
2977
|
+
elif usecase == "fruit_monitoring":
|
|
2978
|
+
# Import here to avoid circular import
|
|
2979
|
+
from ..usecases.banana_defect_detection import BananaMonitoringConfig
|
|
2980
|
+
default_config = BananaMonitoringConfig()
|
|
2981
|
+
return default_config.to_dict()
|
|
2982
|
+
|
|
2983
|
+
elif usecase == "lane_detection":
|
|
2984
|
+
# Import here to avoid circular import
|
|
2985
|
+
from ..usecases.road_lane_detection import LaneDetectionConfig
|
|
2986
|
+
default_config = LaneDetectionConfig()
|
|
2987
|
+
return default_config.to_dict()
|
|
2988
|
+
|
|
2989
|
+
elif usecase == "shelf_inventory":
|
|
2990
|
+
# Import here to avoid circular import
|
|
2991
|
+
from ..usecases.shelf_inventory_detection import ShelfInventoryConfig
|
|
2992
|
+
default_config = ShelfInventoryConfig()
|
|
2993
|
+
return default_config.to_dict()
|
|
2994
|
+
|
|
2995
|
+
elif usecase == "anti_spoofing_detection":
|
|
2996
|
+
# Import here to avoid circular import
|
|
2997
|
+
from ..usecases.anti_spoofing_detection import AntiSpoofingDetectionConfig
|
|
2998
|
+
default_config = AntiSpoofingDetectionConfig()
|
|
2999
|
+
return default_config.to_dict()
|
|
3000
|
+
|
|
3001
|
+
elif usecase == "traffic_sign_monitoring":
|
|
3002
|
+
# Import here to avoid circular import
|
|
3003
|
+
from ..usecases.traffic_sign_monitoring import TrafficSignMonitoringConfig
|
|
3004
|
+
default_config = TrafficSignMonitoringConfig()
|
|
3005
|
+
return default_config.to_dict()
|
|
3006
|
+
|
|
3007
|
+
elif usecase == "theft_detection":
|
|
3008
|
+
# Import here to avoid circular import
|
|
3009
|
+
from ..usecases.theft_detection import TheftDetectionConfig
|
|
3010
|
+
default_config = TheftDetectionConfig()
|
|
3011
|
+
return default_config.to_dict()
|
|
3012
|
+
|
|
3013
|
+
elif usecase == "weapon_detection":
|
|
3014
|
+
# Import here to avoid circular import
|
|
3015
|
+
from ..usecases.weapon_detection import WeaponDetectionConfig
|
|
3016
|
+
default_config = WeaponDetectionConfig()
|
|
3017
|
+
return default_config.to_dict()
|
|
3018
|
+
|
|
3019
|
+
elif usecase == "weld_defect_detection":
|
|
3020
|
+
# Import here to avoid circular import
|
|
3021
|
+
from ..usecases.weld_defect_detection import WeldDefectConfig
|
|
3022
|
+
default_config = WeldDefectConfig()
|
|
3023
|
+
return default_config.to_dict()
|
|
3024
|
+
elif usecase == "video_color_classification":
|
|
3025
|
+
from ..usecases.color_detection import ColorDetectionConfig
|
|
3026
|
+
default_config = ColorDetectionConfig()
|
|
3027
|
+
return default_config.to_dict()
|
|
3028
|
+
elif usecase == "color_detection":
|
|
3029
|
+
# Import here to avoid circular import
|
|
3030
|
+
from ..usecases.color_detection import ColorDetectionConfig
|
|
3031
|
+
default_config = ColorDetectionConfig()
|
|
3032
|
+
return default_config.to_dict()
|
|
3033
|
+
elif usecase == "flare_analysis":
|
|
3034
|
+
# Import here to avoid circular import
|
|
3035
|
+
from ..usecases.flare_analysis import FlareAnalysisConfig
|
|
3036
|
+
default_config = FlareAnalysisConfig()
|
|
3037
|
+
return default_config.to_dict()
|
|
3038
|
+
elif usecase == "ppe_compliance_detection":
|
|
3039
|
+
# Import here to avoid circular import
|
|
3040
|
+
from ..usecases.ppe_compliance import PPEComplianceConfig
|
|
3041
|
+
default_config = PPEComplianceConfig()
|
|
3042
|
+
return default_config.to_dict()
|
|
3043
|
+
elif usecase == "face_emotion":
|
|
3044
|
+
# Import here to avoid circular import
|
|
3045
|
+
from ..usecases.face_emotion import FaceEmotionConfig
|
|
3046
|
+
default_config = FaceEmotionConfig()
|
|
3047
|
+
return default_config.to_dict()
|
|
3048
|
+
elif usecase == "underwater_pollution_detection":
|
|
3049
|
+
# Import here to avoid circular import
|
|
3050
|
+
from ..usecases.underwater_pollution_detection import UnderwaterPlasticConfig
|
|
3051
|
+
default_config = UnderwaterPlasticConfig()
|
|
3052
|
+
return default_config.to_dict()
|
|
3053
|
+
elif usecase == "pedestrian_detection":
|
|
3054
|
+
# Import here to avoid circular import
|
|
3055
|
+
from ..usecases.pedestrian_detection import PedestrianDetectionConfig
|
|
3056
|
+
default_config = PedestrianDetectionConfig()
|
|
3057
|
+
return default_config.to_dict()
|
|
3058
|
+
elif usecase == "age_detection":
|
|
3059
|
+
# Import here to avoid circular import
|
|
3060
|
+
from ..usecases.age_detection import AgeDetectionConfig
|
|
3061
|
+
default_config = AgeDetectionConfig()
|
|
3062
|
+
return default_config.to_dict()
|
|
3063
|
+
elif usecase == "price_tag_detection":
|
|
3064
|
+
# Import here to avoid circular import
|
|
3065
|
+
from ..usecases.price_tag_detection import PriceTagConfig
|
|
3066
|
+
default_config = PriceTagConfig()
|
|
3067
|
+
return default_config.to_dict()
|
|
3068
|
+
elif usecase == "distracted_driver_detection":
|
|
3069
|
+
# Import here to avoid circular import
|
|
3070
|
+
from ..usecases.distracted_driver_detection import DistractedDriverConfig
|
|
3071
|
+
default_config = DistractedDriverConfig()
|
|
3072
|
+
return default_config.to_dict()
|
|
3073
|
+
elif usecase == "emergency_vehicle_detection":
|
|
3074
|
+
# Import here to avoid circular import
|
|
3075
|
+
from ..usecases.emergency_vehicle_detection import EmergencyVehicleConfig
|
|
3076
|
+
default_config = EmergencyVehicleConfig()
|
|
3077
|
+
return default_config.to_dict()
|
|
3078
|
+
elif usecase == "crop_weed_detection":
|
|
3079
|
+
# Import here to avoid circular import
|
|
3080
|
+
from ..usecases.crop_weed_detection import CropWeedDetectionConfig
|
|
3081
|
+
default_config = CropWeedDetectionConfig()
|
|
3082
|
+
return default_config.to_dict()
|
|
3083
|
+
elif usecase == "child_monitoring":
|
|
3084
|
+
# Import here to avoid circular import
|
|
3085
|
+
from ..usecases.child_monitoring import ChildMonitoringConfig
|
|
3086
|
+
default_config = ChildMonitoringConfig()
|
|
3087
|
+
return default_config.to_dict()
|
|
3088
|
+
elif usecase == "gender_detection":
|
|
3089
|
+
# Import here to avoid circular import
|
|
3090
|
+
from ..usecases.gender_detection import GenderDetectionConfig
|
|
3091
|
+
default_config = GenderDetectionConfig()
|
|
3092
|
+
return default_config.to_dict()
|
|
3093
|
+
elif usecase == "concrete_crack_detection":
|
|
3094
|
+
# Import here to avoid circular import
|
|
3095
|
+
from ..usecases.concrete_crack_detection import ConcreteCrackConfig
|
|
3096
|
+
default_config = ConcreteCrackConfig()
|
|
3097
|
+
return default_config.to_dict()
|
|
3098
|
+
elif usecase == "fashion_detection":
|
|
3099
|
+
# Import here to avoid circular import
|
|
3100
|
+
from ..usecases.fashion_detection import FashionDetectionConfig
|
|
3101
|
+
default_config = FashionDetectionConfig()
|
|
3102
|
+
return default_config.to_dict()
|
|
3103
|
+
elif usecase == "warehouse_object_segmentation":
|
|
3104
|
+
# Import here to avoid circular import
|
|
3105
|
+
from ..usecases.warehouse_object_segmentation import WarehouseObjectConfig
|
|
3106
|
+
default_config = WarehouseObjectConfig()
|
|
3107
|
+
return default_config.to_dict()
|
|
3108
|
+
elif usecase == "shopping_cart_analysis":
|
|
3109
|
+
# Import here to avoid circular import
|
|
3110
|
+
from ..usecases.shopping_cart_analysis import ShoppingCartConfig
|
|
3111
|
+
default_config = ShoppingCartConfig()
|
|
3112
|
+
return default_config.to_dict()
|
|
3113
|
+
elif usecase == "defect_detection_products":
|
|
3114
|
+
# Import here to avoid circular import
|
|
3115
|
+
from ..usecases.defect_detection_products import BottleDefectConfig
|
|
3116
|
+
default_config = BottleDefectConfig()
|
|
3117
|
+
return default_config.to_dict()
|
|
3118
|
+
elif usecase == "assembly_line_detection":
|
|
3119
|
+
# Import here to avoid circular import
|
|
3120
|
+
from ..usecases.assembly_line_detection import AssemblyLineConfig
|
|
3121
|
+
default_config = AssemblyLineConfig()
|
|
3122
|
+
return default_config.to_dict()
|
|
3123
|
+
elif usecase == "car_part_segmentation":
|
|
3124
|
+
# Import here to avoid circular import
|
|
3125
|
+
from ..usecases.car_part_segmentation import CarPartSegmentationConfig
|
|
3126
|
+
default_config = CarPartSegmentationConfig()
|
|
3127
|
+
return default_config.to_dict()
|
|
3128
|
+
elif usecase == "windmill_maintenance":
|
|
3129
|
+
# Import here to avoid circular import
|
|
3130
|
+
from ..usecases.windmill_maintenance import WindmillMaintenanceConfig
|
|
3131
|
+
default_config = WindmillMaintenanceConfig()
|
|
3132
|
+
return default_config.to_dict()
|
|
3133
|
+
elif usecase == "flower_segmentation":
|
|
3134
|
+
# Import here to avoid circular import
|
|
3135
|
+
from ..usecases.flower_segmentation import FlowerConfig
|
|
3136
|
+
default_config = FlowerConfig()
|
|
3137
|
+
return default_config.to_dict()
|
|
3138
|
+
elif usecase == "smoker_detection":
|
|
3139
|
+
# Import here to avoid circular import
|
|
3140
|
+
from ..usecases.smoker_detection import SmokerDetectionConfig
|
|
3141
|
+
default_config = SmokerDetectionConfig()
|
|
3142
|
+
return default_config.to_dict()
|
|
3143
|
+
elif usecase == "road_traffic_density":
|
|
3144
|
+
# Import here to avoid circular import
|
|
3145
|
+
from ..usecases.road_traffic_density import RoadTrafficConfig
|
|
3146
|
+
default_config = RoadTrafficConfig()
|
|
3147
|
+
return default_config.to_dict()
|
|
3148
|
+
elif usecase == "road_view_segmentation":
|
|
3149
|
+
# Import here to avoid circular import
|
|
3150
|
+
from ..usecases.road_view_segmentation import RoadViewSegmentationConfig
|
|
3151
|
+
default_config = RoadViewSegmentationConfig()
|
|
3152
|
+
return default_config.to_dict()
|
|
3153
|
+
elif usecase == "face_recognition":
|
|
3154
|
+
# Import here to avoid circular import
|
|
3155
|
+
from ..face_reg.face_recognition import FaceRecognitionEmbeddingConfig
|
|
3156
|
+
default_config = FaceRecognitionEmbeddingConfig()
|
|
3157
|
+
return default_config.to_dict()
|
|
3158
|
+
elif usecase == "drowsy_driver_detection":
|
|
3159
|
+
# Import here to avoid circular import
|
|
3160
|
+
from ..usecases.drowsy_driver_detection import DrowsyDriverConfig
|
|
3161
|
+
default_config = DrowsyDriverConfig()
|
|
3162
|
+
return default_config.to_dict()
|
|
3163
|
+
elif usecase == "waterbody_segmentation":
|
|
3164
|
+
# Import here to avoid circular import
|
|
3165
|
+
from ..usecases.waterbody_segmentation import WaterBodyConfig
|
|
3166
|
+
default_config = WaterBodyConfig()
|
|
3167
|
+
return default_config.to_dict()
|
|
3168
|
+
|
|
3169
|
+
elif usecase == "litter_detection":
|
|
3170
|
+
# Import here to avoid circular import
|
|
3171
|
+
from ..usecases.litter_monitoring import LitterDetectionConfig
|
|
3172
|
+
default_config = LitterDetectionConfig()
|
|
3173
|
+
return default_config.to_dict()
|
|
3174
|
+
|
|
3175
|
+
elif usecase == "abandoned_object_detection":
|
|
3176
|
+
# Import here to avoid circular import
|
|
3177
|
+
from ..usecases.abandoned_object_detection import AbandonedObjectConfig
|
|
3178
|
+
default_config = AbandonedObjectConfig()
|
|
3179
|
+
return default_config.to_dict()
|
|
3180
|
+
elif usecase == "leak_detection":
|
|
3181
|
+
# Import here to avoid circular import
|
|
3182
|
+
from ..usecases.leak_detection import LeakDetectionConfig
|
|
3183
|
+
default_config = LeakDetectionConfig()
|
|
3184
|
+
return default_config.to_dict()
|
|
3185
|
+
elif usecase == "human_activity_recognition":
|
|
3186
|
+
# Import here to avoid circular import
|
|
3187
|
+
from ..usecases.human_activity_recognition import HumanActivityConfig
|
|
3188
|
+
default_config = HumanActivityConfig()
|
|
3189
|
+
return default_config.to_dict()
|
|
3190
|
+
elif usecase == "gas_leak_detection":
|
|
3191
|
+
# Import here to avoid circular import
|
|
3192
|
+
from ..usecases.gas_leak_detection import GasLeakDetectionConfig
|
|
3193
|
+
default_config = GasLeakDetectionConfig()
|
|
3194
|
+
return default_config.to_dict()
|
|
3195
|
+
|
|
3196
|
+
elif usecase == "license_plate_monitor":
|
|
3197
|
+
# Import here to avoid circular import
|
|
3198
|
+
from ..usecases.license_plate_monitoring import LicensePlateMonitorConfig
|
|
3199
|
+
default_config = LicensePlateMonitorConfig()
|
|
3200
|
+
return default_config.to_dict()
|
|
3201
|
+
|
|
3202
|
+
elif usecase == "dwell":
|
|
3203
|
+
# Import here to avoid circular import
|
|
3204
|
+
from ..usecases.dwell_detection import DwellConfig
|
|
3205
|
+
default_config = DwellConfig()
|
|
3206
|
+
return default_config.to_dict()
|
|
3207
|
+
|
|
3208
|
+
elif usecase == "age_gender_detection":
|
|
3209
|
+
# Import here to avoid circular import
|
|
3210
|
+
from ..usecases.age_gender_detection import AgeGenderConfig
|
|
3211
|
+
default_config = AgeGenderConfig()
|
|
3212
|
+
return default_config.to_dict()
|
|
3213
|
+
|
|
3214
|
+
elif usecase == "wildlife_monitoring":
|
|
3215
|
+
# Import here to avoid circular import
|
|
3216
|
+
from ..usecases.wildlife_monitoring import WildLifeMonitoringConfig
|
|
3217
|
+
default_config = WildLifeMonitoringConfig()
|
|
3218
|
+
return default_config.to_dict()
|
|
3219
|
+
|
|
3220
|
+
elif usecase == "pcb_defect_detection":
|
|
3221
|
+
# Import here to avoid circular import
|
|
3222
|
+
from ..usecases.pcb_defect_detection import PCBDefectConfig
|
|
3223
|
+
default_config = PCBDefectConfig()
|
|
3224
|
+
return default_config.to_dict()
|
|
3225
|
+
|
|
3226
|
+
elif usecase == "suspicious_activity_detection":
|
|
3227
|
+
# Import here to avoid circular import
|
|
3228
|
+
from ..usecases.suspicious_activity_detection import SusActivityConfig
|
|
3229
|
+
default_config = SusActivityConfig()
|
|
3230
|
+
return default_config.to_dict()
|
|
3231
|
+
|
|
3232
|
+
elif usecase == "natural_disaster_detection":
|
|
3233
|
+
# Import here to avoid circular import
|
|
3234
|
+
from ..usecases.natural_disaster import NaturalDisasterConfig
|
|
3235
|
+
default_config = NaturalDisasterConfig()
|
|
3236
|
+
return default_config.to_dict()
|
|
3237
|
+
|
|
3238
|
+
elif usecase == "underground_pipeline_defect":
|
|
3239
|
+
# Import here to avoid circular import
|
|
3240
|
+
from ..usecases.underground_pipeline_defect_detection import UndergroundPipelineDefectConfig
|
|
3241
|
+
default_config = UndergroundPipelineDefectConfig()
|
|
3242
|
+
return default_config.to_dict()
|
|
3243
|
+
|
|
3244
|
+
#Add all image based usecases here
|
|
3245
|
+
elif usecase == "blood_cancer_detection_img":
|
|
3246
|
+
# Import here to avoid circular import
|
|
3247
|
+
from ..usecases.blood_cancer_detection_img import BloodCancerDetectionConfig
|
|
3248
|
+
default_config = BloodCancerDetectionConfig()
|
|
3249
|
+
return default_config.to_dict()
|
|
3250
|
+
elif usecase == "skin_cancer_classification_img":
|
|
3251
|
+
# Import here to avoid circular import
|
|
3252
|
+
from ..usecases.skin_cancer_classification_img import SkinCancerClassificationConfig
|
|
3253
|
+
default_config = SkinCancerClassificationConfig()
|
|
3254
|
+
return default_config.to_dict()
|
|
3255
|
+
elif usecase == "plaque_segmentation_img":
|
|
3256
|
+
# Import here to avoid circular import
|
|
3257
|
+
from ..usecases.plaque_segmentation_img import PlaqueSegmentationConfig
|
|
3258
|
+
default_config = PlaqueSegmentationConfig()
|
|
3259
|
+
return default_config.to_dict()
|
|
3260
|
+
elif usecase == "cardiomegaly_classification":
|
|
3261
|
+
# Import here to avoid circular import
|
|
3262
|
+
from ..usecases.cardiomegaly_classification import CardiomegalyConfig
|
|
3263
|
+
default_config = CardiomegalyConfig()
|
|
3264
|
+
return default_config.to_dict()
|
|
3265
|
+
elif usecase == "histopathological_cancer_detection":
|
|
3266
|
+
# Import here to avoid circular import
|
|
3267
|
+
from ..usecases.Histopathological_Cancer_Detection_img import HistopathologicalCancerDetectionConfig
|
|
3268
|
+
default_config = HistopathologicalCancerDetectionConfig()
|
|
3269
|
+
return default_config.to_dict()
|
|
3270
|
+
elif usecase == "cell_microscopy_segmentation":
|
|
3271
|
+
# Import here to avoid circular import
|
|
3272
|
+
from ..usecases.cell_microscopy_segmentation import CellMicroscopyConfig
|
|
3273
|
+
default_config = CellMicroscopyConfig()
|
|
3274
|
+
return default_config.to_dict()
|
|
3275
|
+
|
|
3276
|
+
elif usecase not in self._config_classes:
|
|
3277
|
+
raise ConfigValidationError(f"Unsupported use case: {usecase}")
|
|
3278
|
+
|
|
3279
|
+
|
|
3280
|
+
|
|
3281
|
+
config_class = self._config_classes[usecase]
|
|
3282
|
+
default_config = config_class()
|
|
3283
|
+
return default_config.to_dict()
|
|
3284
|
+
|
|
3285
|
+
def list_supported_usecases(self) -> List[str]:
|
|
3286
|
+
"""List all supported use cases."""
|
|
3287
|
+
return list(self._config_classes.keys())
|
|
3288
|
+
|
|
3289
|
+
|
|
3290
|
+
# Global configuration manager instance
|
|
3291
|
+
config_manager = ConfigManager()
|