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,367 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Advanced tracker implementation.
|
|
3
|
+
|
|
4
|
+
This module provides the AdvancedTracker class that implements BYTETracker-like
|
|
5
|
+
functionality for object tracking with support for various input formats.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, List, Optional, Tuple, Union, Dict
|
|
9
|
+
import numpy as np
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
from .base import BaseTrack, TrackState
|
|
13
|
+
from .config import TrackerConfig
|
|
14
|
+
from .kalman_filter import KalmanFilterXYAH
|
|
15
|
+
from .strack import STrack
|
|
16
|
+
from .matching import linear_assignment, iou_distance, fuse_score
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AdvancedTracker:
|
|
22
|
+
"""
|
|
23
|
+
AdvancedTracker: A tracking algorithm similar to BYTETracker for object detection and tracking.
|
|
24
|
+
|
|
25
|
+
This class encapsulates the functionality for initializing, updating, and managing the tracks for detected objects in a
|
|
26
|
+
video sequence. It maintains the state of tracked, lost, and removed tracks over frames, utilizes Kalman filtering for
|
|
27
|
+
predicting the new object locations, and performs data association.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
tracked_stracks (List[STrack]): List of successfully activated tracks.
|
|
31
|
+
lost_stracks (List[STrack]): List of lost tracks.
|
|
32
|
+
removed_stracks (List[STrack]): List of removed tracks.
|
|
33
|
+
frame_id (int): The current frame ID.
|
|
34
|
+
config (TrackerConfig): Tracker configuration.
|
|
35
|
+
max_time_lost (int): The maximum frames for a track to be considered as 'lost'.
|
|
36
|
+
kalman_filter (KalmanFilterXYAH): Kalman Filter object.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, config: TrackerConfig):
|
|
40
|
+
"""
|
|
41
|
+
Initialize an AdvancedTracker instance for object tracking.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
config (TrackerConfig): Tracker configuration object.
|
|
45
|
+
"""
|
|
46
|
+
self.tracked_stracks = [] # type: List[STrack]
|
|
47
|
+
self.lost_stracks = [] # type: List[STrack]
|
|
48
|
+
self.removed_stracks = [] # type: List[STrack]
|
|
49
|
+
|
|
50
|
+
self.frame_id = 0
|
|
51
|
+
self.config = config
|
|
52
|
+
self.max_time_lost = config.max_time_lost
|
|
53
|
+
self.kalman_filter = self.get_kalmanfilter()
|
|
54
|
+
self.reset_id()
|
|
55
|
+
|
|
56
|
+
def update(self, detections: Union[List[Dict], Dict[str, List[Dict]]],
|
|
57
|
+
img: Optional[np.ndarray] = None) -> Union[List[Dict], Dict[str, List[Dict]]]:
|
|
58
|
+
"""
|
|
59
|
+
Update the tracker with new detections and return the current list of tracked objects.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
detections: Detection results in various formats:
|
|
63
|
+
- List[Dict]: Single frame detections
|
|
64
|
+
- Dict[str, List[Dict]]: Multi-frame detections with frame keys
|
|
65
|
+
img: Optional image for motion compensation
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Tracking results in the same format as input
|
|
69
|
+
"""
|
|
70
|
+
self.frame_id += 1
|
|
71
|
+
|
|
72
|
+
# Handle different input formats
|
|
73
|
+
if isinstance(detections, dict):
|
|
74
|
+
# Multi-frame format
|
|
75
|
+
return self._update_multi_frame(detections, img)
|
|
76
|
+
else:
|
|
77
|
+
# Single frame format
|
|
78
|
+
return self._update_single_frame(detections, img)
|
|
79
|
+
|
|
80
|
+
def _update_single_frame(self, detections: List[Dict], img: Optional[np.ndarray] = None) -> List[Dict]:
|
|
81
|
+
"""Update tracker with single frame detections."""
|
|
82
|
+
# Convert detections to STrack format
|
|
83
|
+
stracks = self._convert_detections_to_stracks(detections)
|
|
84
|
+
|
|
85
|
+
# Perform tracking update
|
|
86
|
+
tracked_objects = self._perform_tracking_update(stracks, img)
|
|
87
|
+
|
|
88
|
+
# Convert back to detection format
|
|
89
|
+
return self._convert_stracks_to_detections(tracked_objects)
|
|
90
|
+
|
|
91
|
+
def _update_multi_frame(self, detections: Dict[str, List[Dict]],
|
|
92
|
+
img: Optional[np.ndarray] = None) -> Dict[str, List[Dict]]:
|
|
93
|
+
"""Update tracker with multi-frame detections."""
|
|
94
|
+
results = {}
|
|
95
|
+
|
|
96
|
+
for frame_key, frame_detections in detections.items():
|
|
97
|
+
# Convert frame detections to STrack format
|
|
98
|
+
stracks = self._convert_detections_to_stracks(frame_detections)
|
|
99
|
+
|
|
100
|
+
# Perform tracking update
|
|
101
|
+
tracked_objects = self._perform_tracking_update(stracks, img)
|
|
102
|
+
|
|
103
|
+
# Convert back to detection format
|
|
104
|
+
results[frame_key] = self._convert_stracks_to_detections(tracked_objects)
|
|
105
|
+
|
|
106
|
+
return results
|
|
107
|
+
|
|
108
|
+
def _convert_detections_to_stracks(self, detections: List[Dict]) -> List[STrack]:
|
|
109
|
+
"""Convert detection format to STrack objects."""
|
|
110
|
+
stracks = []
|
|
111
|
+
|
|
112
|
+
for i, det in enumerate(detections):
|
|
113
|
+
# Extract bounding box
|
|
114
|
+
bbox = det.get('bounding_box', {})
|
|
115
|
+
if 'x' in bbox and 'y' in bbox and 'width' in bbox and 'height' in bbox:
|
|
116
|
+
# Center format
|
|
117
|
+
x, y, w, h = bbox['x'], bbox['y'], bbox['width'], bbox['height']
|
|
118
|
+
elif 'xmin' in bbox and 'ymin' in bbox and 'xmax' in bbox and 'ymax' in bbox:
|
|
119
|
+
# Corner format
|
|
120
|
+
x = (bbox['xmin'] + bbox['xmax']) / 2
|
|
121
|
+
y = (bbox['ymin'] + bbox['ymax']) / 2
|
|
122
|
+
w = bbox['xmax'] - bbox['xmin']
|
|
123
|
+
h = bbox['ymax'] - bbox['ymin']
|
|
124
|
+
else:
|
|
125
|
+
# Try to extract from any format
|
|
126
|
+
values = list(bbox.values())
|
|
127
|
+
if len(values) >= 4:
|
|
128
|
+
x, y, w, h = values[0], values[1], values[2], values[3]
|
|
129
|
+
else:
|
|
130
|
+
continue
|
|
131
|
+
|
|
132
|
+
# Extract other properties
|
|
133
|
+
score = det.get('confidence', 0.0)
|
|
134
|
+
category = det.get('category', 'unknown')
|
|
135
|
+
|
|
136
|
+
# Create STrack
|
|
137
|
+
xywh = [x, y, w, h, i] # Add index as last element
|
|
138
|
+
strack = STrack(xywh, score, category)
|
|
139
|
+
|
|
140
|
+
# CRITICAL FIX: Store the original detection data to preserve all fields
|
|
141
|
+
# This ensures face recognition fields (embedding, landmarks, etc.) are preserved
|
|
142
|
+
strack.original_detection = det.copy()
|
|
143
|
+
|
|
144
|
+
stracks.append(strack)
|
|
145
|
+
|
|
146
|
+
return stracks
|
|
147
|
+
|
|
148
|
+
def _convert_stracks_to_detections(self, stracks: List[STrack]) -> List[Dict]:
|
|
149
|
+
"""Convert STrack objects back to detection format."""
|
|
150
|
+
detections = []
|
|
151
|
+
|
|
152
|
+
for strack in stracks:
|
|
153
|
+
if strack.is_activated:
|
|
154
|
+
# Get bounding box in xyxy format
|
|
155
|
+
xyxy = strack.xyxy
|
|
156
|
+
|
|
157
|
+
# CRITICAL FIX: Start with original detection data to preserve all fields
|
|
158
|
+
if hasattr(strack, 'original_detection') and strack.original_detection:
|
|
159
|
+
# Start with the original detection to preserve all face recognition fields
|
|
160
|
+
detection = strack.original_detection.copy()
|
|
161
|
+
|
|
162
|
+
# Update with tracking-specific fields
|
|
163
|
+
detection['bounding_box'] = {
|
|
164
|
+
'xmin': float(xyxy[0]),
|
|
165
|
+
'ymin': float(xyxy[1]),
|
|
166
|
+
'xmax': float(xyxy[2]),
|
|
167
|
+
'ymax': float(xyxy[3])
|
|
168
|
+
}
|
|
169
|
+
detection['confidence'] = float(strack.score)
|
|
170
|
+
detection['category'] = strack.cls
|
|
171
|
+
detection['track_id'] = int(strack.track_id)
|
|
172
|
+
detection['frame_id'] = int(strack.frame_id)
|
|
173
|
+
else:
|
|
174
|
+
# Fallback to minimal detection if original data not available
|
|
175
|
+
detection = {
|
|
176
|
+
'bounding_box': {
|
|
177
|
+
'xmin': float(xyxy[0]),
|
|
178
|
+
'ymin': float(xyxy[1]),
|
|
179
|
+
'xmax': float(xyxy[2]),
|
|
180
|
+
'ymax': float(xyxy[3])
|
|
181
|
+
},
|
|
182
|
+
'confidence': float(strack.score),
|
|
183
|
+
'category': strack.cls,
|
|
184
|
+
'track_id': int(strack.track_id),
|
|
185
|
+
'frame_id': int(strack.frame_id)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
detections.append(detection)
|
|
189
|
+
|
|
190
|
+
return detections
|
|
191
|
+
|
|
192
|
+
def _perform_tracking_update(self, detections: List[STrack],
|
|
193
|
+
img: Optional[np.ndarray] = None) -> List[STrack]:
|
|
194
|
+
"""Perform the core tracking update algorithm."""
|
|
195
|
+
activated_stracks = []
|
|
196
|
+
refind_stracks = []
|
|
197
|
+
lost_stracks = []
|
|
198
|
+
removed_stracks = []
|
|
199
|
+
|
|
200
|
+
# Separate high and low confidence detections
|
|
201
|
+
scores = np.array([det.score for det in detections])
|
|
202
|
+
remain_inds = scores >= self.config.track_high_thresh
|
|
203
|
+
inds_low = scores > self.config.track_low_thresh
|
|
204
|
+
inds_high = scores < self.config.track_high_thresh
|
|
205
|
+
|
|
206
|
+
inds_second = inds_low & inds_high
|
|
207
|
+
dets_second = [detections[i] for i in range(len(detections)) if inds_second[i]]
|
|
208
|
+
dets = [detections[i] for i in range(len(detections)) if remain_inds[i]]
|
|
209
|
+
scores_keep = scores[remain_inds]
|
|
210
|
+
scores_second = scores[inds_second]
|
|
211
|
+
|
|
212
|
+
# Step 1: First association, with high score detection boxes
|
|
213
|
+
unconfirmed = []
|
|
214
|
+
tracked_stracks = []
|
|
215
|
+
for track in self.tracked_stracks:
|
|
216
|
+
if not track.is_activated:
|
|
217
|
+
unconfirmed.append(track)
|
|
218
|
+
else:
|
|
219
|
+
tracked_stracks.append(track)
|
|
220
|
+
|
|
221
|
+
# Predict the current location with KF
|
|
222
|
+
strack_pool = self.joint_stracks(tracked_stracks, self.lost_stracks)
|
|
223
|
+
self.multi_predict(strack_pool)
|
|
224
|
+
|
|
225
|
+
# Calculate distances and perform matching
|
|
226
|
+
dists = self.get_dists(strack_pool, dets)
|
|
227
|
+
matches, u_track, u_detection = linear_assignment(dists, thresh=self.config.match_thresh)
|
|
228
|
+
|
|
229
|
+
for itracked, idet in matches:
|
|
230
|
+
track = strack_pool[itracked]
|
|
231
|
+
det = dets[idet]
|
|
232
|
+
if track.state == TrackState.Tracked:
|
|
233
|
+
track.update(det, self.frame_id)
|
|
234
|
+
activated_stracks.append(track)
|
|
235
|
+
else:
|
|
236
|
+
track.re_activate(det, self.frame_id, new_id=False)
|
|
237
|
+
refind_stracks.append(track)
|
|
238
|
+
|
|
239
|
+
# Step 2: Second association, with low score detection boxes
|
|
240
|
+
r_tracked_stracks = [strack_pool[i] for i in u_track if strack_pool[i].state == TrackState.Tracked]
|
|
241
|
+
dists = iou_distance(r_tracked_stracks, dets_second)
|
|
242
|
+
matches, u_track, u_detection_second = linear_assignment(dists, thresh=0.5)
|
|
243
|
+
|
|
244
|
+
for itracked, idet in matches:
|
|
245
|
+
track = r_tracked_stracks[itracked]
|
|
246
|
+
det = dets_second[idet]
|
|
247
|
+
if track.state == TrackState.Tracked:
|
|
248
|
+
track.update(det, self.frame_id)
|
|
249
|
+
activated_stracks.append(track)
|
|
250
|
+
else:
|
|
251
|
+
track.re_activate(det, self.frame_id, new_id=False)
|
|
252
|
+
refind_stracks.append(track)
|
|
253
|
+
|
|
254
|
+
for it in u_track:
|
|
255
|
+
track = r_tracked_stracks[it]
|
|
256
|
+
if track.state != TrackState.Lost:
|
|
257
|
+
track.mark_lost()
|
|
258
|
+
lost_stracks.append(track)
|
|
259
|
+
|
|
260
|
+
# Step 3: Deal with unconfirmed tracks
|
|
261
|
+
detections = [dets[i] for i in u_detection]
|
|
262
|
+
dists = self.get_dists(unconfirmed, detections)
|
|
263
|
+
matches, u_unconfirmed, u_detection = linear_assignment(dists, thresh=0.7)
|
|
264
|
+
|
|
265
|
+
for itracked, idet in matches:
|
|
266
|
+
unconfirmed[itracked].update(detections[idet], self.frame_id)
|
|
267
|
+
activated_stracks.append(unconfirmed[itracked])
|
|
268
|
+
|
|
269
|
+
for it in u_unconfirmed:
|
|
270
|
+
track = unconfirmed[it]
|
|
271
|
+
track.mark_removed()
|
|
272
|
+
removed_stracks.append(track)
|
|
273
|
+
|
|
274
|
+
# Step 4: Init new stracks
|
|
275
|
+
for inew in u_detection:
|
|
276
|
+
track = detections[inew]
|
|
277
|
+
if track.score < self.config.new_track_thresh:
|
|
278
|
+
continue
|
|
279
|
+
track.activate(self.kalman_filter, self.frame_id)
|
|
280
|
+
activated_stracks.append(track)
|
|
281
|
+
|
|
282
|
+
# Step 5: Update state
|
|
283
|
+
for track in self.lost_stracks:
|
|
284
|
+
if self.frame_id - track.end_frame > self.max_time_lost:
|
|
285
|
+
track.mark_removed()
|
|
286
|
+
removed_stracks.append(track)
|
|
287
|
+
|
|
288
|
+
self.tracked_stracks = [t for t in self.tracked_stracks if t.state == TrackState.Tracked]
|
|
289
|
+
self.tracked_stracks = self.joint_stracks(self.tracked_stracks, activated_stracks)
|
|
290
|
+
self.tracked_stracks = self.joint_stracks(self.tracked_stracks, refind_stracks)
|
|
291
|
+
self.lost_stracks = self.sub_stracks(self.lost_stracks, self.tracked_stracks)
|
|
292
|
+
self.lost_stracks.extend(lost_stracks)
|
|
293
|
+
self.lost_stracks = self.sub_stracks(self.lost_stracks, self.removed_stracks)
|
|
294
|
+
self.tracked_stracks, self.lost_stracks = self.remove_duplicate_stracks(self.tracked_stracks, self.lost_stracks)
|
|
295
|
+
self.removed_stracks.extend(removed_stracks)
|
|
296
|
+
|
|
297
|
+
if len(self.removed_stracks) > 1000:
|
|
298
|
+
self.removed_stracks = self.removed_stracks[-999:]
|
|
299
|
+
|
|
300
|
+
return [x for x in self.tracked_stracks if x.is_activated]
|
|
301
|
+
|
|
302
|
+
def get_kalmanfilter(self) -> KalmanFilterXYAH:
|
|
303
|
+
"""Return a Kalman filter object for tracking bounding boxes using KalmanFilterXYAH."""
|
|
304
|
+
return KalmanFilterXYAH()
|
|
305
|
+
|
|
306
|
+
def get_dists(self, tracks: List[STrack], detections: List[STrack]) -> np.ndarray:
|
|
307
|
+
"""Calculate the distance between tracks and detections using IoU and optionally fuse scores."""
|
|
308
|
+
dists = iou_distance(tracks, detections)
|
|
309
|
+
if self.config.fuse_score:
|
|
310
|
+
dists = fuse_score(dists, detections)
|
|
311
|
+
return dists
|
|
312
|
+
|
|
313
|
+
def multi_predict(self, tracks: List[STrack]):
|
|
314
|
+
"""Predict the next states for multiple tracks using Kalman filter."""
|
|
315
|
+
STrack.multi_predict(tracks)
|
|
316
|
+
|
|
317
|
+
@staticmethod
|
|
318
|
+
def reset_id():
|
|
319
|
+
"""Reset the ID counter for STrack instances to ensure unique track IDs across tracking sessions."""
|
|
320
|
+
STrack.reset_id()
|
|
321
|
+
|
|
322
|
+
def reset(self):
|
|
323
|
+
"""Reset the tracker by clearing all tracked, lost, and removed tracks and reinitializing the Kalman filter."""
|
|
324
|
+
self.tracked_stracks = []
|
|
325
|
+
self.lost_stracks = []
|
|
326
|
+
self.removed_stracks = []
|
|
327
|
+
self.frame_id = 0
|
|
328
|
+
self.kalman_filter = self.get_kalmanfilter()
|
|
329
|
+
self.reset_id()
|
|
330
|
+
|
|
331
|
+
@staticmethod
|
|
332
|
+
def joint_stracks(tlista: List[STrack], tlistb: List[STrack]) -> List[STrack]:
|
|
333
|
+
"""Combine two lists of STrack objects into a single list, ensuring no duplicates based on track IDs."""
|
|
334
|
+
exists = {}
|
|
335
|
+
res = []
|
|
336
|
+
for t in tlista:
|
|
337
|
+
exists[t.track_id] = 1
|
|
338
|
+
res.append(t)
|
|
339
|
+
for t in tlistb:
|
|
340
|
+
tid = t.track_id
|
|
341
|
+
if not exists.get(tid, 0):
|
|
342
|
+
exists[tid] = 1
|
|
343
|
+
res.append(t)
|
|
344
|
+
return res
|
|
345
|
+
|
|
346
|
+
@staticmethod
|
|
347
|
+
def sub_stracks(tlista: List[STrack], tlistb: List[STrack]) -> List[STrack]:
|
|
348
|
+
"""Filter out the stracks present in the second list from the first list."""
|
|
349
|
+
track_ids_b = {t.track_id for t in tlistb}
|
|
350
|
+
return [t for t in tlista if t.track_id not in track_ids_b]
|
|
351
|
+
|
|
352
|
+
@staticmethod
|
|
353
|
+
def remove_duplicate_stracks(stracksa: List[STrack], stracksb: List[STrack]) -> Tuple[List[STrack], List[STrack]]:
|
|
354
|
+
"""Remove duplicate stracks from two lists based on Intersection over Union (IoU) distance."""
|
|
355
|
+
pdist = iou_distance(stracksa, stracksb)
|
|
356
|
+
pairs = np.where(pdist < 0.15)
|
|
357
|
+
dupa, dupb = [], []
|
|
358
|
+
for p, q in zip(*pairs):
|
|
359
|
+
timep = stracksa[p].frame_id - stracksa[p].start_frame
|
|
360
|
+
timeq = stracksb[q].frame_id - stracksb[q].start_frame
|
|
361
|
+
if timep > timeq:
|
|
362
|
+
dupb.append(q)
|
|
363
|
+
else:
|
|
364
|
+
dupa.append(p)
|
|
365
|
+
resa = [t for i, t in enumerate(stracksa) if i not in dupa]
|
|
366
|
+
resb = [t for i, t in enumerate(stracksb) if i not in dupb]
|
|
367
|
+
return resa, resb
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
APP_NAME_TO_USECASE = {
|
|
2
|
+
"people_counting": "people_counting",
|
|
3
|
+
"drone_traffic_monitoring": "drone_traffic_monitoring",
|
|
4
|
+
"intrusion_detection": "intrusion_detection",
|
|
5
|
+
"proximity_detection": "proximity_detection",
|
|
6
|
+
"mask_detection": "mask_detection",
|
|
7
|
+
"pipeline_detection": "pipeline_detection",
|
|
8
|
+
"vehicle_monitoring": "vehicle_monitoring",
|
|
9
|
+
"Vehicle Type Monitoring": "vehicle_monitoring",
|
|
10
|
+
"weapon_detection": "weapon_detection",
|
|
11
|
+
"traffic_sign_monitoring": "traffic_sign_monitoring",
|
|
12
|
+
"flare_analysis": "flare_analysis",
|
|
13
|
+
"ppe_compliance": "ppe_compliance",
|
|
14
|
+
"advanced_customer_service": "advanced_customer_service",
|
|
15
|
+
"assembly_line_detection": "assembly_line_detection",
|
|
16
|
+
"crop_weed_detection" : "crop_weed_detection",
|
|
17
|
+
"emergency_vehicle_detection": "emergency_vehicle_detection",
|
|
18
|
+
"fashion_detection": "fashion_detection",
|
|
19
|
+
"gender_detection": "gender_detection",
|
|
20
|
+
"price_tag_detection": "price_tag_detection",
|
|
21
|
+
"windmill_maintenance": "windmill_maintenance",
|
|
22
|
+
"underwater_pollution_detection": "underwater_pollution_detection",
|
|
23
|
+
"solar_panel": "solar_panel",
|
|
24
|
+
"face_emotion": "face_emotion",
|
|
25
|
+
"pedestrian_detection": "pedestrian_detection",
|
|
26
|
+
"warehouse_object_segmentation": "warehouse_object_segmentation",
|
|
27
|
+
"flower_segmentation": "flower_segmentation",
|
|
28
|
+
"shopping_cart_analysis": "shopping_cart_analysis",
|
|
29
|
+
"car_part_segmentation": "car_part_segmentation",
|
|
30
|
+
"weld_defect_detection" : "weld_defect_detection",
|
|
31
|
+
"fruit_monitoring" : "fruit_monitoring",
|
|
32
|
+
"concrete_crack_detection": "concrete_crack_detection",
|
|
33
|
+
"lane_detection" : "lane_detection",
|
|
34
|
+
"shelf_inventory" :"shelf_inventory",
|
|
35
|
+
"smoker_detection": "smoker_detection",
|
|
36
|
+
"age_detection": "age_detection",
|
|
37
|
+
"defect_detection_products": "defect_detection_products",
|
|
38
|
+
"parking_space_detection": "parking_space_detection",
|
|
39
|
+
"car_damage_detection": "car_damage_detection",
|
|
40
|
+
"license_plate_detection": "license_plate_detection",
|
|
41
|
+
"shoplifting_detection": "shoplifting_detection",
|
|
42
|
+
"cardiomegaly_classification": "cardiomegaly_classification",
|
|
43
|
+
"road_traffic_density": "road_traffic_density",
|
|
44
|
+
"histopathological_cancer_detection" : "histopathological_cancer_detection",
|
|
45
|
+
"road_view_segmentation": "road_view_segmentation",
|
|
46
|
+
"face_recognition": "face_recognition",
|
|
47
|
+
"drowsy_driver_detection": "drowsy_driver_detection",
|
|
48
|
+
"waterbody_segmentation": "waterbody_segmentation",
|
|
49
|
+
"litter_detection" : "litter_detection",
|
|
50
|
+
"leak_detection": "leak_detection",
|
|
51
|
+
"Fire Safety Monitoring": "fire_smoke_detection",
|
|
52
|
+
"human_activity_recognition": "human_activity_recognition",
|
|
53
|
+
"abandoned_object_detection" : "abandoned_object_detection",
|
|
54
|
+
"gas_leak_detection": "gas_leak_detection",
|
|
55
|
+
"color_detection": "color_detection",
|
|
56
|
+
"Color Detection": "color_detection",
|
|
57
|
+
"License Plate Recognition" : "license_plate_monitor",
|
|
58
|
+
"License Plate Monitoring" : "license_plate_monitor",
|
|
59
|
+
"cell_microscopy_segmentation": "cell_microscopy_segmentation",
|
|
60
|
+
"Dwell Detection": "dwell",
|
|
61
|
+
"age_gender_detection": "age_gender_detection",
|
|
62
|
+
"People Tracking" : "people_tracking",
|
|
63
|
+
"wildlife_monitoring": "wildlife_monitoring",
|
|
64
|
+
"pcb_defect_detection": "pcb_defect_detection",
|
|
65
|
+
"underground_pipeline_defect" : "underground_pipeline_defect",
|
|
66
|
+
"suspicious_activity_detection": "suspicious_activity_detection",
|
|
67
|
+
"natural_disaster_detection": "natural_disaster_detection",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
APP_NAME_TO_CATEGORY = {
|
|
71
|
+
"people_counting": "general",
|
|
72
|
+
"drone_traffic_monitoring": "traffic",
|
|
73
|
+
"intrusion_detection": "security",
|
|
74
|
+
"proximity_detection": "security",
|
|
75
|
+
"mask_detection": "mask_detection",
|
|
76
|
+
"pipeline_detection": "pipeline_detection",
|
|
77
|
+
"vehicle_monitoring": "traffic",
|
|
78
|
+
"Vehicle Type Monitoring": "traffic",
|
|
79
|
+
"weapon_detection": "security",
|
|
80
|
+
"traffic_sign_monitoring": "traffic",
|
|
81
|
+
"flare_analysis": "flare_detection",
|
|
82
|
+
"ppe_compliance": "security",
|
|
83
|
+
"advanced_customer_service": "sales",
|
|
84
|
+
"assembly_line_detection": "manufacturing",
|
|
85
|
+
"crop_weed_detection": "agriculture",
|
|
86
|
+
"emergency_vehicle_detection": "traffic",
|
|
87
|
+
"fashion_detection": "retail",
|
|
88
|
+
"gender_detection": "general",
|
|
89
|
+
"price_tag_detection": "retail",
|
|
90
|
+
"windmill_maintenance": "windmill_maintenance",
|
|
91
|
+
"underwater_pollution_detection": "environmental",
|
|
92
|
+
"solar_panel": "energy",
|
|
93
|
+
"face_emotion": "general",
|
|
94
|
+
"pedestrian_detection": "pedestrian",
|
|
95
|
+
"warehouse_object_segmentation": "retail",
|
|
96
|
+
"flower_segmentation": "agriculture",
|
|
97
|
+
"shopping_cart_analysis": "retail",
|
|
98
|
+
"car_part_segmentation": "automobile",
|
|
99
|
+
"weld_defect_detection" : "weld",
|
|
100
|
+
"fruit_monitoring" : "agriculture",
|
|
101
|
+
"concrete_crack_detection": "general",
|
|
102
|
+
"lane_detection" : "traffic",
|
|
103
|
+
"shelf_inventory" : "retail",
|
|
104
|
+
"smoker_detection": "general",
|
|
105
|
+
"age_detection": "general",
|
|
106
|
+
"defect_detection_products": "retail",
|
|
107
|
+
"parking_space_detection": "parking_space",
|
|
108
|
+
"car_damage_detection": "car_damage",
|
|
109
|
+
"license_plate_detection": "license_plate",
|
|
110
|
+
"shoplifting_detection": "security",
|
|
111
|
+
"cardiomegaly_classification": "healthcare",
|
|
112
|
+
"road_traffic_density": "automobile",
|
|
113
|
+
"histopathological_cancer_detection" : "healthcare",
|
|
114
|
+
"road_view_segmentation": "automobile",
|
|
115
|
+
"face_recognition": "security",
|
|
116
|
+
"drowsy_driver_detection": "automobile",
|
|
117
|
+
"waterbody_segmentation": "agriculture",
|
|
118
|
+
"litter_detection" : "litter_detection",
|
|
119
|
+
"leak_detection": "oil_gas",
|
|
120
|
+
"Fire Safety Monitoring": "hazard",
|
|
121
|
+
"human_activity_recognition": "general",
|
|
122
|
+
"abandoned_object_detection" : "security",
|
|
123
|
+
"gas_leak_detection": "oil_gas",
|
|
124
|
+
"color_detection": "visual_appearance",
|
|
125
|
+
"Color Detection": "visual_appearance",
|
|
126
|
+
"License Plate Recognition" : "license_plate_monitor",
|
|
127
|
+
"License Plate Monitoring" : "license_plate_monitor",
|
|
128
|
+
"cell_microscopy_segmentation" : "healthcare",
|
|
129
|
+
"Dwell Detection": "general",
|
|
130
|
+
"age_gender_detection": "age_gender_detection",
|
|
131
|
+
"People Tracking" : "general",
|
|
132
|
+
|
|
133
|
+
"wildlife_monitoring": "environmental",
|
|
134
|
+
"pcb_defect_detection": "manufacturing",
|
|
135
|
+
"underground_pipeline_defect" : "general",
|
|
136
|
+
"suspicious_activity_detection": "security",
|
|
137
|
+
"natural_disaster_detection": "environmental",
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
def get_usecase_from_app_name(app_name: str) -> str:
|
|
141
|
+
normalized_app_name = app_name.lower().replace(" ", "_").replace("-", "_")
|
|
142
|
+
return APP_NAME_TO_USECASE.get(app_name, APP_NAME_TO_USECASE.get(normalized_app_name))
|
|
143
|
+
|
|
144
|
+
def get_category_from_app_name(app_name: str) -> str:
|
|
145
|
+
normalized_app_name = app_name.lower().replace(" ", "_").replace("-", "_")
|
|
146
|
+
return APP_NAME_TO_CATEGORY.get(app_name, APP_NAME_TO_CATEGORY.get(normalized_app_name))
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core components for post-processing.
|
|
3
|
+
|
|
4
|
+
This module contains core base classes and configuration utilities.
|
|
5
|
+
Note: Use case imports have been moved to avoid circular imports.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Core components that don't create circular imports
|
|
9
|
+
from .base import (
|
|
10
|
+
ProcessingResult,
|
|
11
|
+
ProcessingContext,
|
|
12
|
+
ProcessingStatus,
|
|
13
|
+
ResultFormat,
|
|
14
|
+
BaseProcessor,
|
|
15
|
+
BaseUseCase,
|
|
16
|
+
ProcessorRegistry,
|
|
17
|
+
registry
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .config import (
|
|
21
|
+
BaseConfig,
|
|
22
|
+
PeopleCountingConfig,
|
|
23
|
+
CustomerServiceConfig,
|
|
24
|
+
IntrusionConfig,
|
|
25
|
+
ZoneConfig,
|
|
26
|
+
TrackingConfig,
|
|
27
|
+
AlertConfig,
|
|
28
|
+
ConfigManager,
|
|
29
|
+
config_manager,
|
|
30
|
+
ConfigValidationError,
|
|
31
|
+
PeopleTrackingConfig
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Note: Use case imports have been removed from this file to avoid circular imports.
|
|
35
|
+
# Use cases should be imported directly from their respective modules in the usecases package.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Export only core components to avoid circular imports
|
|
39
|
+
__all__ = [
|
|
40
|
+
# Base classes
|
|
41
|
+
'ProcessingResult',
|
|
42
|
+
'ProcessingContext',
|
|
43
|
+
'ProcessingStatus',
|
|
44
|
+
'ResultFormat',
|
|
45
|
+
'BaseProcessor',
|
|
46
|
+
'BaseUseCase',
|
|
47
|
+
'ProcessorRegistry',
|
|
48
|
+
'registry',
|
|
49
|
+
|
|
50
|
+
# Configuration classes
|
|
51
|
+
'BaseConfig',
|
|
52
|
+
'PeopleCountingConfig',
|
|
53
|
+
'IntrusionConfig',
|
|
54
|
+
'ProximityConfig',
|
|
55
|
+
'CustomerServiceConfig',
|
|
56
|
+
'ZoneConfig',
|
|
57
|
+
'TrackingConfig',
|
|
58
|
+
'AlertConfig',
|
|
59
|
+
'ConfigManager',
|
|
60
|
+
'config_manager',
|
|
61
|
+
'ConfigValidationError',
|
|
62
|
+
'PeopleTrackingConfig',
|
|
63
|
+
]
|