matrice-analytics 0.1.43__tar.gz → 0.1.45__tar.gz

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.

Files changed (201) hide show
  1. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/PKG-INFO +1 -1
  2. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/matrice_analytics.egg-info/PKG-INFO +1 -1
  3. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/matrice_analytics.egg-info/SOURCES.txt +1 -0
  4. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/config.py +1 -1
  5. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/face_reg/face_recognition.py +145 -99
  6. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/face_reg/face_recognition_client.py +24 -19
  7. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/face_reg/people_activity_logging.py +6 -4
  8. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/easyocr_extractor.py +3 -1
  9. matrice_analytics-0.1.45/src/matrice_analytics/post_processing/test_cases/test_usecases.py +165 -0
  10. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip.py +4 -3
  11. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/color_mapper.py +1 -1
  12. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color_detection.py +89 -54
  13. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/fire_detection.py +89 -55
  14. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/license_plate_monitoring.py +81 -46
  15. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/people_counting.py +29 -28
  16. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/vehicle_monitoring.py +89 -54
  17. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/LICENSE.txt +0 -0
  18. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/README.md +0 -0
  19. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/matrice_analytics.egg-info/dependency_links.txt +0 -0
  20. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/matrice_analytics.egg-info/not-zip-safe +0 -0
  21. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/matrice_analytics.egg-info/top_level.txt +0 -0
  22. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/pyproject.toml +0 -0
  23. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/setup.cfg +0 -0
  24. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/setup.py +0 -0
  25. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/__init__.py +0 -0
  26. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/README.md +0 -0
  27. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/__init__.py +0 -0
  28. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/boundary_drawing_internal.py +0 -0
  29. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/boundary_drawing_tool.py +0 -0
  30. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/boundary_tool_template.html +0 -0
  31. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/example_usage.py +0 -0
  32. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/usage/README.md +0 -0
  33. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/usage/boundary_drawer_launcher.py +0 -0
  34. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/boundary_drawing_internal/usage/simple_boundary_launcher.py +0 -0
  35. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/README.md +0 -0
  36. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/__init__.py +0 -0
  37. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/README.md +0 -0
  38. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/__init__.py +0 -0
  39. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/base.py +0 -0
  40. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/config.py +0 -0
  41. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/kalman_filter.py +0 -0
  42. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/matching.py +0 -0
  43. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/strack.py +0 -0
  44. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/advanced_tracker/tracker.py +0 -0
  45. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/core/__init__.py +0 -0
  46. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/core/base.py +0 -0
  47. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/core/config.py +0 -0
  48. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/core/config_utils.py +0 -0
  49. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/face_reg/__init__.py +0 -0
  50. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/face_reg/compare_similarity.py +0 -0
  51. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/face_reg/embedding_manager.py +0 -0
  52. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/__init__.py +0 -0
  53. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/__init__.py +0 -0
  54. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/__init__.py +0 -0
  55. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/cli.py +0 -0
  56. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/dataset_stats.py +0 -0
  57. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/export.py +0 -0
  58. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/train.py +0 -0
  59. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/utils.py +0 -0
  60. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/valid.py +0 -0
  61. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/validate_dataset.py +0 -0
  62. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_augmentation.py +0 -0
  63. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_predictions.py +0 -0
  64. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/__init__.py +0 -0
  65. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/process.py +0 -0
  66. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/types.py +0 -0
  67. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/utils.py +0 -0
  68. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/__init__.py +0 -0
  69. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/config.py +0 -0
  70. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/hub.py +0 -0
  71. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/plate_recognizer.py +0 -0
  72. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/py.typed +0 -0
  73. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/__init__.py +0 -0
  74. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/__init__.py +0 -0
  75. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/augmentation.py +0 -0
  76. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/dataset.py +0 -0
  77. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/__init__.py +0 -0
  78. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/config.py +0 -0
  79. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/layers.py +0 -0
  80. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/loss.py +0 -0
  81. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/metric.py +0 -0
  82. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_builders.py +0 -0
  83. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_schema.py +0 -0
  84. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/__init__.py +0 -0
  85. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/backend_utils.py +0 -0
  86. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/utils.py +0 -0
  87. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/postprocessing.py +0 -0
  88. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/ocr/preprocessing.py +0 -0
  89. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/post_processor.py +0 -0
  90. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/__init__.py +0 -0
  91. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/run_tests.py +0 -0
  92. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_advanced_customer_service.py +0 -0
  93. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_basic_counting_tracking.py +0 -0
  94. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_comprehensive.py +0 -0
  95. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_config.py +0 -0
  96. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_customer_service.py +0 -0
  97. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_data_generators.py +0 -0
  98. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_people_counting.py +0 -0
  99. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_processor.py +0 -0
  100. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_utilities.py +0 -0
  101. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/test_cases/test_utils.py +0 -0
  102. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/Histopathological_Cancer_Detection_img.py +0 -0
  103. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/__init__.py +0 -0
  104. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/abandoned_object_detection.py +0 -0
  105. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/advanced_customer_service.py +0 -0
  106. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/age_detection.py +0 -0
  107. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/age_gender_detection.py +0 -0
  108. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/anti_spoofing_detection.py +0 -0
  109. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/assembly_line_detection.py +0 -0
  110. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/banana_defect_detection.py +0 -0
  111. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/basic_counting_tracking.py +0 -0
  112. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/blood_cancer_detection_img.py +0 -0
  113. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/car_damage_detection.py +0 -0
  114. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/car_part_segmentation.py +0 -0
  115. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/car_service.py +0 -0
  116. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/cardiomegaly_classification.py +0 -0
  117. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/cell_microscopy_segmentation.py +0 -0
  118. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/chicken_pose_detection.py +0 -0
  119. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/child_monitoring.py +0 -0
  120. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip_processor/merges.txt +0 -0
  121. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip_processor/preprocessor_config.json +0 -0
  122. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip_processor/special_tokens_map.json +0 -0
  123. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer.json +0 -0
  124. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer_config.json +0 -0
  125. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/clip_processor/vocab.json +0 -0
  126. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color/color_map_utils.py +0 -0
  127. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/color_map_utils.py +0 -0
  128. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/concrete_crack_detection.py +0 -0
  129. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/crop_weed_detection.py +0 -0
  130. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/customer_service.py +0 -0
  131. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/defect_detection_products.py +0 -0
  132. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/distracted_driver_detection.py +0 -0
  133. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/drone_traffic_monitoring.py +0 -0
  134. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/drowsy_driver_detection.py +0 -0
  135. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/dwell_detection.py +0 -0
  136. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/emergency_vehicle_detection.py +0 -0
  137. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/face_emotion.py +0 -0
  138. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/face_recognition.py +0 -0
  139. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/fashion_detection.py +0 -0
  140. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/field_mapping.py +0 -0
  141. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/flare_analysis.py +0 -0
  142. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/flower_segmentation.py +0 -0
  143. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/gas_leak_detection.py +0 -0
  144. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/gender_detection.py +0 -0
  145. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/human_activity_recognition.py +0 -0
  146. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/intrusion_detection.py +0 -0
  147. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/leaf.py +0 -0
  148. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/leaf_disease.py +0 -0
  149. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/leak_detection.py +0 -0
  150. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/license_plate_detection.py +0 -0
  151. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/litter_monitoring.py +0 -0
  152. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/mask_detection.py +0 -0
  153. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/natural_disaster.py +0 -0
  154. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/parking.py +0 -0
  155. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/parking_space_detection.py +0 -0
  156. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/pcb_defect_detection.py +0 -0
  157. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/pedestrian_detection.py +0 -0
  158. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/people_counting_bckp.py +0 -0
  159. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/people_tracking.py +0 -0
  160. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/pipeline_detection.py +0 -0
  161. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/plaque_segmentation_img.py +0 -0
  162. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/pothole_segmentation.py +0 -0
  163. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/ppe_compliance.py +0 -0
  164. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/price_tag_detection.py +0 -0
  165. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/proximity_detection.py +0 -0
  166. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/road_lane_detection.py +0 -0
  167. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/road_traffic_density.py +0 -0
  168. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/road_view_segmentation.py +0 -0
  169. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/shelf_inventory_detection.py +0 -0
  170. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/shoplifting_detection.py +0 -0
  171. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/shopping_cart_analysis.py +0 -0
  172. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/skin_cancer_classification_img.py +0 -0
  173. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/smoker_detection.py +0 -0
  174. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/solar_panel.py +0 -0
  175. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/suspicious_activity_detection.py +0 -0
  176. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/template_usecase.py +0 -0
  177. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/theft_detection.py +0 -0
  178. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/traffic_sign_monitoring.py +0 -0
  179. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/underground_pipeline_defect_detection.py +0 -0
  180. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/underwater_pollution_detection.py +0 -0
  181. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/warehouse_object_segmentation.py +0 -0
  182. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/waterbody_segmentation.py +0 -0
  183. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/weapon_detection.py +0 -0
  184. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/weld_defect_detection.py +0 -0
  185. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/wildlife_monitoring.py +0 -0
  186. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/windmill_maintenance.py +0 -0
  187. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/usecases/wound_segmentation.py +0 -0
  188. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/__init__.py +0 -0
  189. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/advanced_counting_utils.py +0 -0
  190. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/advanced_helper_utils.py +0 -0
  191. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/advanced_tracking_utils.py +0 -0
  192. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/alerting_utils.py +0 -0
  193. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/category_mapping_utils.py +0 -0
  194. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/color_utils.py +0 -0
  195. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/counting_utils.py +0 -0
  196. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/filter_utils.py +0 -0
  197. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/format_utils.py +0 -0
  198. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/geometry_utils.py +0 -0
  199. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/smoothing_utils.py +0 -0
  200. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/post_processing/utils/tracking_utils.py +0 -0
  201. {matrice_analytics-0.1.43 → matrice_analytics-0.1.45}/src/matrice_analytics/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice_analytics
