matrice-analytics 0.1.60__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matrice_analytics/__init__.py +28 -0
- matrice_analytics/boundary_drawing_internal/README.md +305 -0
- matrice_analytics/boundary_drawing_internal/__init__.py +45 -0
- matrice_analytics/boundary_drawing_internal/boundary_drawing_internal.py +1207 -0
- matrice_analytics/boundary_drawing_internal/boundary_drawing_tool.py +429 -0
- matrice_analytics/boundary_drawing_internal/boundary_tool_template.html +1036 -0
- matrice_analytics/boundary_drawing_internal/data/.gitignore +12 -0
- matrice_analytics/boundary_drawing_internal/example_usage.py +206 -0
- matrice_analytics/boundary_drawing_internal/usage/README.md +110 -0
- matrice_analytics/boundary_drawing_internal/usage/boundary_drawer_launcher.py +102 -0
- matrice_analytics/boundary_drawing_internal/usage/simple_boundary_launcher.py +107 -0
- matrice_analytics/post_processing/README.md +455 -0
- matrice_analytics/post_processing/__init__.py +732 -0
- matrice_analytics/post_processing/advanced_tracker/README.md +650 -0
- matrice_analytics/post_processing/advanced_tracker/__init__.py +17 -0
- matrice_analytics/post_processing/advanced_tracker/base.py +99 -0
- matrice_analytics/post_processing/advanced_tracker/config.py +77 -0
- matrice_analytics/post_processing/advanced_tracker/kalman_filter.py +370 -0
- matrice_analytics/post_processing/advanced_tracker/matching.py +195 -0
- matrice_analytics/post_processing/advanced_tracker/strack.py +230 -0
- matrice_analytics/post_processing/advanced_tracker/tracker.py +367 -0
- matrice_analytics/post_processing/config.py +146 -0
- matrice_analytics/post_processing/core/__init__.py +63 -0
- matrice_analytics/post_processing/core/base.py +704 -0
- matrice_analytics/post_processing/core/config.py +3291 -0
- matrice_analytics/post_processing/core/config_utils.py +925 -0
- matrice_analytics/post_processing/face_reg/__init__.py +43 -0
- matrice_analytics/post_processing/face_reg/compare_similarity.py +556 -0
- matrice_analytics/post_processing/face_reg/embedding_manager.py +950 -0
- matrice_analytics/post_processing/face_reg/face_recognition.py +2234 -0
- matrice_analytics/post_processing/face_reg/face_recognition_client.py +606 -0
- matrice_analytics/post_processing/face_reg/people_activity_logging.py +321 -0
- matrice_analytics/post_processing/ocr/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/easyocr_extractor.py +250 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/__init__.py +9 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/__init__.py +4 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/cli.py +33 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/dataset_stats.py +139 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/export.py +398 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/train.py +447 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/utils.py +129 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/valid.py +93 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/validate_dataset.py +240 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_augmentation.py +176 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/cli/visualize_predictions.py +96 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/__init__.py +3 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/process.py +246 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/types.py +60 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/core/utils.py +87 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/__init__.py +3 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/config.py +82 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/hub.py +141 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/inference/plate_recognizer.py +323 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/py.typed +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/augmentation.py +101 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/data/dataset.py +97 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/config.py +114 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/layers.py +553 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/loss.py +55 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/metric.py +86 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_builders.py +95 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/model/model_schema.py +395 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/__init__.py +0 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/backend_utils.py +38 -0
- matrice_analytics/post_processing/ocr/fast_plate_ocr_py38/train/utilities/utils.py +214 -0
- matrice_analytics/post_processing/ocr/postprocessing.py +270 -0
- matrice_analytics/post_processing/ocr/preprocessing.py +52 -0
- matrice_analytics/post_processing/post_processor.py +1175 -0
- matrice_analytics/post_processing/test_cases/__init__.py +1 -0
- matrice_analytics/post_processing/test_cases/run_tests.py +143 -0
- matrice_analytics/post_processing/test_cases/test_advanced_customer_service.py +841 -0
- matrice_analytics/post_processing/test_cases/test_basic_counting_tracking.py +523 -0
- matrice_analytics/post_processing/test_cases/test_comprehensive.py +531 -0
- matrice_analytics/post_processing/test_cases/test_config.py +852 -0
- matrice_analytics/post_processing/test_cases/test_customer_service.py +585 -0
- matrice_analytics/post_processing/test_cases/test_data_generators.py +583 -0
- matrice_analytics/post_processing/test_cases/test_people_counting.py +510 -0
- matrice_analytics/post_processing/test_cases/test_processor.py +524 -0
- matrice_analytics/post_processing/test_cases/test_usecases.py +165 -0
- matrice_analytics/post_processing/test_cases/test_utilities.py +356 -0
- matrice_analytics/post_processing/test_cases/test_utils.py +743 -0
- matrice_analytics/post_processing/usecases/Histopathological_Cancer_Detection_img.py +604 -0
- matrice_analytics/post_processing/usecases/__init__.py +267 -0
- matrice_analytics/post_processing/usecases/abandoned_object_detection.py +797 -0
- matrice_analytics/post_processing/usecases/advanced_customer_service.py +1601 -0
- matrice_analytics/post_processing/usecases/age_detection.py +842 -0
- matrice_analytics/post_processing/usecases/age_gender_detection.py +1085 -0
- matrice_analytics/post_processing/usecases/anti_spoofing_detection.py +656 -0
- matrice_analytics/post_processing/usecases/assembly_line_detection.py +841 -0
- matrice_analytics/post_processing/usecases/banana_defect_detection.py +624 -0
- matrice_analytics/post_processing/usecases/basic_counting_tracking.py +667 -0
- matrice_analytics/post_processing/usecases/blood_cancer_detection_img.py +881 -0
- matrice_analytics/post_processing/usecases/car_damage_detection.py +834 -0
- matrice_analytics/post_processing/usecases/car_part_segmentation.py +946 -0
- matrice_analytics/post_processing/usecases/car_service.py +1601 -0
- matrice_analytics/post_processing/usecases/cardiomegaly_classification.py +864 -0
- matrice_analytics/post_processing/usecases/cell_microscopy_segmentation.py +897 -0
- matrice_analytics/post_processing/usecases/chicken_pose_detection.py +648 -0
- matrice_analytics/post_processing/usecases/child_monitoring.py +814 -0
- matrice_analytics/post_processing/usecases/color/clip.py +660 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/merges.txt +48895 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/preprocessor_config.json +28 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/special_tokens_map.json +30 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer.json +245079 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/tokenizer_config.json +32 -0
- matrice_analytics/post_processing/usecases/color/clip_processor/vocab.json +1 -0
- matrice_analytics/post_processing/usecases/color/color_map_utils.py +70 -0
- matrice_analytics/post_processing/usecases/color/color_mapper.py +468 -0
- matrice_analytics/post_processing/usecases/color_detection.py +1936 -0
- matrice_analytics/post_processing/usecases/color_map_utils.py +70 -0
- matrice_analytics/post_processing/usecases/concrete_crack_detection.py +827 -0
- matrice_analytics/post_processing/usecases/crop_weed_detection.py +781 -0
- matrice_analytics/post_processing/usecases/customer_service.py +1008 -0
- matrice_analytics/post_processing/usecases/defect_detection_products.py +936 -0
- matrice_analytics/post_processing/usecases/distracted_driver_detection.py +822 -0
- matrice_analytics/post_processing/usecases/drone_traffic_monitoring.py +585 -0
- matrice_analytics/post_processing/usecases/drowsy_driver_detection.py +829 -0
- matrice_analytics/post_processing/usecases/dwell_detection.py +829 -0
- matrice_analytics/post_processing/usecases/emergency_vehicle_detection.py +827 -0
- matrice_analytics/post_processing/usecases/face_emotion.py +813 -0
- matrice_analytics/post_processing/usecases/face_recognition.py +827 -0
- matrice_analytics/post_processing/usecases/fashion_detection.py +835 -0
- matrice_analytics/post_processing/usecases/field_mapping.py +902 -0
- matrice_analytics/post_processing/usecases/fire_detection.py +1146 -0
- matrice_analytics/post_processing/usecases/flare_analysis.py +836 -0
- matrice_analytics/post_processing/usecases/flower_segmentation.py +1006 -0
- matrice_analytics/post_processing/usecases/gas_leak_detection.py +837 -0
- matrice_analytics/post_processing/usecases/gender_detection.py +832 -0
- matrice_analytics/post_processing/usecases/human_activity_recognition.py +871 -0
- matrice_analytics/post_processing/usecases/intrusion_detection.py +1672 -0
- matrice_analytics/post_processing/usecases/leaf.py +821 -0
- matrice_analytics/post_processing/usecases/leaf_disease.py +840 -0
- matrice_analytics/post_processing/usecases/leak_detection.py +837 -0
- matrice_analytics/post_processing/usecases/license_plate_detection.py +1188 -0
- matrice_analytics/post_processing/usecases/license_plate_monitoring.py +1781 -0
- matrice_analytics/post_processing/usecases/litter_monitoring.py +717 -0
- matrice_analytics/post_processing/usecases/mask_detection.py +869 -0
- matrice_analytics/post_processing/usecases/natural_disaster.py +907 -0
- matrice_analytics/post_processing/usecases/parking.py +787 -0
- matrice_analytics/post_processing/usecases/parking_space_detection.py +822 -0
- matrice_analytics/post_processing/usecases/pcb_defect_detection.py +888 -0
- matrice_analytics/post_processing/usecases/pedestrian_detection.py +808 -0
- matrice_analytics/post_processing/usecases/people_counting.py +706 -0
- matrice_analytics/post_processing/usecases/people_counting_bckp.py +1683 -0
- matrice_analytics/post_processing/usecases/people_tracking.py +1842 -0
- matrice_analytics/post_processing/usecases/pipeline_detection.py +605 -0
- matrice_analytics/post_processing/usecases/plaque_segmentation_img.py +874 -0
- matrice_analytics/post_processing/usecases/pothole_segmentation.py +915 -0
- matrice_analytics/post_processing/usecases/ppe_compliance.py +645 -0
- matrice_analytics/post_processing/usecases/price_tag_detection.py +822 -0
- matrice_analytics/post_processing/usecases/proximity_detection.py +1901 -0
- matrice_analytics/post_processing/usecases/road_lane_detection.py +623 -0
- matrice_analytics/post_processing/usecases/road_traffic_density.py +832 -0
- matrice_analytics/post_processing/usecases/road_view_segmentation.py +915 -0
- matrice_analytics/post_processing/usecases/shelf_inventory_detection.py +583 -0
- matrice_analytics/post_processing/usecases/shoplifting_detection.py +822 -0
- matrice_analytics/post_processing/usecases/shopping_cart_analysis.py +899 -0
- matrice_analytics/post_processing/usecases/skin_cancer_classification_img.py +864 -0
- matrice_analytics/post_processing/usecases/smoker_detection.py +833 -0
- matrice_analytics/post_processing/usecases/solar_panel.py +810 -0
- matrice_analytics/post_processing/usecases/suspicious_activity_detection.py +1030 -0
- matrice_analytics/post_processing/usecases/template_usecase.py +380 -0
- matrice_analytics/post_processing/usecases/theft_detection.py +648 -0
- matrice_analytics/post_processing/usecases/traffic_sign_monitoring.py +724 -0
- matrice_analytics/post_processing/usecases/underground_pipeline_defect_detection.py +775 -0
- matrice_analytics/post_processing/usecases/underwater_pollution_detection.py +842 -0
- matrice_analytics/post_processing/usecases/vehicle_monitoring.py +1029 -0
- matrice_analytics/post_processing/usecases/warehouse_object_segmentation.py +899 -0
- matrice_analytics/post_processing/usecases/waterbody_segmentation.py +923 -0
- matrice_analytics/post_processing/usecases/weapon_detection.py +771 -0
- matrice_analytics/post_processing/usecases/weld_defect_detection.py +615 -0
- matrice_analytics/post_processing/usecases/wildlife_monitoring.py +898 -0
- matrice_analytics/post_processing/usecases/windmill_maintenance.py +834 -0
- matrice_analytics/post_processing/usecases/wound_segmentation.py +856 -0
- matrice_analytics/post_processing/utils/__init__.py +150 -0
- matrice_analytics/post_processing/utils/advanced_counting_utils.py +400 -0
- matrice_analytics/post_processing/utils/advanced_helper_utils.py +317 -0
- matrice_analytics/post_processing/utils/advanced_tracking_utils.py +461 -0
- matrice_analytics/post_processing/utils/alerting_utils.py +213 -0
- matrice_analytics/post_processing/utils/category_mapping_utils.py +94 -0
- matrice_analytics/post_processing/utils/color_utils.py +592 -0
- matrice_analytics/post_processing/utils/counting_utils.py +182 -0
- matrice_analytics/post_processing/utils/filter_utils.py +261 -0
- matrice_analytics/post_processing/utils/format_utils.py +293 -0
- matrice_analytics/post_processing/utils/geometry_utils.py +300 -0
- matrice_analytics/post_processing/utils/smoothing_utils.py +358 -0
- matrice_analytics/post_processing/utils/tracking_utils.py +234 -0
- matrice_analytics/py.typed +0 -0
- matrice_analytics-0.1.60.dist-info/METADATA +481 -0
- matrice_analytics-0.1.60.dist-info/RECORD +196 -0
- matrice_analytics-0.1.60.dist-info/WHEEL +5 -0
- matrice_analytics-0.1.60.dist-info/licenses/LICENSE.txt +21 -0
- matrice_analytics-0.1.60.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Easy-to-use boundary drawing tool for creating interactive zone definitions.
|
|
3
|
+
|
|
4
|
+
This module provides a simple interface for creating boundary drawing tools
|
|
5
|
+
from videos or images with just a few lines of code.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import cv2
|
|
9
|
+
import numpy as np
|
|
10
|
+
import os
|
|
11
|
+
import webbrowser
|
|
12
|
+
import base64
|
|
13
|
+
import datetime
|
|
14
|
+
import uuid
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Optional, Dict, Any, Union
|
|
17
|
+
from .boundary_drawing_internal import BoundaryDrawingTool
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EasyBoundaryTool:
|
|
21
|
+
"""
|
|
22
|
+
A simplified, easy-to-use boundary drawing tool that can be imported and used
|
|
23
|
+
with minimal code. Perfect for quickly creating zone definitions from videos or images.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
from matrice_analytics.boundary_drawing_internal import EasyBoundaryTool
|
|
27
|
+
|
|
28
|
+
# Create tool and open interactive interface
|
|
29
|
+
tool = EasyBoundaryTool()
|
|
30
|
+
zones = tool.create_from_video("my_video.mp4")
|
|
31
|
+
|
|
32
|
+
# Or from an image
|
|
33
|
+
zones = tool.create_from_image("frame.jpg")
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, auto_open_browser: bool = True, grid_step: int = 50):
|
|
37
|
+
"""
|
|
38
|
+
Initialize the easy boundary drawing tool.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
auto_open_browser (bool): Whether to automatically open the tool in browser
|
|
42
|
+
grid_step (int): Grid line spacing in pixels for reference
|
|
43
|
+
"""
|
|
44
|
+
self.auto_open_browser = auto_open_browser
|
|
45
|
+
self.grid_step = grid_step
|
|
46
|
+
self.tool = BoundaryDrawingTool()
|
|
47
|
+
self._data_dir = None
|
|
48
|
+
|
|
49
|
+
def _create_unique_data_dir(self, input_filename: str) -> str:
|
|
50
|
+
"""
|
|
51
|
+
Create a unique directory in the boundary_drawing_internal/data folder.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
input_filename (str): Name of the input file to create unique folder for
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
str: Path to the created unique directory
|
|
58
|
+
"""
|
|
59
|
+
# Get the boundary_drawing_internal directory
|
|
60
|
+
base_dir = Path(__file__).parent
|
|
61
|
+
data_dir = base_dir / "data"
|
|
62
|
+
|
|
63
|
+
# Create data directory if it doesn't exist
|
|
64
|
+
data_dir.mkdir(exist_ok=True)
|
|
65
|
+
|
|
66
|
+
# Create unique directory name with timestamp and UUID
|
|
67
|
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
68
|
+
unique_id = str(uuid.uuid4())[:8]
|
|
69
|
+
input_name = Path(input_filename).stem
|
|
70
|
+
|
|
71
|
+
unique_dir_name = f"{input_name}_{timestamp}_{unique_id}"
|
|
72
|
+
unique_dir = data_dir / unique_dir_name
|
|
73
|
+
|
|
74
|
+
# Create the unique directory
|
|
75
|
+
unique_dir.mkdir(exist_ok=True)
|
|
76
|
+
|
|
77
|
+
self._data_dir = str(unique_dir)
|
|
78
|
+
return self._data_dir
|
|
79
|
+
|
|
80
|
+
def create_from_video(self, video_path: str, output_dir: Optional[str] = None) -> str:
|
|
81
|
+
"""
|
|
82
|
+
Create an interactive boundary drawing tool from a video file.
|
|
83
|
+
Extracts the first frame and opens the drawing interface.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
video_path (str): Path to the video file
|
|
87
|
+
output_dir (str, optional): Directory to save output files.
|
|
88
|
+
If None, creates a unique directory in boundary_drawing_internal/data.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
str: Path to the HTML boundary drawing tool
|
|
92
|
+
|
|
93
|
+
Example:
|
|
94
|
+
tool = EasyBoundaryTool()
|
|
95
|
+
html_path = tool.create_from_video("security_camera.mp4")
|
|
96
|
+
# Interactive tool opens in browser
|
|
97
|
+
"""
|
|
98
|
+
if not os.path.exists(video_path):
|
|
99
|
+
raise FileNotFoundError(f"Video file not found: {video_path}")
|
|
100
|
+
|
|
101
|
+
# Set up output directory
|
|
102
|
+
if output_dir is None:
|
|
103
|
+
output_dir = self._create_unique_data_dir(video_path)
|
|
104
|
+
else:
|
|
105
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
106
|
+
|
|
107
|
+
# Process the video
|
|
108
|
+
results = self.tool.process_input_file(
|
|
109
|
+
input_path=video_path,
|
|
110
|
+
output_dir=output_dir,
|
|
111
|
+
grid_step=self.grid_step,
|
|
112
|
+
open_browser=self.auto_open_browser,
|
|
113
|
+
embed_image=True
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
print(f"๐ฏ Boundary drawing tool created from video: {video_path}")
|
|
117
|
+
print(f"๐ Files saved to: {output_dir}")
|
|
118
|
+
if self.auto_open_browser:
|
|
119
|
+
print("๐ Interactive tool opened in your browser")
|
|
120
|
+
else:
|
|
121
|
+
print(f"๐ Open this file in browser: {results['html_tool']}")
|
|
122
|
+
|
|
123
|
+
return results['html_tool']
|
|
124
|
+
|
|
125
|
+
def create_from_image(self, image_path: str, output_dir: Optional[str] = None) -> str:
|
|
126
|
+
"""
|
|
127
|
+
Create an interactive boundary drawing tool from an image file.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
image_path (str): Path to the image file
|
|
131
|
+
output_dir (str, optional): Directory to save output files.
|
|
132
|
+
If None, creates a unique directory in boundary_drawing_internal/data.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
str: Path to the HTML boundary drawing tool
|
|
136
|
+
|
|
137
|
+
Example:
|
|
138
|
+
tool = EasyBoundaryTool()
|
|
139
|
+
html_path = tool.create_from_image("frame.jpg")
|
|
140
|
+
# Interactive tool opens in browser
|
|
141
|
+
"""
|
|
142
|
+
if not os.path.exists(image_path):
|
|
143
|
+
raise FileNotFoundError(f"Image file not found: {image_path}")
|
|
144
|
+
|
|
145
|
+
# Set up output directory
|
|
146
|
+
if output_dir is None:
|
|
147
|
+
output_dir = self._create_unique_data_dir(image_path)
|
|
148
|
+
else:
|
|
149
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
150
|
+
|
|
151
|
+
# Process the image
|
|
152
|
+
results = self.tool.process_input_file(
|
|
153
|
+
input_path=image_path,
|
|
154
|
+
output_dir=output_dir,
|
|
155
|
+
grid_step=self.grid_step,
|
|
156
|
+
open_browser=self.auto_open_browser,
|
|
157
|
+
embed_image=True
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
print(f"๐ฏ Boundary drawing tool created from image: {image_path}")
|
|
161
|
+
print(f"๐ Files saved to: {output_dir}")
|
|
162
|
+
if self.auto_open_browser:
|
|
163
|
+
print("๐ Interactive tool opened in your browser")
|
|
164
|
+
else:
|
|
165
|
+
print(f"๐ Open this file in browser: {results['html_tool']}")
|
|
166
|
+
|
|
167
|
+
return results['html_tool']
|
|
168
|
+
|
|
169
|
+
def quick_setup(self, file_path: str, zones_needed: list = None) -> str:
|
|
170
|
+
"""
|
|
171
|
+
Quick setup method that auto-detects file type and creates the tool.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
file_path (str): Path to video or image file
|
|
175
|
+
zones_needed (list, optional): List of zone types you plan to create.
|
|
176
|
+
Used for informational purposes.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
str: Path to the HTML boundary drawing tool
|
|
180
|
+
|
|
181
|
+
Example:
|
|
182
|
+
tool = EasyBoundaryTool()
|
|
183
|
+
tool.quick_setup("video.mp4", zones_needed=["queue", "staff", "entry"])
|
|
184
|
+
"""
|
|
185
|
+
if not os.path.exists(file_path):
|
|
186
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
187
|
+
|
|
188
|
+
# Detect file type
|
|
189
|
+
file_type = self.tool.get_file_type(file_path)
|
|
190
|
+
|
|
191
|
+
if file_type == 'video':
|
|
192
|
+
html_path = self.create_from_video(file_path)
|
|
193
|
+
elif file_type == 'image':
|
|
194
|
+
html_path = self.create_from_image(file_path)
|
|
195
|
+
else:
|
|
196
|
+
raise ValueError(f"Unsupported file format: {Path(file_path).suffix}")
|
|
197
|
+
|
|
198
|
+
# Print helpful information
|
|
199
|
+
if zones_needed:
|
|
200
|
+
print(f"\n๐ Zones you plan to create: {', '.join(zones_needed)}")
|
|
201
|
+
|
|
202
|
+
print("\n๐ก Tips:")
|
|
203
|
+
print("1. Select a zone type from the sidebar")
|
|
204
|
+
print("2. Click on the image to add points")
|
|
205
|
+
print("3. Right-click or press Enter to complete a zone")
|
|
206
|
+
print("4. Use the 'Generate Code' button to get Python code")
|
|
207
|
+
print("5. Copy the generated code for use in your applications")
|
|
208
|
+
|
|
209
|
+
return html_path
|
|
210
|
+
|
|
211
|
+
def create_standalone_tool(self, output_path: str = "boundary_tool.html") -> str:
|
|
212
|
+
"""
|
|
213
|
+
Create a standalone HTML tool that can accept file uploads.
|
|
214
|
+
This creates a self-contained tool that doesn't need a specific input file.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
output_path (str): Path where to save the standalone HTML tool
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
str: Path to the created HTML tool
|
|
221
|
+
|
|
222
|
+
Example:
|
|
223
|
+
tool = EasyBoundaryTool()
|
|
224
|
+
html_path = tool.create_standalone_tool("my_boundary_tool.html")
|
|
225
|
+
# Opens a tool where you can drag & drop any video/image
|
|
226
|
+
"""
|
|
227
|
+
# Read the template HTML
|
|
228
|
+
template_path = Path(__file__).parent / "boundary_tool_template.html"
|
|
229
|
+
|
|
230
|
+
if not template_path.exists():
|
|
231
|
+
raise FileNotFoundError("Template HTML file not found")
|
|
232
|
+
|
|
233
|
+
# Copy template to output location
|
|
234
|
+
with open(template_path, 'r', encoding='utf-8') as f:
|
|
235
|
+
html_content = f.read()
|
|
236
|
+
|
|
237
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
|
238
|
+
f.write(html_content)
|
|
239
|
+
|
|
240
|
+
print(f"๐ฏ Standalone boundary drawing tool created: {output_path}")
|
|
241
|
+
|
|
242
|
+
if self.auto_open_browser:
|
|
243
|
+
try:
|
|
244
|
+
webbrowser.open(f'file://{os.path.abspath(output_path)}')
|
|
245
|
+
print("๐ Standalone tool opened in your browser")
|
|
246
|
+
except Exception as e:
|
|
247
|
+
print(f"Could not open browser: {e}")
|
|
248
|
+
print(f"๐ Please manually open: {output_path}")
|
|
249
|
+
else:
|
|
250
|
+
print(f"๐ Open this file in browser: {output_path}")
|
|
251
|
+
|
|
252
|
+
print("\n๐ก With the standalone tool you can:")
|
|
253
|
+
print("- Drag & drop any video or image file")
|
|
254
|
+
print("- Create multiple zone configurations")
|
|
255
|
+
print("- Save and load configurations")
|
|
256
|
+
print("- Generate code for different projects")
|
|
257
|
+
|
|
258
|
+
return output_path
|
|
259
|
+
|
|
260
|
+
def get_template_code(self, zone_types: list = None) -> str:
|
|
261
|
+
"""
|
|
262
|
+
Get template Python code showing how to use the generated zones.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
zone_types (list, optional): List of zone types to include in template
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
str: Template Python code
|
|
269
|
+
|
|
270
|
+
Example:
|
|
271
|
+
tool = EasyBoundaryTool()
|
|
272
|
+
template = tool.get_template_code(["queue", "staff", "service"])
|
|
273
|
+
print(template)
|
|
274
|
+
"""
|
|
275
|
+
if zone_types is None:
|
|
276
|
+
zone_types = ["queue", "staff", "entry", "exit"]
|
|
277
|
+
|
|
278
|
+
template = """# Template code for using your boundary zones
|
|
279
|
+
from matrice_analytics.post_processing import (
|
|
280
|
+
CustomerServiceProcessor,
|
|
281
|
+
AdvancedTrackingProcessor,
|
|
282
|
+
CountingProcessor
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Your zones dictionary (replace with generated code)
|
|
286
|
+
zones = {
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
for i, zone_type in enumerate(zone_types):
|
|
290
|
+
template += f' "{zone_type}": [[100, 100], [200, 100], [200, 200], [100, 200]]'
|
|
291
|
+
if i < len(zone_types) - 1:
|
|
292
|
+
template += ","
|
|
293
|
+
template += "\n"
|
|
294
|
+
|
|
295
|
+
template += """}\n
|
|
296
|
+
# Usage examples:
|
|
297
|
+
|
|
298
|
+
# 1. Customer Service Processor
|
|
299
|
+
customer_processor = CustomerServiceProcessor(
|
|
300
|
+
customer_areas=zones.get("queue", {}),
|
|
301
|
+
staff_areas=zones.get("staff", {}),
|
|
302
|
+
service_areas=zones.get("service", {})
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# 2. Advanced Tracking with Boundaries
|
|
306
|
+
from matrice_analytics.post_processing.config import AdvancedTrackingConfig
|
|
307
|
+
|
|
308
|
+
tracking_config = AdvancedTrackingConfig(
|
|
309
|
+
boundary_config={
|
|
310
|
+
"points": zones.get("entry", []),
|
|
311
|
+
"type": "line"
|
|
312
|
+
}
|
|
313
|
+
)
|
|
314
|
+
tracking_processor = AdvancedTrackingProcessor(tracking_config)
|
|
315
|
+
|
|
316
|
+
# 3. Counting in Zones
|
|
317
|
+
from matrice_analytics.post_processing.config import CountingConfig
|
|
318
|
+
|
|
319
|
+
counting_config = CountingConfig(
|
|
320
|
+
count_rules={"enable_time_based_counting": True}
|
|
321
|
+
)
|
|
322
|
+
counting_processor = CountingProcessor(counting_config)
|
|
323
|
+
|
|
324
|
+
# Count objects in specific zones
|
|
325
|
+
detection_results = {} # Your detection results
|
|
326
|
+
count_results = counting_processor.count_in_zones(
|
|
327
|
+
results=detection_results,
|
|
328
|
+
zones=zones
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
print("Zone counts:", count_results)
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
return template
|
|
335
|
+
|
|
336
|
+
def cleanup(self):
|
|
337
|
+
"""
|
|
338
|
+
Optionally clean up data files created by the tool.
|
|
339
|
+
Note: Files are now saved permanently in boundary_drawing_internal/data/
|
|
340
|
+
"""
|
|
341
|
+
if self._data_dir and os.path.exists(self._data_dir):
|
|
342
|
+
import shutil
|
|
343
|
+
try:
|
|
344
|
+
response = input(f"๐๏ธ Delete saved boundary tool files in {self._data_dir}? (y/N): ")
|
|
345
|
+
if response.lower() in ['y', 'yes']:
|
|
346
|
+
shutil.rmtree(self._data_dir)
|
|
347
|
+
print(f"๐งน Cleaned up boundary tool files: {self._data_dir}")
|
|
348
|
+
else:
|
|
349
|
+
print(f"๐ Files preserved in: {self._data_dir}")
|
|
350
|
+
except Exception as e:
|
|
351
|
+
print(f"Warning: Could not clean up files: {e}")
|
|
352
|
+
|
|
353
|
+
def get_data_directory(self) -> Optional[str]:
|
|
354
|
+
"""
|
|
355
|
+
Get the data directory where files are saved.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
str: Path to the data directory, or None if not created yet
|
|
359
|
+
"""
|
|
360
|
+
return self._data_dir
|
|
361
|
+
|
|
362
|
+
def __del__(self):
|
|
363
|
+
"""Clean up on object destruction - but don't auto-delete data files."""
|
|
364
|
+
# Don't auto-cleanup data files since they're meant to be permanent
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# Convenience functions for even easier usage
|
|
369
|
+
def quick_boundary_tool(file_path: str, zones_needed: list = None, auto_open: bool = True) -> str:
|
|
370
|
+
"""
|
|
371
|
+
One-line function to create a boundary drawing tool from any file.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
file_path (str): Path to video or image file
|
|
375
|
+
zones_needed (list, optional): List of zone types you plan to create
|
|
376
|
+
auto_open (bool): Whether to automatically open in browser
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
str: Path to the HTML boundary drawing tool
|
|
380
|
+
|
|
381
|
+
Example:
|
|
382
|
+
from matrice_analytics.boundary_drawing_internal import quick_boundary_tool
|
|
383
|
+
|
|
384
|
+
# One line to create and open the tool
|
|
385
|
+
quick_boundary_tool("my_video.mp4", ["queue", "staff", "exit"])
|
|
386
|
+
"""
|
|
387
|
+
tool = EasyBoundaryTool(auto_open_browser=auto_open)
|
|
388
|
+
return tool.quick_setup(file_path, zones_needed)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def create_standalone_tool(output_path: str = "boundary_tool.html", auto_open: bool = True) -> str:
|
|
392
|
+
"""
|
|
393
|
+
One-line function to create a standalone boundary drawing tool.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
output_path (str): Where to save the HTML tool
|
|
397
|
+
auto_open (bool): Whether to automatically open in browser
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
str: Path to the created HTML tool
|
|
401
|
+
|
|
402
|
+
Example:
|
|
403
|
+
from matrice_analytics.boundary_drawing_internal import create_standalone_tool
|
|
404
|
+
|
|
405
|
+
# Create a standalone tool
|
|
406
|
+
create_standalone_tool("my_tool.html")
|
|
407
|
+
"""
|
|
408
|
+
tool = EasyBoundaryTool(auto_open_browser=auto_open)
|
|
409
|
+
return tool.create_standalone_tool(output_path)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def get_usage_template(zone_types: list = None) -> str:
|
|
413
|
+
"""
|
|
414
|
+
Get template code for using generated zones.
|
|
415
|
+
|
|
416
|
+
Args:
|
|
417
|
+
zone_types (list, optional): Zone types to include in template
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
str: Template Python code
|
|
421
|
+
|
|
422
|
+
Example:
|
|
423
|
+
from matrice_analytics.boundary_drawing_internal import get_usage_template
|
|
424
|
+
|
|
425
|
+
template = get_usage_template(["queue", "staff"])
|
|
426
|
+
print(template)
|
|
427
|
+
"""
|
|
428
|
+
tool = EasyBoundaryTool()
|
|
429
|
+
return tool.get_template_code(zone_types)
|