matrice-analytics 0.1.45__py3-none-any.whl → 0.1.46__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.
Potentially problematic release.
This version of matrice-analytics might be problematic. Click here for more details.
- matrice_analytics/post_processing/face_reg/face_recognition.py +110 -76
- matrice_analytics/post_processing/face_reg/face_recognition_client.py +20 -25
- matrice_analytics/post_processing/face_reg/people_activity_logging.py +5 -7
- {matrice_analytics-0.1.45.dist-info → matrice_analytics-0.1.46.dist-info}/METADATA +1 -1
- {matrice_analytics-0.1.45.dist-info → matrice_analytics-0.1.46.dist-info}/RECORD +8 -8
- {matrice_analytics-0.1.45.dist-info → matrice_analytics-0.1.46.dist-info}/WHEEL +0 -0
- {matrice_analytics-0.1.45.dist-info → matrice_analytics-0.1.46.dist-info}/licenses/LICENSE.txt +0 -0
- {matrice_analytics-0.1.45.dist-info → matrice_analytics-0.1.46.dist-info}/top_level.txt +0 -0
|
@@ -24,7 +24,7 @@ subprocess.run(
|
|
|
24
24
|
cmd,
|
|
25
25
|
stdout=log_file,
|
|
26
26
|
stderr=subprocess.STDOUT,
|
|
27
|
-
#
|
|
27
|
+
#preexec_fn=os.setpgrp
|
|
28
28
|
)
|
|
29
29
|
log_file.close()
|
|
30
30
|
|
|
@@ -81,13 +81,13 @@ class TemporalIdentityManager:
|
|
|
81
81
|
"""
|
|
82
82
|
Maintains stable identity labels per tracker ID using temporal smoothing and embedding history.
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Adaptation for production: _compute_best_identity queries the face recognition API
|
|
85
|
+
via search_similar_faces(embedding, threshold=0.01, limit=1) to obtain top-1 match and score.
|
|
85
86
|
"""
|
|
86
87
|
|
|
87
88
|
def __init__(
|
|
88
89
|
self,
|
|
89
90
|
face_client: FacialRecognitionClient,
|
|
90
|
-
embedding_manager: Optional[Any] = None, # EmbeddingManager instance
|
|
91
91
|
recognition_threshold: float = 0.35,
|
|
92
92
|
history_size: int = 20,
|
|
93
93
|
unknown_patience: int = 7,
|
|
@@ -96,7 +96,6 @@ class TemporalIdentityManager:
|
|
|
96
96
|
) -> None:
|
|
97
97
|
self.logger = logging.getLogger(__name__)
|
|
98
98
|
self.face_client = face_client
|
|
99
|
-
self.embedding_manager = embedding_manager
|
|
100
99
|
self.threshold = float(recognition_threshold)
|
|
101
100
|
self.history_size = int(history_size)
|
|
102
101
|
self.unknown_patience = int(unknown_patience)
|
|
@@ -120,65 +119,69 @@ class TemporalIdentityManager:
|
|
|
120
119
|
|
|
121
120
|
async def _compute_best_identity(self, emb: List[float], location: str = "", timestamp: str = "") -> Tuple[Optional[str], str, float, Optional[str], Dict[str, Any], str]:
|
|
122
121
|
"""
|
|
123
|
-
Query
|
|
122
|
+
Query backend for top-1 match for the given embedding.
|
|
124
123
|
Returns (staff_id, person_name, score, employee_id, staff_details, detection_type).
|
|
125
|
-
|
|
126
|
-
NOTE: API call to search_similar_faces is commented out - using local embeddings only.
|
|
124
|
+
Robust to varying response shapes.
|
|
127
125
|
"""
|
|
128
126
|
if not emb or not isinstance(emb, list):
|
|
129
127
|
return None, "Unknown", 0.0, None, {}, "unknown"
|
|
130
|
-
|
|
131
|
-
# COMMENTED OUT: API-based search - now using local embedding similarity search
|
|
132
|
-
# try:
|
|
133
|
-
# resp = await self.face_client.search_similar_faces(
|
|
134
|
-
# face_embedding=emb,
|
|
135
|
-
# threshold=0.01, # low threshold to always get top-1
|
|
136
|
-
# limit=1,
|
|
137
|
-
# collection="staff_enrollment",
|
|
138
|
-
# location=location,
|
|
139
|
-
# timestamp=timestamp,
|
|
140
|
-
# )
|
|
141
|
-
# except Exception as e:
|
|
142
|
-
# self.logger.error(f"API ERROR: Failed to search similar faces in _compute_best_identity: {e}", exc_info=True)
|
|
143
|
-
# return None, "Unknown", 0.0, None, {}, "unknown"
|
|
144
|
-
#
|
|
145
|
-
# [API response parsing code removed - see git history]
|
|
146
|
-
|
|
147
|
-
# NEW: Use local embedding manager for similarity search
|
|
148
128
|
try:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
search_result = await self.embedding_manager.search_face_embedding(
|
|
155
|
-
embedding=emb,
|
|
156
|
-
track_id=None, # No track_id needed for this search
|
|
129
|
+
resp = await self.face_client.search_similar_faces(
|
|
130
|
+
face_embedding=emb,
|
|
131
|
+
threshold=0.01, # low threshold to always get top-1
|
|
132
|
+
limit=1,
|
|
133
|
+
collection="staff_enrollment",
|
|
157
134
|
location=location,
|
|
158
135
|
timestamp=timestamp,
|
|
159
136
|
)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
137
|
+
except Exception as e:
|
|
138
|
+
self.logger.error(f"API ERROR: Failed to search similar faces in _compute_best_identity: {e}", exc_info=True)
|
|
139
|
+
return None, "Unknown", 0.0, None, {}, "unknown"
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
results: List[Any] = []
|
|
143
|
+
self.logger.debug('API Response received for identity search')
|
|
144
|
+
if isinstance(resp, dict):
|
|
145
|
+
if isinstance(resp.get("data"), list):
|
|
146
|
+
results = resp.get("data", [])
|
|
147
|
+
elif isinstance(resp.get("results"), list):
|
|
148
|
+
results = resp.get("results", [])
|
|
149
|
+
elif isinstance(resp.get("items"), list):
|
|
150
|
+
results = resp.get("items", [])
|
|
151
|
+
elif isinstance(resp, list):
|
|
152
|
+
results = resp
|
|
153
|
+
|
|
154
|
+
if not results:
|
|
155
|
+
self.logger.debug("No identity match found from API")
|
|
163
156
|
return None, "Unknown", 0.0, None, {}, "unknown"
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
employee_id =
|
|
170
|
-
|
|
171
|
-
detection_type =
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
157
|
+
|
|
158
|
+
item = results[0] if isinstance(results, list) else results
|
|
159
|
+
self.logger.debug(f'Top-1 match from API: {item}')
|
|
160
|
+
# Be defensive with keys and types
|
|
161
|
+
staff_id = item.get("staffId") if isinstance(item, dict) else None
|
|
162
|
+
employee_id = str(item.get("_id")) if isinstance(item, dict) and item.get("_id") is not None else None
|
|
163
|
+
score = float(item.get("score", 0.0)) if isinstance(item, dict) else 0.0
|
|
164
|
+
detection_type = str(item.get("detectionType", "unknown")) if isinstance(item, dict) else "unknown"
|
|
165
|
+
staff_details = item.get("staffDetails", {}) if isinstance(item, dict) else {}
|
|
166
|
+
# Extract a person name from staff_details
|
|
167
|
+
person_name = "Unknown"
|
|
168
|
+
if isinstance(staff_details, dict) and staff_details:
|
|
169
|
+
first_name = staff_details.get("firstName")
|
|
170
|
+
last_name = staff_details.get("lastName")
|
|
171
|
+
name = staff_details.get("name")
|
|
172
|
+
if name:
|
|
173
|
+
person_name = str(name)
|
|
174
|
+
else:
|
|
175
|
+
if first_name or last_name:
|
|
176
|
+
person_name = f"{first_name or ''} {last_name or ''}".strip() or "UnknowNN" #TODO:ebugging change to normal once done
|
|
177
|
+
# If API says unknown or missing staff_id, treat as unknown
|
|
178
|
+
if not staff_id: #or detection_type == "unknown"
|
|
179
|
+
self.logger.debug(f"API returned unknown or missing staff_id - score={score}, employee_id={employee_id}")
|
|
175
180
|
return None, "Unknown", float(score), employee_id, staff_details if isinstance(staff_details, dict) else {}, "unknown"
|
|
176
|
-
|
|
177
|
-
self.logger.info(f"Local embedding identified face - staff_id={staff_id}, person_name={person_name}, score={score:.3f}")
|
|
181
|
+
self.logger.info(f"API identified face - staff_id={staff_id}, person_name={person_name}, score={score:.3f}")
|
|
178
182
|
return str(staff_id), person_name, float(score), employee_id, staff_details if isinstance(staff_details, dict) else {}, "known"
|
|
179
|
-
|
|
180
183
|
except Exception as e:
|
|
181
|
-
self.logger.error(f"Error
|
|
184
|
+
self.logger.error(f"Error parsing API response in _compute_best_identity: {e}", exc_info=True)
|
|
182
185
|
return None, "Unknown", 0.0, None, {}, "unknown"
|
|
183
186
|
|
|
184
187
|
async def _compute_best_identity_from_history(self, track_state: Dict[str, object], location: str = "", timestamp: str = "") -> Tuple[Optional[str], str, float, Optional[str], Dict[str, Any], str]:
|
|
@@ -485,17 +488,16 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
485
488
|
self.embedding_manager = EmbeddingManager(init_config.embedding_config, self.face_client)
|
|
486
489
|
self.logger.info("Embedding manager initialized")
|
|
487
490
|
|
|
488
|
-
# Initialize TemporalIdentityManager
|
|
491
|
+
# Initialize TemporalIdentityManager
|
|
489
492
|
self.temporal_identity_manager = TemporalIdentityManager(
|
|
490
493
|
face_client=self.face_client,
|
|
491
|
-
embedding_manager=self.embedding_manager, # Pass embedding manager for local similarity search
|
|
492
494
|
recognition_threshold=float(init_config.similarity_threshold),
|
|
493
495
|
history_size=20,
|
|
494
496
|
unknown_patience=7,
|
|
495
497
|
switch_patience=5,
|
|
496
498
|
fallback_margin=0.05,
|
|
497
499
|
)
|
|
498
|
-
self.logger.info("Temporal identity manager initialized
|
|
500
|
+
self.logger.info("Temporal identity manager initialized")
|
|
499
501
|
|
|
500
502
|
self._initialized = True
|
|
501
503
|
self.logger.info("Face recognition use case fully initialized")
|
|
@@ -633,7 +635,9 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
633
635
|
)
|
|
634
636
|
self.logger.debug("Applied category filtering")
|
|
635
637
|
|
|
636
|
-
|
|
638
|
+
print("------------------TILL TRACKER MS----------------------------")
|
|
639
|
+
print("LATENCY:",(time.time() - processing_start)*1000,"| Throughput fps:",(1.0 / (time.time() - processing_start)) if (time.time() - processing_start) > 0 else None)
|
|
640
|
+
print("------------------TILL TRACKER MS----------------------------")
|
|
637
641
|
# Advanced tracking (BYTETracker-like) - only if enabled
|
|
638
642
|
if config.enable_face_tracking:
|
|
639
643
|
from ..advanced_tracker import AdvancedTracker
|
|
@@ -673,6 +677,10 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
673
677
|
recognized_persons = {}
|
|
674
678
|
current_frame_staff_details = {}
|
|
675
679
|
|
|
680
|
+
print("------------------TRACKER INIT END----------------------------")
|
|
681
|
+
print("LATENCY:",(time.time() - processing_start)*1000,"| Throughput fps:",(1.0 / (time.time() - processing_start)) if (time.time() - processing_start) > 0 else None)
|
|
682
|
+
print("------------------TRACKER INIT END----------------------------")
|
|
683
|
+
|
|
676
684
|
# Process face recognition for each detection (if enabled)
|
|
677
685
|
if config.enable_face_recognition:
|
|
678
686
|
face_recognition_result = await self._process_face_recognition(
|
|
@@ -687,6 +695,10 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
687
695
|
detection["recognition_status"] = "disabled"
|
|
688
696
|
detection["enrolled"] = False
|
|
689
697
|
|
|
698
|
+
print("------------------FACE RECONG CONFIG ENABLED----------------------------")
|
|
699
|
+
print("LATENCY:",(time.time() - processing_start)*1000,"| Throughput fps:",(1.0 / (time.time() - processing_start)) if (time.time() - processing_start) > 0 else None)
|
|
700
|
+
print("------------------FACE RECONG CONFIG ENABLED----------------------------")
|
|
701
|
+
|
|
690
702
|
# Update tracking state for total count per label
|
|
691
703
|
self._update_tracking_state(processed_data)
|
|
692
704
|
|
|
@@ -719,6 +731,10 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
719
731
|
current_recognized_count, current_unknown_count, recognized_persons
|
|
720
732
|
))
|
|
721
733
|
|
|
734
|
+
print("------------------TILL FACE RECOG SUMMARY----------------------------")
|
|
735
|
+
print("LATENCY:",(time.time() - processing_start)*1000,"| Throughput fps:",(1.0 / (time.time() - processing_start)) if (time.time() - processing_start) > 0 else None)
|
|
736
|
+
print("------------------TILL FACE RECOG SUMMARY----------------------------")
|
|
737
|
+
|
|
722
738
|
# Add detections to the counting summary (standard pattern for detection use cases)
|
|
723
739
|
# Ensure display label is present for UI (does not affect logic/counters)
|
|
724
740
|
for _d in processed_data:
|
|
@@ -749,6 +765,12 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
749
765
|
business_analytics_list[0] if business_analytics_list else {}
|
|
750
766
|
)
|
|
751
767
|
summary = summary_list[0] if summary_list else {}
|
|
768
|
+
|
|
769
|
+
print("------------------TILL TRACKING STATS----------------------------")
|
|
770
|
+
print("LATENCY:",(time.time() - processing_start)*1000,"| Throughput fps:",(1.0 / (time.time() - processing_start)) if (time.time() - processing_start) > 0 else None)
|
|
771
|
+
print("------------------TILL TRACKING STATS----------------------------")
|
|
772
|
+
|
|
773
|
+
|
|
752
774
|
agg_summary = {
|
|
753
775
|
str(frame_number): {
|
|
754
776
|
"incidents": incidents,
|
|
@@ -861,6 +883,7 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
861
883
|
"""Process face recognition for each detection with embeddings"""
|
|
862
884
|
|
|
863
885
|
# Initialize face client only when needed and if credentials are available
|
|
886
|
+
st=time.time()
|
|
864
887
|
if not self.face_client:
|
|
865
888
|
try:
|
|
866
889
|
self.face_client = self._get_facial_recognition_client(config)
|
|
@@ -870,6 +893,9 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
870
893
|
)
|
|
871
894
|
# No client available, return empty list (no results)
|
|
872
895
|
return []
|
|
896
|
+
print("------------------FACE RECOG CLIENT INIT----------------------------")
|
|
897
|
+
print("LATENCY:",(time.time() - st)*1000,"| Throughput fps:",(1.0 / (time.time() - st)) if (time.time() - st) > 0 else None)
|
|
898
|
+
print("------------------FACE RECOG CLIENT INIT----------------------------")
|
|
873
899
|
|
|
874
900
|
# Initialize unknown faces storage if not exists
|
|
875
901
|
if not hasattr(self, "unknown_faces_storage"):
|
|
@@ -907,28 +933,21 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
907
933
|
# Generate current timestamp
|
|
908
934
|
current_timestamp = datetime.now(timezone.utc).isoformat()
|
|
909
935
|
|
|
910
|
-
|
|
911
|
-
#
|
|
912
|
-
|
|
913
|
-
|
|
936
|
+
final_detections = []
|
|
937
|
+
# Process detections sequentially to preserve order
|
|
938
|
+
for detection in detections:
|
|
939
|
+
|
|
940
|
+
# Process each detection sequentially with await to preserve order
|
|
941
|
+
st=time.time()
|
|
942
|
+
processed_detection = await self._process_face(
|
|
914
943
|
detection, current_frame, location, current_timestamp, config,
|
|
915
944
|
current_recognized_count, current_unknown_count,
|
|
916
945
|
recognized_persons, current_frame_staff_details
|
|
917
946
|
)
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
processed_detections = await asyncio.gather(*tasks, return_exceptions=True)
|
|
923
|
-
|
|
924
|
-
# Build final results and update counters (maintains order)
|
|
925
|
-
final_detections = []
|
|
926
|
-
for processed_detection in processed_detections:
|
|
927
|
-
# Handle exceptions from parallel processing
|
|
928
|
-
if isinstance(processed_detection, Exception):
|
|
929
|
-
self.logger.error(f"Error processing face detection: {processed_detection}", exc_info=True)
|
|
930
|
-
continue
|
|
931
|
-
|
|
947
|
+
print("------------------WHOLE FACE RECOG PROCESSING DETECTION----------------------------")
|
|
948
|
+
print("LATENCY:",(time.time() - st)*1000,"| Throughput fps:",(1.0 / (time.time() - st)) if (time.time() - st) > 0 else None)
|
|
949
|
+
print("------------------FACE RECOG PROCESSING DETECTION----------------------------")
|
|
950
|
+
|
|
932
951
|
# Include both known and unknown faces in final detections (maintains original order)
|
|
933
952
|
if processed_detection:
|
|
934
953
|
final_detections.append(processed_detection)
|
|
@@ -958,12 +977,16 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
958
977
|
) -> Dict:
|
|
959
978
|
|
|
960
979
|
# Extract and validate embedding using EmbeddingManager
|
|
980
|
+
st=time.time()
|
|
961
981
|
detection, embedding = self.embedding_manager.extract_embedding_from_detection(detection)
|
|
962
982
|
if not embedding:
|
|
963
983
|
return None
|
|
964
984
|
|
|
965
985
|
# Internal tracker-provided ID (from AdvancedTracker; ignore upstream IDs entirely)
|
|
966
986
|
track_id = detection.get("track_id")
|
|
987
|
+
print("------------------FACE RECOG EMBEDDING EXTRACTION----------------------------")
|
|
988
|
+
print("LATENCY:",(time.time() - st)*1000,"| Throughput fps:",(1.0 / (time.time() - st)) if (time.time() - st) > 0 else None)
|
|
989
|
+
print("------------------FACE RECOG EMBEDDING EXTRACTION----------------------------")
|
|
967
990
|
|
|
968
991
|
# Determine if detection is eligible for recognition (similar to compare_similarity gating)
|
|
969
992
|
bbox = detection.get("bounding_box", {}) or {}
|
|
@@ -1026,6 +1049,7 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1026
1049
|
except Exception:
|
|
1027
1050
|
pass
|
|
1028
1051
|
else: #if eligible for recognition
|
|
1052
|
+
st=time.time()
|
|
1029
1053
|
staff_id, person_name, similarity_score, employee_id, staff_details, detection_type = await self.temporal_identity_manager.update(
|
|
1030
1054
|
track_id=track_key,
|
|
1031
1055
|
emb=embedding,
|
|
@@ -1033,6 +1057,9 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1033
1057
|
location=location,
|
|
1034
1058
|
timestamp=current_timestamp,
|
|
1035
1059
|
)
|
|
1060
|
+
print("------------------FACE RECOG TEMPORAL IDENTITY MANAGER UPDATE----------------------------")
|
|
1061
|
+
print("LATENCY:",(time.time() - st)*1000,"| Throughput fps:",(1.0 / (time.time() - st)) if (time.time() - st) > 0 else None)
|
|
1062
|
+
print("------------------FACE RECOG TEMPORAL IDENTITY MANAGER UPDATE----------------------------")
|
|
1036
1063
|
except Exception as e:
|
|
1037
1064
|
self.logger.warning(f"TemporalIdentityManager update failed: {e}")
|
|
1038
1065
|
|
|
@@ -1095,7 +1122,7 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1095
1122
|
# If it later becomes recognized, we'll remove it from unknown set above
|
|
1096
1123
|
self._unknown_track_ids.add(internal_tid)
|
|
1097
1124
|
|
|
1098
|
-
# Enqueue detection for background logging with all required parameters
|
|
1125
|
+
# Enqueue detection for background logging with all required parameters
|
|
1099
1126
|
try:
|
|
1100
1127
|
# Log known faces for activity tracking (skip any employee_id starting with "unknown_")
|
|
1101
1128
|
if (
|
|
@@ -1106,15 +1133,22 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1106
1133
|
and employee_id
|
|
1107
1134
|
and not str(employee_id).startswith("unknown_")
|
|
1108
1135
|
):
|
|
1109
|
-
|
|
1110
|
-
self.people_activity_logging.enqueue_detection(
|
|
1136
|
+
st=time.time()
|
|
1137
|
+
await self.people_activity_logging.enqueue_detection(
|
|
1111
1138
|
detection=detection,
|
|
1112
1139
|
current_frame=current_frame,
|
|
1113
1140
|
location=location,
|
|
1114
1141
|
)
|
|
1142
|
+
print("------------------FACE RECOG ENQUEUEING DETECTION FOR ACTIVITY LOGGING----------------------------")
|
|
1143
|
+
print("LATENCY:",(time.time() - st)*1000,"| Throughput fps:",(1.0 / (time.time() - st)) if (time.time() - st) > 0 else None)
|
|
1144
|
+
print("------------------FACE RECOG ENQUEUEING DETECTION FOR ACTIVITY LOGGING----------------------------")
|
|
1145
|
+
|
|
1115
1146
|
self.logger.debug(f"Enqueued known face detection for activity logging: {detection.get('person_name', 'Unknown')}")
|
|
1116
1147
|
except Exception as e:
|
|
1117
1148
|
self.logger.error(f"Error enqueueing detection for activity logging: {e}")
|
|
1149
|
+
print("------------------FACE RECOG ENQUEUEING DETECTION FOR ACTIVITY LOGGING----------------------------")
|
|
1150
|
+
print("LATENCY:",(time.time() - st)*1000,"| Throughput fps:",(1.0 / (time.time() - st)) if (time.time() - st) > 0 else None)
|
|
1151
|
+
print("------------------FACE RECOG ENQUEUEING DETECTION FOR ACTIVITY LOGGING----------------------------")
|
|
1118
1152
|
|
|
1119
1153
|
return detection
|
|
1120
1154
|
|
|
@@ -182,9 +182,9 @@ class FacialRecognitionClient:
|
|
|
182
182
|
payload=enrollment_request,
|
|
183
183
|
base_url=self.server_base_url
|
|
184
184
|
)
|
|
185
|
-
self.logger.info(f"API RESPONSE: Staff enrollment completed - Success: {response.get('success', False)
|
|
186
|
-
if not response
|
|
187
|
-
self.logger.warning(f"Staff enrollment failed: {response.get('error', 'Unknown error')
|
|
185
|
+
self.logger.info(f"API RESPONSE: Staff enrollment completed - Success: {response.get('success', False)}")
|
|
186
|
+
if not response.get('success', False):
|
|
187
|
+
self.logger.warning(f"Staff enrollment failed: {response.get('error', 'Unknown error')}")
|
|
188
188
|
return self._handle_response(response)
|
|
189
189
|
except Exception as e:
|
|
190
190
|
self.logger.error(f"API ERROR: Staff enrollment request failed - {e}", exc_info=True)
|
|
@@ -236,14 +236,14 @@ class FacialRecognitionClient:
|
|
|
236
236
|
)
|
|
237
237
|
|
|
238
238
|
results_count = 0
|
|
239
|
-
if response
|
|
239
|
+
if response.get('success', False):
|
|
240
240
|
data = response.get('data', [])
|
|
241
241
|
results_count = len(data) if isinstance(data, list) else 0
|
|
242
242
|
self.logger.info(f"API RESPONSE: Face search completed - Found {results_count} matches")
|
|
243
243
|
if results_count > 0:
|
|
244
244
|
self.logger.debug(f"Top match: staff_id={data[0].get('staffId', 'N/A')}, score={data[0].get('score', 0):.3f}")
|
|
245
245
|
else:
|
|
246
|
-
self.logger.warning(f"Face search failed: {response.get('error', 'Unknown error')
|
|
246
|
+
self.logger.warning(f"Face search failed: {response.get('error', 'Unknown error')}")
|
|
247
247
|
|
|
248
248
|
return self._handle_response(response)
|
|
249
249
|
except Exception as e:
|
|
@@ -267,10 +267,10 @@ class FacialRecognitionClient:
|
|
|
267
267
|
base_url=self.server_base_url
|
|
268
268
|
)
|
|
269
269
|
|
|
270
|
-
if response
|
|
270
|
+
if response.get('success', False):
|
|
271
271
|
self.logger.info(f"API RESPONSE: Staff details retrieved successfully - staff_id={staff_id}")
|
|
272
272
|
else:
|
|
273
|
-
self.logger.warning(f"Failed to get staff details for staff_id={staff_id}: {response.get('error', 'Unknown error')
|
|
273
|
+
self.logger.warning(f"Failed to get staff details for staff_id={staff_id}: {response.get('error', 'Unknown error')}")
|
|
274
274
|
|
|
275
275
|
return self._handle_response(response)
|
|
276
276
|
except Exception as e:
|
|
@@ -366,10 +366,10 @@ class FacialRecognitionClient:
|
|
|
366
366
|
base_url=self.server_base_url
|
|
367
367
|
)
|
|
368
368
|
|
|
369
|
-
if response
|
|
369
|
+
if response.get('success', False):
|
|
370
370
|
self.logger.info(f"API RESPONSE: Staff images updated successfully - employee_id={employee_id}")
|
|
371
371
|
else:
|
|
372
|
-
self.logger.warning(f"Failed to update staff images for employee_id={employee_id}: {response.get('error', 'Unknown error')
|
|
372
|
+
self.logger.warning(f"Failed to update staff images for employee_id={employee_id}: {response.get('error', 'Unknown error')}")
|
|
373
373
|
|
|
374
374
|
return self._handle_response(response)
|
|
375
375
|
except Exception as e:
|
|
@@ -417,10 +417,10 @@ class FacialRecognitionClient:
|
|
|
417
417
|
base_url=self.server_base_url
|
|
418
418
|
)
|
|
419
419
|
|
|
420
|
-
if response
|
|
420
|
+
if response.get('success', False):
|
|
421
421
|
self.logger.info(f"API RESPONSE: Service shutdown successful")
|
|
422
422
|
else:
|
|
423
|
-
self.logger.warning(f"Service shutdown failed: {response.get('error', 'Unknown error')
|
|
423
|
+
self.logger.warning(f"Service shutdown failed: {response.get('error', 'Unknown error')}")
|
|
424
424
|
|
|
425
425
|
return self._handle_response(response)
|
|
426
426
|
except Exception as e:
|
|
@@ -447,12 +447,12 @@ class FacialRecognitionClient:
|
|
|
447
447
|
)
|
|
448
448
|
|
|
449
449
|
embeddings_count = 0
|
|
450
|
-
if response
|
|
450
|
+
if response.get('success', False):
|
|
451
451
|
data = response.get('data', [])
|
|
452
452
|
embeddings_count = len(data) if isinstance(data, list) else 0
|
|
453
453
|
self.logger.info(f"API RESPONSE: Retrieved {embeddings_count} staff embeddings")
|
|
454
454
|
else:
|
|
455
|
-
self.logger.warning(f"Failed to get staff embeddings: {response.get('error', 'Unknown error')
|
|
455
|
+
self.logger.warning(f"Failed to get staff embeddings: {response.get('error', 'Unknown error')}")
|
|
456
456
|
|
|
457
457
|
return self._handle_response(response)
|
|
458
458
|
except Exception as e:
|
|
@@ -485,10 +485,10 @@ class FacialRecognitionClient:
|
|
|
485
485
|
base_url=self.server_base_url
|
|
486
486
|
)
|
|
487
487
|
|
|
488
|
-
if response
|
|
488
|
+
if response.get('success', False):
|
|
489
489
|
self.logger.info(f"API RESPONSE: Deployment updated successfully - deployment_id={deployment_id}")
|
|
490
490
|
else:
|
|
491
|
-
self.logger.warning(f"Failed to update deployment for deployment_id={deployment_id}: {response.get('error', 'Unknown error')
|
|
491
|
+
self.logger.warning(f"Failed to update deployment for deployment_id={deployment_id}: {response.get('error', 'Unknown error')}")
|
|
492
492
|
|
|
493
493
|
return self._handle_response(response)
|
|
494
494
|
except Exception as e:
|
|
@@ -527,10 +527,10 @@ class FacialRecognitionClient:
|
|
|
527
527
|
base_url=self.server_base_url
|
|
528
528
|
)
|
|
529
529
|
|
|
530
|
-
if response
|
|
530
|
+
if response.get('success', False):
|
|
531
531
|
self.logger.info(f"API RESPONSE: Unknown person enrolled successfully")
|
|
532
532
|
else:
|
|
533
|
-
self.logger.warning(f"Failed to enroll unknown person: {response.get('error', 'Unknown error')
|
|
533
|
+
self.logger.warning(f"Failed to enroll unknown person: {response.get('error', 'Unknown error')}")
|
|
534
534
|
|
|
535
535
|
return self._handle_response(response)
|
|
536
536
|
except Exception as e:
|
|
@@ -551,10 +551,10 @@ class FacialRecognitionClient:
|
|
|
551
551
|
base_url=self.server_base_url
|
|
552
552
|
)
|
|
553
553
|
|
|
554
|
-
if response
|
|
554
|
+
if response.get('success', False):
|
|
555
555
|
self.logger.info(f"API RESPONSE: Service is healthy")
|
|
556
556
|
else:
|
|
557
|
-
self.logger.warning(f"Health check failed: {response.get('error', 'Unknown error')
|
|
557
|
+
self.logger.warning(f"Health check failed: {response.get('error', 'Unknown error')}")
|
|
558
558
|
|
|
559
559
|
return self._handle_response(response)
|
|
560
560
|
except Exception as e:
|
|
@@ -564,11 +564,6 @@ class FacialRecognitionClient:
|
|
|
564
564
|
def _handle_response(self, response: Dict[str, Any]) -> Dict[str, Any]:
|
|
565
565
|
"""Handle RPC response and errors"""
|
|
566
566
|
try:
|
|
567
|
-
# Handle None response
|
|
568
|
-
if response is None:
|
|
569
|
-
self.logger.error("RPC Error: Received None response from API")
|
|
570
|
-
return {"success": False, "error": "No response received from API"}
|
|
571
|
-
|
|
572
567
|
if response.get("success", True):
|
|
573
568
|
return response
|
|
574
569
|
else:
|
|
@@ -592,4 +587,4 @@ def create_face_client(account_number: str = None, access_key: str = None,
|
|
|
592
587
|
project_id=project_id,
|
|
593
588
|
server_id=server_id,
|
|
594
589
|
session=session
|
|
595
|
-
)
|
|
590
|
+
)
|
|
@@ -84,20 +84,19 @@ class PeopleActivityLogging:
|
|
|
84
84
|
self.activity_queue.task_done()
|
|
85
85
|
except queue.Empty:
|
|
86
86
|
# Continue loop to check for empty detections
|
|
87
|
-
await asyncio.sleep(0.01)
|
|
88
87
|
continue
|
|
89
88
|
|
|
90
89
|
except Exception as e:
|
|
91
90
|
self.logger.error(f"Error processing activity queue: {e}", exc_info=True)
|
|
92
91
|
await asyncio.sleep(1.0)
|
|
93
92
|
|
|
94
|
-
def enqueue_detection(
|
|
93
|
+
async def enqueue_detection(
|
|
95
94
|
self,
|
|
96
95
|
detection: Dict,
|
|
97
96
|
current_frame: Optional[np.ndarray] = None,
|
|
98
97
|
location: str = "",
|
|
99
98
|
):
|
|
100
|
-
"""Enqueue a detection for background processing
|
|
99
|
+
"""Enqueue a detection for background processing"""
|
|
101
100
|
try:
|
|
102
101
|
activity_data = {
|
|
103
102
|
"detection_type": detection["recognition_status"], # known, unknown
|
|
@@ -136,9 +135,8 @@ class PeopleActivityLogging:
|
|
|
136
135
|
self.last_detection_time = time.time()
|
|
137
136
|
self.empty_detection_logged = False
|
|
138
137
|
|
|
139
|
-
# Use thread-safe
|
|
140
|
-
|
|
141
|
-
self.activity_queue.put_nowait(activity_data)
|
|
138
|
+
# Use thread-safe put (no await needed for queue.Queue)
|
|
139
|
+
self.activity_queue.put(activity_data)
|
|
142
140
|
except Exception as e:
|
|
143
141
|
self.logger.error(f"Error enqueueing detection: {e}", exc_info=True)
|
|
144
142
|
|
|
@@ -320,4 +318,4 @@ class PeopleActivityLogging:
|
|
|
320
318
|
try:
|
|
321
319
|
self.stop_background_processing()
|
|
322
320
|
except:
|
|
323
|
-
pass
|
|
321
|
+
pass
|
|
@@ -29,9 +29,9 @@ matrice_analytics/post_processing/core/config_utils.py,sha256=QuAS-_JKSoNOtfUWgr
|
|
|
29
29
|
matrice_analytics/post_processing/face_reg/__init__.py,sha256=yntaiGlW9vdjBpPZQXNuovALihJPzRlFyUE88l3MhBA,1364
|
|
30
30
|
matrice_analytics/post_processing/face_reg/compare_similarity.py,sha256=NlFc8b2a74k0PqSFAbuM_fUbA1BT3pr3VUgvSqRpJzQ,23396
|
|
31
31
|
matrice_analytics/post_processing/face_reg/embedding_manager.py,sha256=qbh0df3-YbE0qvFDQvjpCg-JrsCZRJ5capjQ2LPOj1k,35619
|
|
32
|
-
matrice_analytics/post_processing/face_reg/face_recognition.py,sha256=
|
|
33
|
-
matrice_analytics/post_processing/face_reg/face_recognition_client.py,sha256=
|
|
34
|
-
matrice_analytics/post_processing/face_reg/people_activity_logging.py,sha256=
|
|
32
|
+
matrice_analytics/post_processing/face_reg/face_recognition.py,sha256=dLopUldzBCsRw1Zu0jewi1xf-JeUbgFx7_3L5pZ8wAg,96510
|
|
33
|
+
matrice_analytics/post_processing/face_reg/face_recognition_client.py,sha256=VaMhjk_tk9zzcB4Vp_FCA_MtgtHtfpzhFJA2caNx9YU,27574
|
|
34
|
+
matrice_analytics/post_processing/face_reg/people_activity_logging.py,sha256=vZbIvkK1h3h58ROeF0_ygF3lqr19O2h5222bN8XyIis,13675
|
|
35
35
|
matrice_analytics/post_processing/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
36
|
matrice_analytics/post_processing/ocr/easyocr_extractor.py,sha256=RMrRoGb2gMcJEGouQn8U9cCgCLXPT7qRa8liI4LNxFM,11555
|
|
37
37
|
matrice_analytics/post_processing/ocr/postprocessing.py,sha256=RILArp8I9WRH7bALVZ9wPGc-aR7YMdqV1ndOOIcOnGQ,12309
|
|
@@ -189,8 +189,8 @@ matrice_analytics/post_processing/utils/format_utils.py,sha256=UTF7A5h9j0_S12xH9
|
|
|
189
189
|
matrice_analytics/post_processing/utils/geometry_utils.py,sha256=BWfdM6RsdJTTLR1GqkWfdwpjMEjTCJyuBxA4zVGKdfk,9623
|
|
190
190
|
matrice_analytics/post_processing/utils/smoothing_utils.py,sha256=78U-yucAcjUiZ0NIAc9NOUSIT0PWP1cqyIPA_Fdrjp0,14699
|
|
191
191
|
matrice_analytics/post_processing/utils/tracking_utils.py,sha256=rWxuotnJ3VLMHIBOud2KLcu4yZfDp7hVPWUtNAq_2xw,8288
|
|
192
|
-
matrice_analytics-0.1.
|
|
193
|
-
matrice_analytics-0.1.
|
|
194
|
-
matrice_analytics-0.1.
|
|
195
|
-
matrice_analytics-0.1.
|
|
196
|
-
matrice_analytics-0.1.
|
|
192
|
+
matrice_analytics-0.1.46.dist-info/licenses/LICENSE.txt,sha256=_uQUZpgO0mRYL5-fPoEvLSbNnLPv6OmbeEDCHXhK6Qc,1066
|
|
193
|
+
matrice_analytics-0.1.46.dist-info/METADATA,sha256=xzaR5W7et1MNAyYu-bK7bqBi_pLCs5GOfiLkBo_Olk4,14378
|
|
194
|
+
matrice_analytics-0.1.46.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
195
|
+
matrice_analytics-0.1.46.dist-info/top_level.txt,sha256=STAPEU-e-rWTerXaspdi76T_eVRSrEfFpURSP7_Dt8E,18
|
|
196
|
+
matrice_analytics-0.1.46.dist-info/RECORD,,
|
|
File without changes
|
{matrice_analytics-0.1.45.dist-info → matrice_analytics-0.1.46.dist-info}/licenses/LICENSE.txt
RENAMED
|
File without changes
|
|
File without changes
|