3
- Version: 0.1.43
3
+ Version: 0.1.45
4
4
  Summary: Common server utilities for Matrice.ai services
5
5
  Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice_analytics
3
- Version: 0.1.43
3
+ Version: 0.1.45
4
4
  Summary: Common server utilities for Matrice.ai services
5
5
  Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
6
  License-Expression: MIT
@@ -88,6 +88,7 @@ src/matrice_analytics/post_processing/test_cases/test_customer_service.py
88
88
  src/matrice_analytics/post_processing/test_cases/test_data_generators.py
89
89
  src/matrice_analytics/post_processing/test_cases/test_people_counting.py
90
90
  src/matrice_analytics/post_processing/test_cases/test_processor.py
91
+ src/matrice_analytics/post_processing/test_cases/test_usecases.py
91
92
  src/matrice_analytics/post_processing/test_cases/test_utilities.py
92
93
  src/matrice_analytics/post_processing/test_cases/test_utils.py
93
94
  src/matrice_analytics/post_processing/usecases/Histopathological_Cancer_Detection_img.py
@@ -143,4 +143,4 @@ def get_usecase_from_app_name(app_name: str) -> str:
143
143
 
144
144
  def get_category_from_app_name(app_name: str) -> str:
145
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))
146
+ return APP_NAME_TO_CATEGORY.get(app_name, APP_NAME_TO_CATEGORY.get(normalized_app_name))
@@ -24,7 +24,7 @@ subprocess.run(
24
24
  cmd,
25
25
  stdout=log_file,
26
26
  stderr=subprocess.STDOUT,
27
- preexec_fn=os.setpgrp
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
- 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.
84
+ Uses local embedding similarity search via EmbeddingManager instead of API calls.
86
85
  """
87
86
 
88
87
  def __init__(
89
88
  self,
90
89
  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,6 +96,7 @@ 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
99
100
  self.threshold = float(recognition_threshold)
100
101
  self.history_size = int(history_size)
101
102
  self.unknown_patience = int(unknown_patience)
@@ -119,69 +120,65 @@ class TemporalIdentityManager:
119
120
 
120
121
  async def _compute_best_identity(self, emb: List[float], location: str = "", timestamp: str = "") -> Tuple[Optional[str], str, float, Optional[str], Dict[str, Any], str]:
121
122
  """
122
- Query backend for top-1 match for the given embedding.
123
+ Query embedding manager for top-1 match using local similarity search.
123
124
  Returns (staff_id, person_name, score, employee_id, staff_details, detection_type).
124
- Robust to varying response shapes.
125
+
126
+ NOTE: API call to search_similar_faces is commented out - using local embeddings only.
125
127
  """
126
128
  if not emb or not isinstance(emb, list):
127
129
  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
128
148
  try:
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",
149
+ if not self.embedding_manager:
150
+ self.logger.warning("Embedding manager not available for local similarity search")
151
+ return None, "Unknown", 0.0, None, {}, "unknown"
152
+
153
+ # Perform local similarity search using embedding manager
154
+ search_result = await self.embedding_manager.search_face_embedding(
155
+ embedding=emb,
156
+ track_id=None, # No track_id needed for this search
134
157
  location=location,
135
158
  timestamp=timestamp,
136
159
  )
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")
160
+
161
+ if not search_result:
162
+ self.logger.debug("No identity match found from local embeddings")
156
163
  return None, "Unknown", 0.0, None, {}, "unknown"
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}")
164
+
165
+ # Extract data from SearchResult
166
+ staff_id = search_result.staff_id
167
+ person_name = search_result.person_name
168
+ score = search_result.similarity_score
169
+ employee_id = search_result.employee_id
170
+ staff_details = search_result.staff_details
171
+ detection_type = search_result.detection_type
172
+
173
+ if not staff_id or detection_type == "unknown":
174
+ self.logger.debug(f"Local search returned unknown or missing staff_id - score={score}, employee_id={employee_id}")
180
175
  return None, "Unknown", float(score), employee_id, staff_details if isinstance(staff_details, dict) else {}, "unknown"
181
- self.logger.info(f"API identified face - staff_id={staff_id}, person_name={person_name}, score={score:.3f}")
176
+
177
+ self.logger.info(f"Local embedding identified face - staff_id={staff_id}, person_name={person_name}, score={score:.3f}")
182
178
  return str(staff_id), person_name, float(score), employee_id, staff_details if isinstance(staff_details, dict) else {}, "known"
179
+
183
180
  except Exception as e:
184
- self.logger.error(f"Error parsing API response in _compute_best_identity: {e}", exc_info=True)
181
+ self.logger.error(f"Error in local embedding similarity search: {e}", exc_info=True)
185
182
  return None, "Unknown", 0.0, None, {}, "unknown"
186
183
 
187
184
  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]:
@@ -488,16 +485,17 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
488
485
  self.embedding_manager = EmbeddingManager(init_config.embedding_config, self.face_client)
489
486
  self.logger.info("Embedding manager initialized")
490
487
 
491
- # Initialize TemporalIdentityManager
488
+ # Initialize TemporalIdentityManager with embedding_manager for local search
492
489
  self.temporal_identity_manager = TemporalIdentityManager(
493
490
  face_client=self.face_client,
491
+ embedding_manager=self.embedding_manager, # Pass embedding manager for local similarity search
494
492
  recognition_threshold=float(init_config.similarity_threshold),
495
493
  history_size=20,
496
494
  unknown_patience=7,
497
495
  switch_patience=5,
498
496
  fallback_margin=0.05,
499
497
  )
500
- self.logger.info("Temporal identity manager initialized")
498
+ self.logger.info("Temporal identity manager initialized with local embedding search")
501
499
 
502
500
  self._initialized = True
503
501
  self.logger.info("Face recognition use case fully initialized")
@@ -909,16 +907,28 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
909
907
  # Generate current timestamp
910
908
  current_timestamp = datetime.now(timezone.utc).isoformat()
911
909
 
912
- final_detections = []
913
- # Process detections sequentially to preserve order
914
- for detection in detections:
915
-
916
- # Process each detection sequentially with await to preserve order
917
- processed_detection = await self._process_face(
910
+ # Process all detections in parallel for better performance
911
+ # Create tasks for parallel processing
912
+ tasks = [
913
+ self._process_face(
918
914
  detection, current_frame, location, current_timestamp, config,
919
915
  current_recognized_count, current_unknown_count,
920
916
  recognized_persons, current_frame_staff_details
921
917
  )
918
+ for detection in detections
919
+ ]
920
+
921
+ # Process all faces in parallel
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
+
922
932
  # Include both known and unknown faces in final detections (maintains original order)
923
933
  if processed_detection:
924
934
  final_detections.append(processed_detection)
@@ -1085,7 +1095,7 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1085
1095
  # If it later becomes recognized, we'll remove it from unknown set above
1086
1096
  self._unknown_track_ids.add(internal_tid)
1087
1097
 
1088
- # Enqueue detection for background logging with all required parameters
1098
+ # Enqueue detection for background logging with all required parameters (non-blocking)
1089
1099
  try:
1090
1100
  # Log known faces for activity tracking (skip any employee_id starting with "unknown_")
1091
1101
  if (
@@ -1096,7 +1106,8 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1096
1106
  and employee_id
1097
1107
  and not str(employee_id).startswith("unknown_")
1098
1108
  ):
1099
- await self.people_activity_logging.enqueue_detection(
1109
+ # Non-blocking enqueue - no await needed
1110
+ self.people_activity_logging.enqueue_detection(
1100
1111
  detection=detection,
1101
1112
  current_frame=current_frame,
1102
1113
  location=location,
@@ -1743,56 +1754,57 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1743
1754
  return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
1744
1755
 
1745
1756
  def _format_timestamp(self, timestamp: Any) -> str:
1746
- """Format a timestamp so that exactly two digits follow the decimal point (milliseconds).
1757
+ """Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
1747
1758
 
1748
1759
  The input can be either:
1749
- 1. A numeric Unix timestamp (``float`` / ``int``) – it will first be converted to a
1750
- string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
1751
- 2. A string already following the same layout.
1760
+ 1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
1761
+ 2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
1752
1762
 
1753
- The returned value preserves the overall format of the input but truncates or pads
1754
- the fractional seconds portion to **exactly two digits**.
1763
+ The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
1755
1764
 
1756
1765
  Example
1757
1766
  -------
1758
- >>> self._format_timestamp("2025-08-19-04:22:47.187574 UTC")
1759
- '2025-08-19-04:22:47.18 UTC'
1767
+ >>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
1768
+ '2025:10:27 19:31:20'
1760
1769
  """
1761
1770
 
1762
- # Convert numeric timestamps to the expected string representation first
1771
+ # Convert numeric timestamps to datetime first
1763
1772
  if isinstance(timestamp, (int, float)):
1764
- timestamp = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
1765
- '%Y-%m-%d-%H:%M:%S.%f UTC'
1766
- )
1773
+ dt = datetime.fromtimestamp(timestamp, timezone.utc)
1774
+ return dt.strftime('%Y:%m:%d %H:%M:%S')
1767
1775
 
