ultralytics 8.3.89__py3-none-any.whl → 8.3.91__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.
- tests/conftest.py +2 -2
- tests/test_cli.py +13 -11
- tests/test_cuda.py +10 -1
- tests/test_exports.py +2 -2
- tests/test_integrations.py +1 -5
- tests/test_python.py +16 -16
- tests/test_solutions.py +9 -9
- ultralytics/__init__.py +1 -1
- ultralytics/cfg/__init__.py +3 -1
- ultralytics/cfg/models/11/yolo11-cls.yaml +5 -5
- ultralytics/cfg/models/11/yolo11-obb.yaml +5 -5
- ultralytics/cfg/models/11/yolo11-pose.yaml +5 -5
- ultralytics/cfg/models/11/yolo11-seg.yaml +5 -5
- ultralytics/cfg/models/11/yolo11.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-ghost.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-obb.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-p6.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-world.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8-worldv2.yaml +5 -5
- ultralytics/cfg/models/v8/yolov8.yaml +5 -5
- ultralytics/cfg/models/v9/yolov9c-seg.yaml +1 -1
- ultralytics/cfg/models/v9/yolov9c.yaml +1 -1
- ultralytics/cfg/models/v9/yolov9e-seg.yaml +1 -1
- ultralytics/cfg/models/v9/yolov9e.yaml +1 -1
- ultralytics/cfg/models/v9/yolov9m.yaml +1 -1
- ultralytics/cfg/models/v9/yolov9s.yaml +1 -1
- ultralytics/cfg/models/v9/yolov9t.yaml +1 -1
- ultralytics/data/annotator.py +9 -14
- ultralytics/data/base.py +118 -30
- ultralytics/data/build.py +63 -24
- ultralytics/data/converter.py +5 -5
- ultralytics/data/dataset.py +207 -53
- ultralytics/data/loaders.py +1 -0
- ultralytics/data/split_dota.py +39 -12
- ultralytics/data/utils.py +15 -19
- ultralytics/engine/exporter.py +24 -23
- ultralytics/engine/model.py +67 -88
- ultralytics/engine/predictor.py +106 -21
- ultralytics/engine/trainer.py +32 -23
- ultralytics/engine/tuner.py +21 -18
- ultralytics/engine/validator.py +75 -41
- ultralytics/hub/__init__.py +12 -13
- ultralytics/hub/auth.py +9 -12
- ultralytics/hub/session.py +76 -21
- ultralytics/hub/utils.py +19 -17
- ultralytics/models/fastsam/model.py +20 -11
- ultralytics/models/fastsam/predict.py +36 -16
- ultralytics/models/fastsam/utils.py +5 -5
- ultralytics/models/fastsam/val.py +6 -6
- ultralytics/models/nas/model.py +22 -11
- ultralytics/models/nas/predict.py +9 -4
- ultralytics/models/nas/val.py +5 -5
- ultralytics/models/rtdetr/model.py +20 -11
- ultralytics/models/rtdetr/predict.py +18 -15
- ultralytics/models/rtdetr/train.py +20 -16
- ultralytics/models/rtdetr/val.py +42 -6
- ultralytics/models/sam/__init__.py +1 -1
- ultralytics/models/sam/amg.py +50 -4
- ultralytics/models/sam/model.py +8 -14
- ultralytics/models/sam/modules/decoders.py +18 -21
- ultralytics/models/sam/modules/encoders.py +25 -46
- ultralytics/models/sam/modules/memory_attention.py +19 -15
- ultralytics/models/sam/modules/sam.py +18 -25
- ultralytics/models/sam/modules/tiny_encoder.py +19 -29
- ultralytics/models/sam/modules/transformer.py +35 -57
- ultralytics/models/sam/modules/utils.py +15 -15
- ultralytics/models/sam/predict.py +0 -3
- ultralytics/models/utils/loss.py +87 -36
- ultralytics/models/utils/ops.py +26 -31
- ultralytics/models/yolo/classify/predict.py +24 -3
- ultralytics/models/yolo/classify/train.py +77 -10
- ultralytics/models/yolo/classify/val.py +40 -15
- ultralytics/models/yolo/detect/predict.py +23 -10
- ultralytics/models/yolo/detect/train.py +85 -15
- ultralytics/models/yolo/detect/val.py +145 -21
- ultralytics/models/yolo/model.py +1 -2
- ultralytics/models/yolo/obb/predict.py +12 -4
- ultralytics/models/yolo/obb/train.py +7 -0
- ultralytics/models/yolo/obb/val.py +25 -7
- ultralytics/models/yolo/pose/predict.py +22 -6
- ultralytics/models/yolo/pose/train.py +17 -1
- ultralytics/models/yolo/pose/val.py +46 -21
- ultralytics/models/yolo/segment/predict.py +22 -8
- ultralytics/models/yolo/segment/train.py +6 -0
- ultralytics/models/yolo/segment/val.py +100 -14
- ultralytics/models/yolo/world/train.py +38 -8
- ultralytics/models/yolo/world/train_world.py +39 -10
- ultralytics/nn/autobackend.py +28 -14
- ultralytics/nn/modules/__init__.py +3 -0
- ultralytics/nn/modules/activation.py +12 -3
- ultralytics/nn/modules/block.py +587 -84
- ultralytics/nn/modules/conv.py +418 -54
- ultralytics/nn/modules/head.py +3 -4
- ultralytics/nn/modules/transformer.py +320 -34
- ultralytics/nn/modules/utils.py +17 -3
- ultralytics/nn/tasks.py +221 -69
- ultralytics/solutions/ai_gym.py +2 -2
- ultralytics/solutions/analytics.py +4 -4
- ultralytics/solutions/heatmap.py +4 -4
- ultralytics/solutions/instance_segmentation.py +10 -4
- ultralytics/solutions/object_blurrer.py +2 -2
- ultralytics/solutions/object_counter.py +2 -2
- ultralytics/solutions/object_cropper.py +2 -2
- ultralytics/solutions/parking_management.py +9 -9
- ultralytics/solutions/queue_management.py +1 -1
- ultralytics/solutions/region_counter.py +2 -2
- ultralytics/solutions/security_alarm.py +7 -7
- ultralytics/solutions/solutions.py +7 -4
- ultralytics/solutions/speed_estimation.py +2 -2
- ultralytics/solutions/streamlit_inference.py +6 -6
- ultralytics/solutions/trackzone.py +9 -2
- ultralytics/solutions/vision_eye.py +4 -4
- ultralytics/trackers/basetrack.py +1 -1
- ultralytics/trackers/bot_sort.py +23 -22
- ultralytics/trackers/byte_tracker.py +4 -4
- ultralytics/trackers/track.py +2 -1
- ultralytics/trackers/utils/gmc.py +26 -27
- ultralytics/trackers/utils/kalman_filter.py +31 -29
- ultralytics/trackers/utils/matching.py +7 -7
- ultralytics/utils/__init__.py +32 -27
- ultralytics/utils/autobatch.py +5 -5
- ultralytics/utils/benchmarks.py +111 -18
- ultralytics/utils/callbacks/base.py +3 -3
- ultralytics/utils/callbacks/clearml.py +11 -11
- ultralytics/utils/callbacks/comet.py +42 -24
- ultralytics/utils/callbacks/dvc.py +11 -10
- ultralytics/utils/callbacks/hub.py +8 -8
- ultralytics/utils/callbacks/mlflow.py +1 -1
- ultralytics/utils/callbacks/neptune.py +12 -10
- ultralytics/utils/callbacks/raytune.py +1 -1
- ultralytics/utils/callbacks/tensorboard.py +6 -6
- ultralytics/utils/callbacks/wb.py +16 -16
- ultralytics/utils/checks.py +116 -35
- ultralytics/utils/dist.py +15 -2
- ultralytics/utils/downloads.py +13 -9
- ultralytics/utils/files.py +12 -13
- ultralytics/utils/instance.py +112 -45
- ultralytics/utils/loss.py +28 -33
- ultralytics/utils/metrics.py +246 -181
- ultralytics/utils/ops.py +61 -53
- ultralytics/utils/patches.py +8 -6
- ultralytics/utils/plotting.py +65 -45
- ultralytics/utils/tal.py +88 -57
- ultralytics/utils/torch_utils.py +181 -33
- ultralytics/utils/triton.py +13 -3
- ultralytics/utils/tuner.py +8 -16
- {ultralytics-8.3.89.dist-info → ultralytics-8.3.91.dist-info}/METADATA +1 -1
- ultralytics-8.3.91.dist-info/RECORD +250 -0
- ultralytics-8.3.89.dist-info/RECORD +0 -250
- {ultralytics-8.3.89.dist-info → ultralytics-8.3.91.dist-info}/LICENSE +0 -0
- {ultralytics-8.3.89.dist-info → ultralytics-8.3.91.dist-info}/WHEEL +0 -0
- {ultralytics-8.3.89.dist-info → ultralytics-8.3.91.dist-info}/entry_points.txt +0 -0
- {ultralytics-8.3.89.dist-info → ultralytics-8.3.91.dist-info}/top_level.txt +0 -0
@@ -34,7 +34,7 @@ class ObjectBlurrer(BaseSolution):
|
|
34
34
|
|
35
35
|
def __init__(self, **kwargs):
|
36
36
|
"""
|
37
|
-
|
37
|
+
Initialize the ObjectBlurrer class for applying a blur effect to objects detected in video streams or images.
|
38
38
|
|
39
39
|
Args:
|
40
40
|
**kwargs (Any): Keyword arguments passed to the parent class and for configuration.
|
@@ -49,7 +49,7 @@ class ObjectBlurrer(BaseSolution):
|
|
49
49
|
|
50
50
|
def process(self, im0):
|
51
51
|
"""
|
52
|
-
|
52
|
+
Apply a blurring effect to detected objects in the input image.
|
53
53
|
|
54
54
|
This method extracts tracking information, applies blur to regions corresponding to detected objects,
|
55
55
|
and annotates the image with bounding boxes.
|
@@ -127,7 +127,7 @@ class ObjectCounter(BaseSolution):
|
|
127
127
|
|
128
128
|
def display_counts(self, plot_im):
|
129
129
|
"""
|
130
|
-
|
130
|
+
Display object counts on the input image or frame.
|
131
131
|
|
132
132
|
Args:
|
133
133
|
plot_im (numpy.ndarray): The image or frame to display counts on.
|
@@ -148,7 +148,7 @@ class ObjectCounter(BaseSolution):
|
|
148
148
|
|
149
149
|
def process(self, im0):
|
150
150
|
"""
|
151
|
-
|
151
|
+
Process input data (frames or object tracks) and update object counts.
|
152
152
|
|
153
153
|
This method initializes the counting region, extracts tracks, draws bounding boxes and regions, updates
|
154
154
|
object counts, and displays the results on the input image.
|
@@ -32,7 +32,7 @@ class ObjectCropper(BaseSolution):
|
|
32
32
|
|
33
33
|
def __init__(self, **kwargs):
|
34
34
|
"""
|
35
|
-
|
35
|
+
Initialize the ObjectCropper class for cropping objects from detected bounding boxes.
|
36
36
|
|
37
37
|
Args:
|
38
38
|
**kwargs (Any): Keyword arguments passed to the parent class and used for configuration.
|
@@ -53,7 +53,7 @@ class ObjectCropper(BaseSolution):
|
|
53
53
|
|
54
54
|
def process(self, im0):
|
55
55
|
"""
|
56
|
-
|
56
|
+
Crop detected objects from the input image and save them as separate images.
|
57
57
|
|
58
58
|
Args:
|
59
59
|
im0 (numpy.ndarray): The input image containing detected objects.
|
@@ -47,7 +47,7 @@ class ParkingPtsSelection:
|
|
47
47
|
"""
|
48
48
|
|
49
49
|
def __init__(self):
|
50
|
-
"""
|
50
|
+
"""Initialize the ParkingPtsSelection class, setting up UI and properties for parking zone point selection."""
|
51
51
|
try: # check if tkinter installed
|
52
52
|
import tkinter as tk
|
53
53
|
from tkinter import filedialog, messagebox
|
@@ -106,7 +106,7 @@ class ParkingPtsSelection:
|
|
106
106
|
self.canvas_max_width, self.canvas_max_height = 1280, 720
|
107
107
|
|
108
108
|
def upload_image(self):
|
109
|
-
"""
|
109
|
+
"""Upload and display an image on the canvas, resizing it to fit within specified dimensions."""
|
110
110
|
from PIL import Image, ImageTk # scope because ImageTk requires tkinter package
|
111
111
|
|
112
112
|
self.image = Image.open(self.filedialog.askopenfilename(filetypes=[("Image Files", "*.png *.jpg *.jpeg")]))
|
@@ -130,7 +130,7 @@ class ParkingPtsSelection:
|
|
130
130
|
self.rg_data.clear(), self.current_box.clear()
|
131
131
|
|
132
132
|
def on_canvas_click(self, event):
|
133
|
-
"""
|
133
|
+
"""Handle mouse clicks to add points for bounding boxes on the canvas."""
|
134
134
|
self.current_box.append((event.x, event.y))
|
135
135
|
self.canvas.create_oval(event.x - 3, event.y - 3, event.x + 3, event.y + 3, fill="red")
|
136
136
|
if len(self.current_box) == 4:
|
@@ -139,12 +139,12 @@ class ParkingPtsSelection:
|
|
139
139
|
self.current_box.clear()
|
140
140
|
|
141
141
|
def draw_box(self, box):
|
142
|
-
"""
|
142
|
+
"""Draw a bounding box on the canvas using the provided coordinates."""
|
143
143
|
for i in range(4):
|
144
144
|
self.canvas.create_line(box[i], box[(i + 1) % 4], fill="blue", width=2)
|
145
145
|
|
146
146
|
def remove_last_bounding_box(self):
|
147
|
-
"""
|
147
|
+
"""Remove the last bounding box from the list and redraw the canvas."""
|
148
148
|
if not self.rg_data:
|
149
149
|
self.messagebox.showwarning("Warning", "No bounding boxes to remove.")
|
150
150
|
return
|
@@ -152,14 +152,14 @@ class ParkingPtsSelection:
|
|
152
152
|
self.redraw_canvas()
|
153
153
|
|
154
154
|
def redraw_canvas(self):
|
155
|
-
"""
|
155
|
+
"""Redraw the canvas with the image and all bounding boxes."""
|
156
156
|
self.canvas.delete("all")
|
157
157
|
self.canvas.create_image(0, 0, anchor=self.tk.NW, image=self.canvas_image)
|
158
158
|
for box in self.rg_data:
|
159
159
|
self.draw_box(box)
|
160
160
|
|
161
161
|
def save_to_json(self):
|
162
|
-
"""
|
162
|
+
"""Save the selected parking zone points to a JSON file with scaled coordinates."""
|
163
163
|
scale_w, scale_h = self.imgw / self.canvas.winfo_width(), self.imgh / self.canvas.winfo_height()
|
164
164
|
data = [{"points": [(int(x * scale_w), int(y * scale_h)) for x, y in box]} for box in self.rg_data]
|
165
165
|
|
@@ -198,7 +198,7 @@ class ParkingManagement(BaseSolution):
|
|
198
198
|
"""
|
199
199
|
|
200
200
|
def __init__(self, **kwargs):
|
201
|
-
"""
|
201
|
+
"""Initialize the parking management system with a YOLO model and visualization settings."""
|
202
202
|
super().__init__(**kwargs)
|
203
203
|
|
204
204
|
self.json_file = self.CFG["json_file"] # Load JSON data
|
@@ -217,7 +217,7 @@ class ParkingManagement(BaseSolution):
|
|
217
217
|
|
218
218
|
def process(self, im0):
|
219
219
|
"""
|
220
|
-
|
220
|
+
Process the input image for parking lot management and visualization.
|
221
221
|
|
222
222
|
This function analyzes the input image, extracts tracks, and determines the occupancy status of parking
|
223
223
|
regions defined in the JSON file. It annotates the image with occupied and available parking spots,
|
@@ -45,7 +45,7 @@ class QueueManager(BaseSolution):
|
|
45
45
|
|
46
46
|
def process(self, im0):
|
47
47
|
"""
|
48
|
-
|
48
|
+
Process queue management for a single frame of video.
|
49
49
|
|
50
50
|
Args:
|
51
51
|
im0 (numpy.ndarray): Input image for processing, typically a frame from a video stream.
|
@@ -42,7 +42,7 @@ class RegionCounter(BaseSolution):
|
|
42
42
|
|
43
43
|
def add_region(self, name, polygon_points, region_color, text_color):
|
44
44
|
"""
|
45
|
-
|
45
|
+
Add a new region to the counting list based on the provided template with specific attributes.
|
46
46
|
|
47
47
|
Args:
|
48
48
|
name (str): Name assigned to the new region.
|
@@ -63,7 +63,7 @@ class RegionCounter(BaseSolution):
|
|
63
63
|
|
64
64
|
def process(self, im0):
|
65
65
|
"""
|
66
|
-
|
66
|
+
Process the input frame to detect and count objects within each defined region.
|
67
67
|
|
68
68
|
Args:
|
69
69
|
im0 (np.ndarray): Input image frame where objects and regions are annotated.
|
@@ -21,9 +21,9 @@ class SecurityAlarm(BaseSolution):
|
|
21
21
|
from_email (str): Sender's email address for alerts.
|
22
22
|
|
23
23
|
Methods:
|
24
|
-
authenticate:
|
25
|
-
send_email:
|
26
|
-
process:
|
24
|
+
authenticate: Set up email server authentication for sending alerts.
|
25
|
+
send_email: Send an email notification with details and an image attachment.
|
26
|
+
process: Monitor the frame, process detections, and trigger alerts if thresholds are crossed.
|
27
27
|
|
28
28
|
Examples:
|
29
29
|
>>> security = SecurityAlarm()
|
@@ -34,7 +34,7 @@ class SecurityAlarm(BaseSolution):
|
|
34
34
|
|
35
35
|
def __init__(self, **kwargs):
|
36
36
|
"""
|
37
|
-
|
37
|
+
Initialize the SecurityAlarm class with parameters for real-time object monitoring.
|
38
38
|
|
39
39
|
Args:
|
40
40
|
**kwargs (Any): Additional keyword arguments passed to the parent class.
|
@@ -48,7 +48,7 @@ class SecurityAlarm(BaseSolution):
|
|
48
48
|
|
49
49
|
def authenticate(self, from_email, password, to_email):
|
50
50
|
"""
|
51
|
-
|
51
|
+
Authenticate the email server for sending alert notifications.
|
52
52
|
|
53
53
|
Args:
|
54
54
|
from_email (str): Sender's email address.
|
@@ -71,7 +71,7 @@ class SecurityAlarm(BaseSolution):
|
|
71
71
|
|
72
72
|
def send_email(self, im0, records=5):
|
73
73
|
"""
|
74
|
-
|
74
|
+
Send an email notification with an image attachment indicating the number of objects detected.
|
75
75
|
|
76
76
|
Args:
|
77
77
|
im0 (numpy.ndarray): The input image or frame to be attached to the email.
|
@@ -116,7 +116,7 @@ class SecurityAlarm(BaseSolution):
|
|
116
116
|
|
117
117
|
def process(self, im0):
|
118
118
|
"""
|
119
|
-
|
119
|
+
Monitor the frame, process object detections, and trigger alerts if thresholds are exceeded.
|
120
120
|
|
121
121
|
Args:
|
122
122
|
im0 (numpy.ndarray): The input image or frame to be processed and annotated.
|
@@ -86,13 +86,13 @@ class BaseSolution:
|
|
86
86
|
# Load Model and store classes names
|
87
87
|
if self.CFG["model"] is None:
|
88
88
|
self.CFG["model"] = "yolo11n.pt"
|
89
|
-
self.model = YOLO(self.CFG["model"]
|
89
|
+
self.model = YOLO(self.CFG["model"])
|
90
90
|
self.names = self.model.names
|
91
91
|
self.classes = self.CFG["classes"]
|
92
92
|
|
93
93
|
self.track_add_args = { # Tracker additional arguments for advance configuration
|
94
|
-
k: self.CFG[k] for k in ["iou", "conf", "device", "max_det", "half", "tracker", "device"]
|
95
|
-
}
|
94
|
+
k: self.CFG[k] for k in ["iou", "conf", "device", "max_det", "half", "tracker", "device", "verbose"]
|
95
|
+
} # verbose must be passed to track method; setting it False in YOLO still logs the track information.
|
96
96
|
|
97
97
|
if is_cli and self.CFG["source"] is None:
|
98
98
|
d_s = "solutions_ci_demo.mp4" if "-pose" not in self.CFG["model"] else "solution_ci_pose_demo.mp4"
|
@@ -193,7 +193,10 @@ class BaseSolution:
|
|
193
193
|
|
194
194
|
def __call__(self, *args, **kwargs):
|
195
195
|
"""Allow instances to be called like a function with flexible arguments."""
|
196
|
-
|
196
|
+
result = self.process(*args, **kwargs) # Call the subclass-specific process method
|
197
|
+
if self.CFG["verbose"]: # extract verbose value to display the output logs if True
|
198
|
+
LOGGER.info(f"🚀 Results: {result}")
|
199
|
+
return result
|
197
200
|
|
198
201
|
|
199
202
|
class SolutionAnnotator(Annotator):
|
@@ -40,7 +40,7 @@ class SpeedEstimator(BaseSolution):
|
|
40
40
|
|
41
41
|
def __init__(self, **kwargs):
|
42
42
|
"""
|
43
|
-
|
43
|
+
Initialize the SpeedEstimator object with speed estimation parameters and data structures.
|
44
44
|
|
45
45
|
Args:
|
46
46
|
**kwargs (Any): Additional keyword arguments passed to the parent class.
|
@@ -56,7 +56,7 @@ class SpeedEstimator(BaseSolution):
|
|
56
56
|
|
57
57
|
def process(self, im0):
|
58
58
|
"""
|
59
|
-
|
59
|
+
Process an input frame to estimate object speeds based on tracking data.
|
60
60
|
|
61
61
|
Args:
|
62
62
|
im0 (np.ndarray): Input image for processing with shape (H, W, C) for RGB images.
|
@@ -29,7 +29,7 @@ class Inference:
|
|
29
29
|
iou (float): IoU threshold for non-maximum suppression.
|
30
30
|
org_frame (Any): Container for the original frame to be displayed.
|
31
31
|
ann_frame (Any): Container for the annotated frame to be displayed.
|
32
|
-
vid_file_name (
|
32
|
+
vid_file_name (str | int): Name of the uploaded video file or webcam index.
|
33
33
|
selected_ind (List[int]): List of selected class indices for detection.
|
34
34
|
|
35
35
|
Methods:
|
@@ -46,7 +46,7 @@ class Inference:
|
|
46
46
|
|
47
47
|
def __init__(self, **kwargs: Any):
|
48
48
|
"""
|
49
|
-
|
49
|
+
Initialize the Inference class, checking Streamlit requirements and setting up the model path.
|
50
50
|
|
51
51
|
Args:
|
52
52
|
**kwargs (Any): Additional keyword arguments for model configuration.
|
@@ -92,7 +92,7 @@ class Inference:
|
|
92
92
|
self.st.markdown(sub_title_cfg, unsafe_allow_html=True)
|
93
93
|
|
94
94
|
def sidebar(self):
|
95
|
-
"""
|
95
|
+
"""Configure the Streamlit sidebar for model and inference settings."""
|
96
96
|
with self.st.sidebar: # Add Ultralytics LOGO
|
97
97
|
logo = "https://raw.githubusercontent.com/ultralytics/assets/main/logo/Ultralytics_Logotype_Original.svg"
|
98
98
|
self.st.image(logo, width=250)
|
@@ -113,7 +113,7 @@ class Inference:
|
|
113
113
|
self.ann_frame = col2.empty() # Container for annotated frame
|
114
114
|
|
115
115
|
def source_upload(self):
|
116
|
-
"""
|
116
|
+
"""Handle video file uploads through the Streamlit interface."""
|
117
117
|
self.vid_file_name = ""
|
118
118
|
if self.source == "video":
|
119
119
|
vid_file = self.st.sidebar.file_uploader("Upload Video File", type=["mp4", "mov", "avi", "mkv"])
|
@@ -126,7 +126,7 @@ class Inference:
|
|
126
126
|
self.vid_file_name = 0 # Use webcam index 0
|
127
127
|
|
128
128
|
def configure(self):
|
129
|
-
"""
|
129
|
+
"""Configure the model and load selected classes for inference."""
|
130
130
|
# Add dropdown menu for model selection
|
131
131
|
available_models = [x.replace("yolo", "YOLO") for x in GITHUB_ASSETS_STEMS if x.startswith("yolo11")]
|
132
132
|
if self.model_path: # If user provided the custom model, insert model without suffix as *.pt is added later
|
@@ -146,7 +146,7 @@ class Inference:
|
|
146
146
|
self.selected_ind = list(self.selected_ind)
|
147
147
|
|
148
148
|
def inference(self):
|
149
|
-
"""
|
149
|
+
"""Perform real-time object detection inference on video or webcam feed."""
|
150
150
|
self.web_ui() # Initialize the web interface
|
151
151
|
self.sidebar() # Create the sidebar
|
152
152
|
self.source_upload() # Upload the video source
|
@@ -16,9 +16,16 @@ class TrackZone(BaseSolution):
|
|
16
16
|
|
17
17
|
Attributes:
|
18
18
|
region (np.ndarray): The polygonal region for tracking, represented as a convex hull of points.
|
19
|
+
line_width (int): Width of the lines used for drawing bounding boxes and region boundaries.
|
20
|
+
names (List[str]): List of class names that the model can detect.
|
21
|
+
boxes (List[np.ndarray]): Bounding boxes of tracked objects.
|
22
|
+
track_ids (List[int]): Unique identifiers for each tracked object.
|
23
|
+
clss (List[int]): Class indices of tracked objects.
|
19
24
|
|
20
25
|
Methods:
|
21
26
|
process: Processes each frame of the video, applying region-based tracking.
|
27
|
+
extract_tracks: Extracts tracking information from the input frame.
|
28
|
+
display_output: Displays the processed output.
|
22
29
|
|
23
30
|
Examples:
|
24
31
|
>>> tracker = TrackZone()
|
@@ -29,7 +36,7 @@ class TrackZone(BaseSolution):
|
|
29
36
|
|
30
37
|
def __init__(self, **kwargs):
|
31
38
|
"""
|
32
|
-
|
39
|
+
Initialize the TrackZone class for tracking objects within a defined region in video streams.
|
33
40
|
|
34
41
|
Args:
|
35
42
|
**kwargs (Any): Additional keyword arguments passed to the parent class.
|
@@ -40,7 +47,7 @@ class TrackZone(BaseSolution):
|
|
40
47
|
|
41
48
|
def process(self, im0):
|
42
49
|
"""
|
43
|
-
|
50
|
+
Process the input frame to track objects within a defined region.
|
44
51
|
|
45
52
|
This method initializes the annotator, creates a mask for the specified region, extracts tracks
|
46
53
|
only from the masked area, and updates tracking information. Objects outside the region are ignored.
|
@@ -13,10 +13,10 @@ class VisionEye(BaseSolution):
|
|
13
13
|
mapping vision points, and annotating results with bounding boxes and labels.
|
14
14
|
|
15
15
|
Attributes:
|
16
|
-
vision_point (Tuple[int, int]): Coordinates where vision will view objects and draw tracks
|
16
|
+
vision_point (Tuple[int, int]): Coordinates (x, y) where vision will view objects and draw tracks.
|
17
17
|
|
18
18
|
Methods:
|
19
|
-
process:
|
19
|
+
process: Process the input image to detect objects, annotate them, and apply vision mapping.
|
20
20
|
|
21
21
|
Examples:
|
22
22
|
>>> vision_eye = VisionEye()
|
@@ -27,7 +27,7 @@ class VisionEye(BaseSolution):
|
|
27
27
|
|
28
28
|
def __init__(self, **kwargs):
|
29
29
|
"""
|
30
|
-
|
30
|
+
Initialize the VisionEye class for detecting objects and applying vision mapping.
|
31
31
|
|
32
32
|
Args:
|
33
33
|
**kwargs (Any): Keyword arguments passed to the parent class and for configuring vision_point.
|
@@ -38,7 +38,7 @@ class VisionEye(BaseSolution):
|
|
38
38
|
|
39
39
|
def process(self, im0):
|
40
40
|
"""
|
41
|
-
|
41
|
+
Perform object detection, vision mapping, and annotation on the input image.
|
42
42
|
|
43
43
|
Args:
|
44
44
|
im0 (numpy.ndarray): The input image for detection and annotation.
|
ultralytics/trackers/bot_sort.py
CHANGED
@@ -28,14 +28,14 @@ class BOTrack(STrack):
|
|
28
28
|
covariance (np.ndarray): The covariance matrix of the Kalman filter.
|
29
29
|
|
30
30
|
Methods:
|
31
|
-
update_features
|
32
|
-
predict
|
33
|
-
re_activate
|
34
|
-
update
|
31
|
+
update_features: Update features vector and smooth it using exponential moving average.
|
32
|
+
predict: Predict the mean and covariance using Kalman filter.
|
33
|
+
re_activate: Reactivate a track with updated features and optionally new ID.
|
34
|
+
update: Update the track with new detection and frame ID.
|
35
35
|
tlwh: Property that gets the current position in tlwh format `(top left x, top left y, width, height)`.
|
36
|
-
multi_predict
|
37
|
-
convert_coords
|
38
|
-
tlwh_to_xywh
|
36
|
+
multi_predict: Predict the mean and covariance of multiple object tracks using shared Kalman filter.
|
37
|
+
convert_coords: Convert tlwh bounding box coordinates to xywh format.
|
38
|
+
tlwh_to_xywh: Convert bounding box to xywh format `(center x, center y, width, height)`.
|
39
39
|
|
40
40
|
Examples:
|
41
41
|
Create a BOTrack instance and update its features
|
@@ -87,7 +87,7 @@ class BOTrack(STrack):
|
|
87
87
|
self.smooth_feat /= np.linalg.norm(self.smooth_feat)
|
88
88
|
|
89
89
|
def predict(self):
|
90
|
-
"""
|
90
|
+
"""Predict the object's future state using the Kalman filter to update its mean and covariance."""
|
91
91
|
mean_state = self.mean.copy()
|
92
92
|
if self.state != TrackState.Tracked:
|
93
93
|
mean_state[6] = 0
|
@@ -96,20 +96,20 @@ class BOTrack(STrack):
|
|
96
96
|
self.mean, self.covariance = self.kalman_filter.predict(mean_state, self.covariance)
|
97
97
|
|
98
98
|
def re_activate(self, new_track, frame_id, new_id=False):
|
99
|
-
"""
|
99
|
+
"""Reactivate a track with updated features and optionally assign a new ID."""
|
100
100
|
if new_track.curr_feat is not None:
|
101
101
|
self.update_features(new_track.curr_feat)
|
102
102
|
super().re_activate(new_track, frame_id, new_id)
|
103
103
|
|
104
104
|
def update(self, new_track, frame_id):
|
105
|
-
"""
|
105
|
+
"""Update the track with new detection information and the current frame ID."""
|
106
106
|
if new_track.curr_feat is not None:
|
107
107
|
self.update_features(new_track.curr_feat)
|
108
108
|
super().update(new_track, frame_id)
|
109
109
|
|
110
110
|
@property
|
111
111
|
def tlwh(self):
|
112
|
-
"""
|
112
|
+
"""Return the current bounding box position in `(top left x, top left y, width, height)` format."""
|
113
113
|
if self.mean is None:
|
114
114
|
return self._tlwh.copy()
|
115
115
|
ret = self.mean[:4].copy()
|
@@ -118,7 +118,7 @@ class BOTrack(STrack):
|
|
118
118
|
|
119
119
|
@staticmethod
|
120
120
|
def multi_predict(stracks):
|
121
|
-
"""
|
121
|
+
"""Predict the mean and covariance for multiple object tracks using a shared Kalman filter."""
|
122
122
|
if len(stracks) <= 0:
|
123
123
|
return
|
124
124
|
multi_mean = np.asarray([st.mean.copy() for st in stracks])
|
@@ -133,7 +133,7 @@ class BOTrack(STrack):
|
|
133
133
|
stracks[i].covariance = cov
|
134
134
|
|
135
135
|
def convert_coords(self, tlwh):
|
136
|
-
"""
|
136
|
+
"""Convert tlwh bounding box coordinates to xywh format."""
|
137
137
|
return self.tlwh_to_xywh(tlwh)
|
138
138
|
|
139
139
|
@staticmethod
|
@@ -156,10 +156,11 @@ class BOTSORT(BYTETracker):
|
|
156
156
|
args (Any): Parsed command-line arguments containing tracking parameters.
|
157
157
|
|
158
158
|
Methods:
|
159
|
-
get_kalmanfilter
|
160
|
-
init_track
|
161
|
-
get_dists
|
162
|
-
multi_predict
|
159
|
+
get_kalmanfilter: Return an instance of KalmanFilterXYWH for object tracking.
|
160
|
+
init_track: Initialize track with detections, scores, and classes.
|
161
|
+
get_dists: Get distances between tracks and detections using IoU and (optionally) ReID.
|
162
|
+
multi_predict: Predict and track multiple objects with YOLOv8 model.
|
163
|
+
reset: Reset the BOTSORT tracker to its initial state.
|
163
164
|
|
164
165
|
Examples:
|
165
166
|
Initialize BOTSORT and process detections
|
@@ -173,7 +174,7 @@ class BOTSORT(BYTETracker):
|
|
173
174
|
|
174
175
|
def __init__(self, args, frame_rate=30):
|
175
176
|
"""
|
176
|
-
Initialize
|
177
|
+
Initialize BOTSORT object with ReID module and GMC algorithm.
|
177
178
|
|
178
179
|
Args:
|
179
180
|
args (object): Parsed command-line arguments containing tracking parameters.
|
@@ -195,7 +196,7 @@ class BOTSORT(BYTETracker):
|
|
195
196
|
self.gmc = GMC(method=args.gmc_method)
|
196
197
|
|
197
198
|
def get_kalmanfilter(self):
|
198
|
-
"""
|
199
|
+
"""Return an instance of KalmanFilterXYWH for predicting and updating object states in the tracking process."""
|
199
200
|
return KalmanFilterXYWH()
|
200
201
|
|
201
202
|
def init_track(self, dets, scores, cls, img=None):
|
@@ -209,7 +210,7 @@ class BOTSORT(BYTETracker):
|
|
209
210
|
return [BOTrack(xyxy, s, c) for (xyxy, s, c) in zip(dets, scores, cls)] # detections
|
210
211
|
|
211
212
|
def get_dists(self, tracks, detections):
|
212
|
-
"""
|
213
|
+
"""Calculate distances between tracks and detections using IoU and optionally ReID embeddings."""
|
213
214
|
dists = matching.iou_distance(tracks, detections)
|
214
215
|
dists_mask = dists > self.proximity_thresh
|
215
216
|
|
@@ -224,10 +225,10 @@ class BOTSORT(BYTETracker):
|
|
224
225
|
return dists
|
225
226
|
|
226
227
|
def multi_predict(self, tracks):
|
227
|
-
"""
|
228
|
+
"""Predict the mean and covariance of multiple object tracks using a shared Kalman filter."""
|
228
229
|
BOTrack.multi_predict(tracks)
|
229
230
|
|
230
231
|
def reset(self):
|
231
|
-
"""
|
232
|
+
"""Reset the BOTSORT tracker to its initial state, clearing all tracked objects and internal states."""
|
232
233
|
super().reset()
|
233
234
|
self.gmc.reset_params()
|
@@ -17,7 +17,7 @@ class STrack(BaseTrack):
|
|
17
17
|
and predictions based on Kalman filter.
|
18
18
|
|
19
19
|
Attributes:
|
20
|
-
shared_kalman (KalmanFilterXYAH): Shared Kalman filter
|
20
|
+
shared_kalman (KalmanFilterXYAH): Shared Kalman filter used across all STrack instances for prediction.
|
21
21
|
_tlwh (np.ndarray): Private attribute to store top-left corner coordinates and width and height of bounding box.
|
22
22
|
kalman_filter (KalmanFilterXYAH): Instance of Kalman filter used for this particular object track.
|
23
23
|
mean (np.ndarray): Mean state estimate vector.
|
@@ -236,9 +236,9 @@ class BYTETracker:
|
|
236
236
|
"""
|
237
237
|
BYTETracker: A tracking algorithm built on top of YOLOv8 for object detection and tracking.
|
238
238
|
|
239
|
-
|
240
|
-
It maintains the state of tracked, lost, and removed tracks over frames, utilizes Kalman filtering for
|
241
|
-
the new object locations, and performs data association.
|
239
|
+
This class encapsulates the functionality for initializing, updating, and managing the tracks for detected objects in a
|
240
|
+
video sequence. It maintains the state of tracked, lost, and removed tracks over frames, utilizes Kalman filtering for
|
241
|
+
predicting the new object locations, and performs data association.
|
242
242
|
|
243
243
|
Attributes:
|
244
244
|
tracked_stracks (List[STrack]): List of successfully activated tracks.
|
ultralytics/trackers/track.py
CHANGED
@@ -25,6 +25,7 @@ def on_predict_start(predictor: object, persist: bool = False) -> None:
|
|
25
25
|
|
26
26
|
Raises:
|
27
27
|
AssertionError: If the tracker_type is not 'bytetrack' or 'botsort'.
|
28
|
+
ValueError: If the task is 'classify' as classification doesn't support tracking.
|
28
29
|
|
29
30
|
Examples:
|
30
31
|
Initialize trackers for a predictor object:
|
@@ -47,7 +48,7 @@ def on_predict_start(predictor: object, persist: bool = False) -> None:
|
|
47
48
|
for _ in range(predictor.dataset.bs):
|
48
49
|
tracker = TRACKER_MAP[cfg.tracker_type](args=cfg, frame_rate=30)
|
49
50
|
trackers.append(tracker)
|
50
|
-
if predictor.dataset.mode != "stream": # only need one tracker for other modes
|
51
|
+
if predictor.dataset.mode != "stream": # only need one tracker for other modes
|
51
52
|
break
|
52
53
|
predictor.trackers = trackers
|
53
54
|
predictor.vid_path = [None] * predictor.dataset.bs # for determining when to reset tracker on new video
|