matrice-analytics 0.1.43__tar.gz → 0.1.44__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.
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/PKG-INFO +1 -1
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/matrice_analytics.egg-info/PKG-INFO +1 -1
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/face_reg/face_recognition.py +70 -35
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color_detection.py +89 -54
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/fire_detection.py +89 -54
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/license_plate_monitoring.py +81 -46
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/people_counting.py +29 -28
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/vehicle_monitoring.py +89 -54
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/LICENSE.txt +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/README.md +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/matrice_analytics.egg-info/SOURCES.txt +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/matrice_analytics.egg-info/dependency_links.txt +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/matrice_analytics.egg-info/not-zip-safe +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/matrice_analytics.egg-info/top_level.txt +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/pyproject.toml +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/setup.cfg +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/setup.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/README.md +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/boundary_drawing_internal.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/boundary_drawing_tool.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/boundary_tool_template.html +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/example_usage.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/usage/README.md +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/usage/boundary_drawer_launcher.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/boundary_drawing_internal/usage/simple_boundary_launcher.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/README.md +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/README.md +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/base.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/config.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/kalman_filter.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/matching.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/strack.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/advanced_tracker/tracker.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/config.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/core/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/core/base.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/core/config.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/core/config_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/face_reg/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/face_reg/compare_similarity.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/face_reg/embedding_manager.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/face_reg/face_recognition_client.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/face_reg/people_activity_logging.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/easyocr_extractor.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/cli.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/dataset_stats.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/export.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/train.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/valid.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/validate_dataset.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_augmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_predictions.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/process.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/types.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/config.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/hub.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/plate_recognizer.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/py.typed +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/augmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/dataset.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/config.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/layers.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/loss.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/metric.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_builders.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_schema.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/backend_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/postprocessing.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/ocr/preprocessing.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/post_processor.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/run_tests.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_advanced_customer_service.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_basic_counting_tracking.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_comprehensive.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_config.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_customer_service.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_data_generators.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_people_counting.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_processor.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_utilities.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/test_cases/test_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/Histopathological_Cancer_Detection_img.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/abandoned_object_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/advanced_customer_service.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/age_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/age_gender_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/anti_spoofing_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/assembly_line_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/banana_defect_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/basic_counting_tracking.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/blood_cancer_detection_img.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/car_damage_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/car_part_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/car_service.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/cardiomegaly_classification.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/cell_microscopy_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/chicken_pose_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/child_monitoring.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip_processor/merges.txt +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip_processor/preprocessor_config.json +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip_processor/special_tokens_map.json +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer.json +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer_config.json +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/clip_processor/vocab.json +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/color_map_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color/color_mapper.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/color_map_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/concrete_crack_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/crop_weed_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/customer_service.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/defect_detection_products.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/distracted_driver_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/drone_traffic_monitoring.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/drowsy_driver_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/dwell_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/emergency_vehicle_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/face_emotion.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/face_recognition.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/fashion_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/field_mapping.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/flare_analysis.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/flower_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/gas_leak_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/gender_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/human_activity_recognition.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/intrusion_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/leaf.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/leaf_disease.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/leak_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/license_plate_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/litter_monitoring.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/mask_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/natural_disaster.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/parking.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/parking_space_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/pcb_defect_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/pedestrian_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/people_counting_bckp.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/people_tracking.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/pipeline_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/plaque_segmentation_img.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/pothole_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/ppe_compliance.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/price_tag_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/proximity_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/road_lane_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/road_traffic_density.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/road_view_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/shelf_inventory_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/shoplifting_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/shopping_cart_analysis.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/skin_cancer_classification_img.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/smoker_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/solar_panel.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/suspicious_activity_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/template_usecase.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/theft_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/traffic_sign_monitoring.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/underground_pipeline_defect_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/underwater_pollution_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/warehouse_object_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/waterbody_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/weapon_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/weld_defect_detection.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/wildlife_monitoring.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/windmill_maintenance.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/usecases/wound_segmentation.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/__init__.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/advanced_counting_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/advanced_helper_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/advanced_tracking_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/alerting_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/category_mapping_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/color_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/counting_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/filter_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/format_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/geometry_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/smoothing_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/post_processing/utils/tracking_utils.py +0 -0
- {matrice_analytics-0.1.43 → matrice_analytics-0.1.44}/src/matrice_analytics/py.typed +0 -0
|
@@ -1743,56 +1743,57 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1743
1743
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
1744
1744
|
|
|
1745
1745
|
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1746
|
-
"""Format a timestamp
|
|
1746
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
1747
1747
|
|
|
1748
1748
|
The input can be either:
|
|
1749
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will
|
|
1750
|
-
|
|
1751
|
-
2. A string already following the same layout.
|
|
1749
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
1750
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1752
1751
|
|
|
1753
|
-
The returned value
|
|
1754
|
-
the fractional seconds portion to **exactly two digits**.
|
|
1752
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
1755
1753
|
|
|
1756
1754
|
Example
|
|
1757
1755
|
-------
|
|
1758
|
-
>>> self._format_timestamp("2025-
|
|
1759
|
-
'2025
|
|
1756
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
1757
|
+
'2025:10:27 19:31:20'
|
|
1760
1758
|
"""
|
|
1761
1759
|
|
|
1762
|
-
# Convert numeric timestamps to
|
|
1760
|
+
# Convert numeric timestamps to datetime first
|
|
1763
1761
|
if isinstance(timestamp, (int, float)):
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
)
|
|
1762
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
1763
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1767
1764
|
|
|
1768
1765
|
# Ensure we are working with a string from here on
|
|
1769
1766
|
if not isinstance(timestamp, str):
|
|
1770
1767
|
return str(timestamp)
|
|
1771
1768
|
|
|
1772
|
-
#
|
|
1773
|
-
|
|
1774
|
-
return timestamp
|
|
1769
|
+
# Remove ' UTC' suffix if present
|
|
1770
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
1775
1771
|
|
|
1776
|
-
#
|
|
1777
|
-
|
|
1778
|
-
|
|
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, ''
|
|
1772
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
1773
|
+
if '.' in timestamp_clean:
|
|
1774
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
1785
1775
|
|
|
1786
|
-
#
|
|
1787
|
-
|
|
1776
|
+
# Parse the timestamp string and convert to desired format
|
|
1777
|
+
try:
|
|
1778
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
1779
|
+
if timestamp_clean.count('-') >= 2:
|
|
1780
|
+
# Replace first two dashes with colons for date part, third with space
|
|
1781
|
+
parts = timestamp_clean.split('-')
|
|
1782
|
+
if len(parts) >= 4:
|
|
1783
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
1784
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
1785
|
+
return formatted
|
|
1786
|
+
except Exception:
|
|
1787
|
+
pass
|
|
1788
1788
|
|
|
1789
|
-
return
|
|
1789
|
+
# If parsing fails, return the cleaned string as-is
|
|
1790
|
+
return timestamp_clean
|
|
1790
1791
|
|
|
1791
1792
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
1792
1793
|
"""Get formatted current timestamp based on stream type."""
|
|
1794
|
+
|
|
1793
1795
|
if not stream_info:
|
|
1794
1796
|
return "00:00:00.00"
|
|
1795
|
-
|
|
1796
1797
|
if precision:
|
|
1797
1798
|
if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
|
|
1798
1799
|
if frame_id:
|
|
@@ -1801,7 +1802,6 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1801
1802
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1802
1803
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1803
1804
|
|
|
1804
|
-
|
|
1805
1805
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1806
1806
|
else:
|
|
1807
1807
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -1813,7 +1813,8 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1813
1813
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1814
1814
|
|
|
1815
1815
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1816
|
-
|
|
1816
|
+
|
|
1817
|
+
|
|
1817
1818
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1818
1819
|
else:
|
|
1819
1820
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -1835,23 +1836,57 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1835
1836
|
|
|
1836
1837
|
if precision:
|
|
1837
1838
|
if self.start_timer is None:
|
|
1838
|
-
|
|
1839
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1840
|
+
if not candidate or candidate == "NA":
|
|
1841
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1842
|
+
self.start_timer = candidate
|
|
1839
1843
|
return self._format_timestamp(self.start_timer)
|
|
1840
1844
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1841
|
-
|
|
1845
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1846
|
+
if not candidate or candidate == "NA":
|
|
1847
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1848
|
+
self.start_timer = candidate
|
|
1842
1849
|
return self._format_timestamp(self.start_timer)
|
|
1843
1850
|
else:
|
|
1844
1851
|
return self._format_timestamp(self.start_timer)
|
|
1845
1852
|
|
|
1846
1853
|
if self.start_timer is None:
|
|
1847
|
-
|
|
1854
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1855
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1856
|
+
if not candidate or candidate == "NA":
|
|
1857
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1858
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1859
|
+
if stream_time_str:
|
|
1860
|
+
try:
|
|
1861
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1862
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1863
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1864
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1865
|
+
except:
|
|
1866
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1867
|
+
else:
|
|
1868
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1869
|
+
self.start_timer = candidate
|
|
1848
1870
|
return self._format_timestamp(self.start_timer)
|
|
1849
1871
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1850
|
-
|
|
1872
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1873
|
+
if not candidate or candidate == "NA":
|
|
1874
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1875
|
+
if stream_time_str:
|
|
1876
|
+
try:
|
|
1877
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1878
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1879
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1880
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1881
|
+
except:
|
|
1882
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1883
|
+
else:
|
|
1884
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1885
|
+
self.start_timer = candidate
|
|
1851
1886
|
return self._format_timestamp(self.start_timer)
|
|
1852
1887
|
|
|
1853
1888
|
else:
|
|
1854
|
-
if self.start_timer is not None:
|
|
1889
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
1855
1890
|
return self._format_timestamp(self.start_timer)
|
|
1856
1891
|
|
|
1857
1892
|
if self._tracking_start_time is None:
|
|
@@ -1617,6 +1617,53 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1617
1617
|
seconds = round(float(timestamp % 60),2)
|
|
1618
1618
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
1619
1619
|
|
|
1620
|
+
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1621
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
1622
|
+
|
|
1623
|
+
The input can be either:
|
|
1624
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
1625
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1626
|
+
|
|
1627
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
1628
|
+
|
|
1629
|
+
Example
|
|
1630
|
+
-------
|
|
1631
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
1632
|
+
'2025:10:27 19:31:20'
|
|
1633
|
+
"""
|
|
1634
|
+
|
|
1635
|
+
# Convert numeric timestamps to datetime first
|
|
1636
|
+
if isinstance(timestamp, (int, float)):
|
|
1637
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
1638
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1639
|
+
|
|
1640
|
+
# Ensure we are working with a string from here on
|
|
1641
|
+
if not isinstance(timestamp, str):
|
|
1642
|
+
return str(timestamp)
|
|
1643
|
+
|
|
1644
|
+
# Remove ' UTC' suffix if present
|
|
1645
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
1646
|
+
|
|
1647
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
1648
|
+
if '.' in timestamp_clean:
|
|
1649
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
1650
|
+
|
|
1651
|
+
# Parse the timestamp string and convert to desired format
|
|
1652
|
+
try:
|
|
1653
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
1654
|
+
if timestamp_clean.count('-') >= 2:
|
|
1655
|
+
# Replace first two dashes with colons for date part, third with space
|
|
1656
|
+
parts = timestamp_clean.split('-')
|
|
1657
|
+
if len(parts) >= 4:
|
|
1658
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
1659
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
1660
|
+
return formatted
|
|
1661
|
+
except Exception:
|
|
1662
|
+
pass
|
|
1663
|
+
|
|
1664
|
+
# If parsing fails, return the cleaned string as-is
|
|
1665
|
+
return timestamp_clean
|
|
1666
|
+
|
|
1620
1667
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
1621
1668
|
"""Get formatted current timestamp based on stream type."""
|
|
1622
1669
|
|
|
@@ -1630,7 +1677,6 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1630
1677
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1631
1678
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1632
1679
|
|
|
1633
|
-
|
|
1634
1680
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1635
1681
|
else:
|
|
1636
1682
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -1642,7 +1688,8 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1642
1688
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1643
1689
|
|
|
1644
1690
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1645
|
-
|
|
1691
|
+
|
|
1692
|
+
|
|
1646
1693
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1647
1694
|
else:
|
|
1648
1695
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -1661,26 +1708,60 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1661
1708
|
"""Get formatted start timestamp for 'TOTAL SINCE' based on stream type."""
|
|
1662
1709
|
if not stream_info:
|
|
1663
1710
|
return "00:00:00"
|
|
1664
|
-
|
|
1711
|
+
|
|
1665
1712
|
if precision:
|
|
1666
1713
|
if self.start_timer is None:
|
|
1667
|
-
|
|
1714
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1715
|
+
if not candidate or candidate == "NA":
|
|
1716
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1717
|
+
self.start_timer = candidate
|
|
1668
1718
|
return self._format_timestamp(self.start_timer)
|
|
1669
1719
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1670
|
-
|
|
1720
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1721
|
+
if not candidate or candidate == "NA":
|
|
1722
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1723
|
+
self.start_timer = candidate
|
|
1671
1724
|
return self._format_timestamp(self.start_timer)
|
|
1672
1725
|
else:
|
|
1673
1726
|
return self._format_timestamp(self.start_timer)
|
|
1674
1727
|
|
|
1675
1728
|
if self.start_timer is None:
|
|
1676
|
-
|
|
1729
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1730
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1731
|
+
if not candidate or candidate == "NA":
|
|
1732
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1733
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1734
|
+
if stream_time_str:
|
|
1735
|
+
try:
|
|
1736
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1737
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1738
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1739
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1740
|
+
except:
|
|
1741
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1742
|
+
else:
|
|
1743
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1744
|
+
self.start_timer = candidate
|
|
1677
1745
|
return self._format_timestamp(self.start_timer)
|
|
1678
1746
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1679
|
-
|
|
1747
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1748
|
+
if not candidate or candidate == "NA":
|
|
1749
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1750
|
+
if stream_time_str:
|
|
1751
|
+
try:
|
|
1752
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1753
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1754
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1755
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1756
|
+
except:
|
|
1757
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1758
|
+
else:
|
|
1759
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1760
|
+
self.start_timer = candidate
|
|
1680
1761
|
return self._format_timestamp(self.start_timer)
|
|
1681
1762
|
|
|
1682
1763
|
else:
|
|
1683
|
-
if self.start_timer is not None:
|
|
1764
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
1684
1765
|
return self._format_timestamp(self.start_timer)
|
|
1685
1766
|
|
|
1686
1767
|
if self._tracking_start_time is None:
|
|
@@ -1699,52 +1780,6 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1699
1780
|
dt = dt.replace(minute=0, second=0, microsecond=0)
|
|
1700
1781
|
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1701
1782
|
|
|
1702
|
-
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1703
|
-
"""Format a timestamp so that exactly two digits follow the decimal point (milliseconds).
|
|
1704
|
-
|
|
1705
|
-
The input can be either:
|
|
1706
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will first be converted to a
|
|
1707
|
-
string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1708
|
-
2. A string already following the same layout.
|
|
1709
|
-
|
|
1710
|
-
The returned value preserves the overall format of the input but truncates or pads
|
|
1711
|
-
the fractional seconds portion to **exactly two digits**.
|
|
1712
|
-
|
|
1713
|
-
Example
|
|
1714
|
-
-------
|
|
1715
|
-
>>> self._format_timestamp("2025-08-19-04:22:47.187574 UTC")
|
|
1716
|
-
'2025-08-19-04:22:47.18 UTC'
|
|
1717
|
-
"""
|
|
1718
|
-
|
|
1719
|
-
# Convert numeric timestamps to the expected string representation first
|
|
1720
|
-
if isinstance(timestamp, (int, float)):
|
|
1721
|
-
timestamp = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
|
|
1722
|
-
'%Y-%m-%d-%H:%M:%S.%f UTC'
|
|
1723
|
-
)
|
|
1724
|
-
|
|
1725
|
-
# Ensure we are working with a string from here on
|
|
1726
|
-
if not isinstance(timestamp, str):
|
|
1727
|
-
return str(timestamp)
|
|
1728
|
-
|
|
1729
|
-
# If there is no fractional component, simply return the original string
|
|
1730
|
-
if '.' not in timestamp:
|
|
1731
|
-
return timestamp
|
|
1732
|
-
|
|
1733
|
-
# Split out the main portion (up to the decimal point)
|
|
1734
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
1735
|
-
|
|
1736
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
1737
|
-
if ' ' in fractional_and_suffix:
|
|
1738
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
1739
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
1740
|
-
else:
|
|
1741
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
1742
|
-
|
|
1743
|
-
# Guarantee exactly two digits for the fractional part
|
|
1744
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
1745
|
-
|
|
1746
|
-
return f"{main_part}.{fractional_part}{suffix}"
|
|
1747
|
-
|
|
1748
1783
|
def _get_tracking_start_time(self) -> str:
|
|
1749
1784
|
"""Get the tracking start time, formatted as a string."""
|
|
1750
1785
|
if self._tracking_start_time is None:
|
|
@@ -892,11 +892,58 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
892
892
|
seconds = round(float(timestamp % 60), 2)
|
|
893
893
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
894
894
|
|
|
895
|
+
def _format_timestamp(self, timestamp: Any) -> str:
|
|
896
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
897
|
+
|
|
898
|
+
The input can be either:
|
|
899
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
900
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
901
|
+
|
|
902
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
903
|
+
|
|
904
|
+
Example
|
|
905
|
+
-------
|
|
906
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
907
|
+
'2025:10:27 19:31:20'
|
|
908
|
+
"""
|
|
909
|
+
|
|
910
|
+
# Convert numeric timestamps to datetime first
|
|
911
|
+
if isinstance(timestamp, (int, float)):
|
|
912
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
913
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
914
|
+
|
|
915
|
+
# Ensure we are working with a string from here on
|
|
916
|
+
if not isinstance(timestamp, str):
|
|
917
|
+
return str(timestamp)
|
|
918
|
+
|
|
919
|
+
# Remove ' UTC' suffix if present
|
|
920
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
921
|
+
|
|
922
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
923
|
+
if '.' in timestamp_clean:
|
|
924
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
925
|
+
|
|
926
|
+
# Parse the timestamp string and convert to desired format
|
|
927
|
+
try:
|
|
928
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
929
|
+
if timestamp_clean.count('-') >= 2:
|
|
930
|
+
# Replace first two dashes with colons for date part, third with space
|
|
931
|
+
parts = timestamp_clean.split('-')
|
|
932
|
+
if len(parts) >= 4:
|
|
933
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
934
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
935
|
+
return formatted
|
|
936
|
+
except Exception:
|
|
937
|
+
pass
|
|
938
|
+
|
|
939
|
+
# If parsing fails, return the cleaned string as-is
|
|
940
|
+
return timestamp_clean
|
|
941
|
+
|
|
895
942
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
896
943
|
"""Get formatted current timestamp based on stream type."""
|
|
944
|
+
|
|
897
945
|
if not stream_info:
|
|
898
946
|
return "00:00:00.00"
|
|
899
|
-
|
|
900
947
|
if precision:
|
|
901
948
|
if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
|
|
902
949
|
if frame_id:
|
|
@@ -905,7 +952,6 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
905
952
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
906
953
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
907
954
|
|
|
908
|
-
|
|
909
955
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
910
956
|
else:
|
|
911
957
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -917,7 +963,8 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
917
963
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
918
964
|
|
|
919
965
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
920
|
-
|
|
966
|
+
|
|
967
|
+
|
|
921
968
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
922
969
|
else:
|
|
923
970
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -939,23 +986,57 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
939
986
|
|
|
940
987
|
if precision:
|
|
941
988
|
if self.start_timer is None:
|
|
942
|
-
|
|
989
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
990
|
+
if not candidate or candidate == "NA":
|
|
991
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
992
|
+
self.start_timer = candidate
|
|
943
993
|
return self._format_timestamp(self.start_timer)
|
|
944
994
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
945
|
-
|
|
995
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
996
|
+
if not candidate or candidate == "NA":
|
|
997
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
998
|
+
self.start_timer = candidate
|
|
946
999
|
return self._format_timestamp(self.start_timer)
|
|
947
1000
|
else:
|
|
948
1001
|
return self._format_timestamp(self.start_timer)
|
|
949
1002
|
|
|
950
1003
|
if self.start_timer is None:
|
|
951
|
-
|
|
1004
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1005
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1006
|
+
if not candidate or candidate == "NA":
|
|
1007
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1008
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1009
|
+
if stream_time_str:
|
|
1010
|
+
try:
|
|
1011
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1012
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1013
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1014
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1015
|
+
except:
|
|
1016
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1017
|
+
else:
|
|
1018
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1019
|
+
self.start_timer = candidate
|
|
952
1020
|
return self._format_timestamp(self.start_timer)
|
|
953
1021
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
954
|
-
|
|
1022
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1023
|
+
if not candidate or candidate == "NA":
|
|
1024
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1025
|
+
if stream_time_str:
|
|
1026
|
+
try:
|
|
1027
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1028
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1029
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1030
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1031
|
+
except:
|
|
1032
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1033
|
+
else:
|
|
1034
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1035
|
+
self.start_timer = candidate
|
|
955
1036
|
return self._format_timestamp(self.start_timer)
|
|
956
1037
|
|
|
957
1038
|
else:
|
|
958
|
-
if self.start_timer is not None:
|
|
1039
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
959
1040
|
return self._format_timestamp(self.start_timer)
|
|
960
1041
|
|
|
961
1042
|
if self._tracking_start_time is None:
|
|
@@ -974,52 +1055,6 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
974
1055
|
dt = dt.replace(minute=0, second=0, microsecond=0)
|
|
975
1056
|
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
976
1057
|
|
|
977
|
-
def _format_timestamp(self, timestamp: Any) -> str:
|
|
978
|
-
"""Format a timestamp so that exactly two digits follow the decimal point (milliseconds).
|
|
979
|
-
|
|
980
|
-
The input can be either:
|
|
981
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will first be converted to a
|
|
982
|
-
string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
983
|
-
2. A string already following the same layout.
|
|
984
|
-
|
|
985
|
-
The returned value preserves the overall format of the input but truncates or pads
|
|
986
|
-
the fractional seconds portion to **exactly two digits**.
|
|
987
|
-
|
|
988
|
-
Example
|
|
989
|
-
-------
|
|
990
|
-
>>> self._format_timestamp("2025-08-19-04:22:47.187574 UTC")
|
|
991
|
-
'2025-08-19-04:22:47.18 UTC'
|
|
992
|
-
"""
|
|
993
|
-
|
|
994
|
-
# Convert numeric timestamps to the expected string representation first
|
|
995
|
-
if isinstance(timestamp, (int, float)):
|
|
996
|
-
timestamp = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
|
|
997
|
-
'%Y-%m-%d-%H:%M:%S.%f UTC'
|
|
998
|
-
)
|
|
999
|
-
|
|
1000
|
-
# Ensure we are working with a string from here on
|
|
1001
|
-
if not isinstance(timestamp, str):
|
|
1002
|
-
return str(timestamp)
|
|
1003
|
-
|
|
1004
|
-
# If there is no fractional component, simply return the original string
|
|
1005
|
-
if '.' not in timestamp:
|
|
1006
|
-
return timestamp
|
|
1007
|
-
|
|
1008
|
-
# Split out the main portion (up to the decimal point)
|
|
1009
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
1010
|
-
|
|
1011
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
1012
|
-
if ' ' in fractional_and_suffix:
|
|
1013
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
1014
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
1015
|
-
else:
|
|
1016
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
1017
|
-
|
|
1018
|
-
# Guarantee exactly two digits for the fractional part
|
|
1019
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
1020
|
-
|
|
1021
|
-
return f"{main_part}.{fractional_part}{suffix}"
|
|
1022
|
-
|
|
1023
1058
|
def get_duration_seconds(self, start_time, end_time):
|
|
1024
1059
|
def parse_relative_time(t):
|
|
1025
1060
|
"""Parse HH:MM:SS(.f) manually into timedelta"""
|