1768
1776
  # Ensure we are working with a string from here on
1769
1777
  if not isinstance(timestamp, str):
1770
1778
  return str(timestamp)
1771
1779
 
1772
- # If there is no fractional component, simply return the original string
1773
- if '.' not in timestamp:
1774
- return timestamp
1780
+ # Remove ' UTC' suffix if present
1781
+ timestamp_clean = timestamp.replace(' UTC', '').strip()
1775
1782
 
1776
- # Split out the main portion (up to the decimal point)
1777
- main_part, fractional_and_suffix = timestamp.split('.', 1)
1783
+ # Remove milliseconds if present (everything after the last dot)
1784
+ if '.' in timestamp_clean:
1785
+ timestamp_clean = timestamp_clean.split('.')[0]
1778
1786
 
1779
- # Separate fractional digits from the suffix (typically ' UTC')
1780
- if ' ' in fractional_and_suffix:
1781
- fractional_part, suffix = fractional_and_suffix.split(' ', 1)
1782
- suffix = ' ' + suffix # Re-attach the space removed by split
1783
- else:
1784
- fractional_part, suffix = fractional_and_suffix, ''
1785
-
1786
- # Guarantee exactly two digits for the fractional part
1787
- fractional_part = (fractional_part + '00')[:2]
1787
+ # Parse the timestamp string and convert to desired format
1788
+ try:
1789
+ # Handle format: YYYY-MM-DD-HH:MM:SS
1790
+ if timestamp_clean.count('-') >= 2:
1791
+ # Replace first two dashes with colons for date part, third with space
1792
+ parts = timestamp_clean.split('-')
1793
+ if len(parts) >= 4:
1794
+ # parts = ['2025', '10', '27', '19:31:20']
1795
+ formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
1796
+ return formatted
1797
+ except Exception:
1798
+ pass
1788
1799
 
1789
- return f"{main_part}.{fractional_part}{suffix}"
1800
+ # If parsing fails, return the cleaned string as-is
1801
+ return timestamp_clean
1790
1802
 
1791
1803
  def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
1792
1804
  """Get formatted current timestamp based on stream type."""
1805
+
1793
1806
  if not stream_info:
1794
1807
  return "00:00:00.00"
1795
-
1796
1808
  if precision:
1797
1809
  if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
1798
1810
  if frame_id:
@@ -1801,7 +1813,6 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1801
1813
  start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
1802
1814
  stream_time_str = self._format_timestamp_for_video(start_time)
1803
1815
 
1804
-
1805
1816
  return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
1806
1817
  else:
1807
1818
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
@@ -1813,7 +1824,8 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1813
1824
  start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
1814
1825
 
1815
1826
  stream_time_str = self._format_timestamp_for_video(start_time)
1816
-
1827
+
1828
+
1817
1829
  return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
1818
1830
  else:
1819
1831
  stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
@@ -1835,23 +1847,57 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1835
1847
 
1836
1848
  if precision:
1837
1849
  if self.start_timer is None:
1838
- self.start_timer = stream_info.get("input_settings", {}).get("stream_time", "NA")
1850
+ candidate = stream_info.get("input_settings", {}).get("stream_time")
1851
+ if not candidate or candidate == "NA":
1852
+ candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1853
+ self.start_timer = candidate
1839
1854
  return self._format_timestamp(self.start_timer)
1840
1855
  elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
1841
- self.start_timer = stream_info.get("input_settings", {}).get("stream_time", "NA")
1856
+ candidate = stream_info.get("input_settings", {}).get("stream_time")
1857
+ if not candidate or candidate == "NA":
1858
+ candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1859
+ self.start_timer = candidate
1842
1860
  return self._format_timestamp(self.start_timer)
1843
1861
  else:
1844
1862
  return self._format_timestamp(self.start_timer)
1845
1863
 
1846
1864
  if self.start_timer is None:
1847
- self.start_timer = stream_info.get("input_settings", {}).get("stream_time", "NA")
1865
+ # Prefer direct input_settings.stream_time if available and not NA
1866
+ candidate = stream_info.get("input_settings", {}).get("stream_time")
1867
+ if not candidate or candidate == "NA":
1868
+ # Fallback to nested stream_info.stream_time used by current timestamp path
1869
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
1870
+ if stream_time_str:
1871
+ try:
1872
+ timestamp_str = stream_time_str.replace(" UTC", "")
1873
+ dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
1874
+ self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
1875
+ candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1876
+ except:
1877
+ candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1878
+ else:
1879
+ candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1880
+ self.start_timer = candidate
1848
1881
  return self._format_timestamp(self.start_timer)
1849
1882
  elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
1850
- self.start_timer = stream_info.get("input_settings", {}).get("stream_time", "NA")
1883
+ candidate = stream_info.get("input_settings", {}).get("stream_time")
1884
+ if not candidate or candidate == "NA":
1885
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
1886
+ if stream_time_str:
1887
+ try:
1888
+ timestamp_str = stream_time_str.replace(" UTC", "")
1889
+ dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
1890
+ ts = dt.replace(tzinfo=timezone.utc).timestamp()
1891
+ candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1892
+ except:
1893
+ candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1894
+ else:
1895
+ candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
1896
+ self.start_timer = candidate
1851
1897
  return self._format_timestamp(self.start_timer)
1852
1898
 
1853
1899
  else:
1854
- if self.start_timer is not None:
1900
+ if self.start_timer is not None and self.start_timer != "NA":
1855
1901
  return self._format_timestamp(self.start_timer)
1856
1902
 
1857
1903
  if self._tracking_start_time is None:
@@ -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.get('success', False):
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) if response else False}")
186
+ if not response or not response.get('success', False):
187
+ self.logger.warning(f"Staff enrollment failed: {response.get('error', 'Unknown error') if response else 'No response'}")
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.get('success', False):
239
+ if response and 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') if response else 'No response'}")
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.get('success', False):
270
+ if response and 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') if response else 'No response'}")
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.get('success', False):
369
+ if response and 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') if response else 'No response'}")
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.get('success', False):
420
+ if response and 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') if response else 'No response'}")
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.get('success', False):
450
+ if response and 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') if response else 'No response'}")
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.get('success', False):
488
+ if response and 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') if response else 'No response'}")
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.get('success', False):
530
+ if response and 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') if response else 'No response'}")
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.get('success', False):
554
+ if response and 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') if response else 'No response'}")
558
558
 
559
559
  return self._handle_response(response)
560
560
  except Exception as e:
@@ -564,6 +564,11 @@ 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
+
567
572
  if response.get("success", True):
568
573
  return response
569
574
  else:
@@ -84,19 +84,20 @@ 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)
87
88
  continue
88
89
 
89
90
  except Exception as e:
90
91
  self.logger.error(f"Error processing activity queue: {e}", exc_info=True)
91
92
  await asyncio.sleep(1.0)
92
93
 
93
- async def enqueue_detection(
94
+ def enqueue_detection(
94
95
  self,
95
96
  detection: Dict,
96
97
  current_frame: Optional[np.ndarray] = None,
97
98
  location: str = "",
98
99
  ):
99
- """Enqueue a detection for background processing"""
100
+ """Enqueue a detection for background processing (non-blocking)"""
100
101
  try:
101
102
  activity_data = {
102
103
  "detection_type": detection["recognition_status"], # known, unknown
@@ -135,8 +136,9 @@ class PeopleActivityLogging:
135
136
  self.last_detection_time = time.time()
136
137
  self.empty_detection_logged = False
137
138
 
138
- # Use thread-safe put (no await needed for queue.Queue)
139
- self.activity_queue.put(activity_data)
139
+ # Use thread-safe put_nowait to avoid any potential blocking
140
+ # queue.Queue.put() is already non-blocking with no timeout, but being explicit
141
+ self.activity_queue.put_nowait(activity_data)
140
142
  except Exception as e:
141
143
  self.logger.error(f"Error enqueueing detection: {e}", exc_info=True)
142
144
 
@@ -1,6 +1,7 @@
1
1
  import easyocr
2
2
  import numpy as np
3
3
  import torch
4
+ from matrice_common.utils import log_errors
4
5
 
5
6
  class EasyOCRExtractor:
6
7
  def __init__(self, lang=['en', 'hi', 'ar'], gpu=False, model_storage_directory=None,
@@ -30,7 +31,8 @@ class EasyOCRExtractor:
30
31
  self.recognizer = recognizer
31
32
  self.verbose = verbose
32
33
  self.reader = None
33
-
34
+
35
+ @log_errors(default_return=None, raise_exception=True, service_name="py_analytics", log_error=True)
34
36
  def setup(self):
35
37
  """
36
38
  Initializes the EasyOCR reader if not already initialized.