ultralytics 8.3.88__py3-none-any.whl → 8.3.90__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.
Files changed (155) hide show
  1. tests/conftest.py +2 -2
  2. tests/test_cli.py +13 -11
  3. tests/test_cuda.py +10 -1
  4. tests/test_integrations.py +1 -5
  5. tests/test_python.py +16 -16
  6. tests/test_solutions.py +9 -9
  7. ultralytics/__init__.py +1 -1
  8. ultralytics/cfg/__init__.py +3 -1
  9. ultralytics/cfg/models/11/yolo11-cls.yaml +5 -5
  10. ultralytics/cfg/models/11/yolo11-obb.yaml +5 -5
  11. ultralytics/cfg/models/11/yolo11-pose.yaml +5 -5
  12. ultralytics/cfg/models/11/yolo11-seg.yaml +5 -5
  13. ultralytics/cfg/models/11/yolo11.yaml +5 -5
  14. ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +5 -5
  15. ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +5 -5
  16. ultralytics/cfg/models/v8/yolov8-ghost.yaml +5 -5
  17. ultralytics/cfg/models/v8/yolov8-obb.yaml +5 -5
  18. ultralytics/cfg/models/v8/yolov8-p6.yaml +5 -5
  19. ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +5 -5
  20. ultralytics/cfg/models/v8/yolov8-world.yaml +5 -5
  21. ultralytics/cfg/models/v8/yolov8-worldv2.yaml +5 -5
  22. ultralytics/cfg/models/v8/yolov8.yaml +5 -5
  23. ultralytics/cfg/models/v9/yolov9c-seg.yaml +1 -1
  24. ultralytics/cfg/models/v9/yolov9c.yaml +1 -1
  25. ultralytics/cfg/models/v9/yolov9e-seg.yaml +1 -1
  26. ultralytics/cfg/models/v9/yolov9e.yaml +1 -1
  27. ultralytics/cfg/models/v9/yolov9m.yaml +1 -1
  28. ultralytics/cfg/models/v9/yolov9s.yaml +1 -1
  29. ultralytics/cfg/models/v9/yolov9t.yaml +1 -1
  30. ultralytics/data/annotator.py +9 -14
  31. ultralytics/data/base.py +125 -39
  32. ultralytics/data/build.py +63 -24
  33. ultralytics/data/converter.py +34 -33
  34. ultralytics/data/dataset.py +207 -53
  35. ultralytics/data/loaders.py +1 -0
  36. ultralytics/data/split_dota.py +39 -12
  37. ultralytics/data/utils.py +33 -47
  38. ultralytics/engine/exporter.py +19 -17
  39. ultralytics/engine/model.py +69 -90
  40. ultralytics/engine/predictor.py +106 -21
  41. ultralytics/engine/trainer.py +32 -23
  42. ultralytics/engine/tuner.py +31 -38
  43. ultralytics/engine/validator.py +75 -41
  44. ultralytics/hub/__init__.py +21 -26
  45. ultralytics/hub/auth.py +9 -12
  46. ultralytics/hub/session.py +76 -21
  47. ultralytics/hub/utils.py +19 -17
  48. ultralytics/models/fastsam/model.py +23 -17
  49. ultralytics/models/fastsam/predict.py +36 -16
  50. ultralytics/models/fastsam/utils.py +5 -5
  51. ultralytics/models/fastsam/val.py +6 -6
  52. ultralytics/models/nas/model.py +29 -24
  53. ultralytics/models/nas/predict.py +14 -11
  54. ultralytics/models/nas/val.py +11 -13
  55. ultralytics/models/rtdetr/model.py +20 -11
  56. ultralytics/models/rtdetr/predict.py +21 -21
  57. ultralytics/models/rtdetr/train.py +25 -24
  58. ultralytics/models/rtdetr/val.py +47 -14
  59. ultralytics/models/sam/__init__.py +1 -1
  60. ultralytics/models/sam/amg.py +50 -4
  61. ultralytics/models/sam/model.py +8 -14
  62. ultralytics/models/sam/modules/decoders.py +18 -21
  63. ultralytics/models/sam/modules/encoders.py +25 -46
  64. ultralytics/models/sam/modules/memory_attention.py +19 -15
  65. ultralytics/models/sam/modules/sam.py +18 -25
  66. ultralytics/models/sam/modules/tiny_encoder.py +19 -29
  67. ultralytics/models/sam/modules/transformer.py +35 -57
  68. ultralytics/models/sam/modules/utils.py +15 -15
  69. ultralytics/models/sam/predict.py +0 -3
  70. ultralytics/models/utils/loss.py +87 -36
  71. ultralytics/models/utils/ops.py +26 -31
  72. ultralytics/models/yolo/classify/predict.py +30 -12
  73. ultralytics/models/yolo/classify/train.py +83 -19
  74. ultralytics/models/yolo/classify/val.py +45 -23
  75. ultralytics/models/yolo/detect/predict.py +29 -19
  76. ultralytics/models/yolo/detect/train.py +90 -23
  77. ultralytics/models/yolo/detect/val.py +150 -29
  78. ultralytics/models/yolo/model.py +1 -2
  79. ultralytics/models/yolo/obb/predict.py +18 -13
  80. ultralytics/models/yolo/obb/train.py +12 -8
  81. ultralytics/models/yolo/obb/val.py +35 -22
  82. ultralytics/models/yolo/pose/predict.py +28 -15
  83. ultralytics/models/yolo/pose/train.py +21 -8
  84. ultralytics/models/yolo/pose/val.py +51 -31
  85. ultralytics/models/yolo/segment/predict.py +27 -16
  86. ultralytics/models/yolo/segment/train.py +11 -8
  87. ultralytics/models/yolo/segment/val.py +110 -29
  88. ultralytics/models/yolo/world/train.py +43 -16
  89. ultralytics/models/yolo/world/train_world.py +61 -36
  90. ultralytics/nn/autobackend.py +28 -14
  91. ultralytics/nn/modules/__init__.py +12 -12
  92. ultralytics/nn/modules/activation.py +12 -3
  93. ultralytics/nn/modules/block.py +587 -84
  94. ultralytics/nn/modules/conv.py +418 -54
  95. ultralytics/nn/modules/head.py +3 -4
  96. ultralytics/nn/modules/transformer.py +320 -34
  97. ultralytics/nn/modules/utils.py +17 -3
  98. ultralytics/nn/tasks.py +226 -79
  99. ultralytics/solutions/ai_gym.py +2 -2
  100. ultralytics/solutions/analytics.py +4 -4
  101. ultralytics/solutions/heatmap.py +4 -4
  102. ultralytics/solutions/instance_segmentation.py +10 -4
  103. ultralytics/solutions/object_blurrer.py +2 -2
  104. ultralytics/solutions/object_counter.py +2 -2
  105. ultralytics/solutions/object_cropper.py +2 -2
  106. ultralytics/solutions/parking_management.py +9 -9
  107. ultralytics/solutions/queue_management.py +1 -1
  108. ultralytics/solutions/region_counter.py +2 -2
  109. ultralytics/solutions/security_alarm.py +7 -7
  110. ultralytics/solutions/solutions.py +7 -4
  111. ultralytics/solutions/speed_estimation.py +2 -2
  112. ultralytics/solutions/streamlit_inference.py +6 -6
  113. ultralytics/solutions/trackzone.py +9 -2
  114. ultralytics/solutions/vision_eye.py +4 -4
  115. ultralytics/trackers/basetrack.py +1 -1
  116. ultralytics/trackers/bot_sort.py +23 -22
  117. ultralytics/trackers/byte_tracker.py +4 -4
  118. ultralytics/trackers/track.py +2 -1
  119. ultralytics/trackers/utils/gmc.py +26 -27
  120. ultralytics/trackers/utils/kalman_filter.py +31 -29
  121. ultralytics/trackers/utils/matching.py +7 -7
  122. ultralytics/utils/__init__.py +37 -35
  123. ultralytics/utils/autobatch.py +5 -5
  124. ultralytics/utils/benchmarks.py +111 -18
  125. ultralytics/utils/callbacks/base.py +3 -3
  126. ultralytics/utils/callbacks/clearml.py +11 -11
  127. ultralytics/utils/callbacks/comet.py +35 -22
  128. ultralytics/utils/callbacks/dvc.py +11 -10
  129. ultralytics/utils/callbacks/hub.py +8 -8
  130. ultralytics/utils/callbacks/mlflow.py +1 -1
  131. ultralytics/utils/callbacks/neptune.py +12 -10
  132. ultralytics/utils/callbacks/raytune.py +1 -1
  133. ultralytics/utils/callbacks/tensorboard.py +6 -6
  134. ultralytics/utils/callbacks/wb.py +16 -16
  135. ultralytics/utils/checks.py +139 -68
  136. ultralytics/utils/dist.py +15 -2
  137. ultralytics/utils/downloads.py +37 -56
  138. ultralytics/utils/files.py +12 -13
  139. ultralytics/utils/instance.py +117 -52
  140. ultralytics/utils/loss.py +28 -33
  141. ultralytics/utils/metrics.py +246 -181
  142. ultralytics/utils/ops.py +65 -61
  143. ultralytics/utils/patches.py +8 -6
  144. ultralytics/utils/plotting.py +72 -59
  145. ultralytics/utils/tal.py +88 -57
  146. ultralytics/utils/torch_utils.py +202 -64
  147. ultralytics/utils/triton.py +13 -3
  148. ultralytics/utils/tuner.py +13 -25
  149. {ultralytics-8.3.88.dist-info → ultralytics-8.3.90.dist-info}/METADATA +2 -2
  150. ultralytics-8.3.90.dist-info/RECORD +250 -0
  151. ultralytics-8.3.88.dist-info/RECORD +0 -250
  152. {ultralytics-8.3.88.dist-info → ultralytics-8.3.90.dist-info}/LICENSE +0 -0
  153. {ultralytics-8.3.88.dist-info → ultralytics-8.3.90.dist-info}/WHEEL +0 -0
  154. {ultralytics-8.3.88.dist-info → ultralytics-8.3.90.dist-info}/entry_points.txt +0 -0
  155. {ultralytics-8.3.88.dist-info → ultralytics-8.3.90.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
3
  from ultralytics.solutions.solutions import BaseSolution, SolutionAnnotator, SolutionResults
4
4
  from ultralytics.utils.plotting import colors
@@ -13,9 +13,15 @@ class InstanceSegmentation(BaseSolution):
13
13
 
14
14
  Attributes:
15
15
  model (str): The segmentation model to use for inference.
16
+ line_width (int): Width of the bounding box and text lines.
17
+ names (Dict[int, str]): Dictionary mapping class indices to class names.
18
+ clss (List[int]): List of detected class indices.
19
+ track_ids (List[int]): List of track IDs for detected instances.
20
+ masks (List[numpy.ndarray]): List of segmentation masks for detected instances.
16
21
 
17
22
  Methods:
18
- process: Processes the input image to perform instance segmentation and annotate results.
23
+ process: Process the input image to perform instance segmentation and annotate results.
24
+ extract_tracks: Extract tracks including bounding boxes, classes, and masks from model predictions.
19
25
 
20
26
  Examples:
21
27
  >>> segmenter = InstanceSegmentation()
@@ -26,7 +32,7 @@ class InstanceSegmentation(BaseSolution):
26
32
 
27
33
  def __init__(self, **kwargs):
28
34
  """
29
- Initializes the InstanceSegmentation class for detecting and annotating segmented instances.
35
+ Initialize the InstanceSegmentation class for detecting and annotating segmented instances.
30
36
 
31
37
  Args:
32
38
  **kwargs (Any): Keyword arguments passed to the BaseSolution parent class.
@@ -37,7 +43,7 @@ class InstanceSegmentation(BaseSolution):
37
43
 
38
44
  def process(self, im0):
39
45
  """
40
- Performs instance segmentation on the input image and annotates the results.
46
+ Perform instance segmentation on the input image and annotate the results.
41
47
 
42
48
  Args:
43
49
  im0 (numpy.ndarray): The input image for segmentation.
@@ -34,7 +34,7 @@ class ObjectBlurrer(BaseSolution):
34
34
 
35
35
  def __init__(self, **kwargs):
36
36
  """
37
- Initializes the ObjectBlurrer class for applying a blur effect to objects detected in video streams or images.
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
- Applies a blurring effect to detected objects in the input image.
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
- Displays object counts on the input image or frame.
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
- Processes input data (frames or object tracks) and updates object counts.
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
- Initializes the ObjectCropper class for cropping objects from detected bounding boxes.
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
- Crops detected objects from the input image and saves them as separate images.
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
- """Initializes the ParkingPtsSelection class, setting up UI and properties for parking zone point selection."""
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
- """Uploads and displays an image on the canvas, resizing it to fit within specified dimensions."""
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
- """Handles mouse clicks to add points for bounding boxes on the canvas."""
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
- """Draws a bounding box on the canvas using the provided coordinates."""
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
- """Removes the last bounding box from the list and redraws the canvas."""
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
- """Redraws the canvas with the image and all bounding boxes."""
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
- """Saves the selected parking zone points to a JSON file with scaled coordinates."""
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
- """Initializes the parking management system with a YOLO model and visualization settings."""
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
- Processes the input image for parking lot management and visualization.
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
- Processes the queue management for a single frame of video.
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
- Adds a new region to the counting list based on the provided template with specific attributes.
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
- Processes the input frame to detect and count objects within each defined region.
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: Sets up email server authentication for sending alerts.
25
- send_email: Sends an email notification with details and an image attachment.
26
- process: Monitors the frame, processes detections, and triggers alerts if thresholds are crossed.
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
- Initializes the SecurityAlarm class with parameters for real-time object monitoring.
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
- Authenticates the email server for sending alert notifications.
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
- Sends an email notification with an image attachment indicating the number of objects detected.
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
- Monitors the frame, processes object detections, and triggers alerts if thresholds are exceeded.
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"], verbose=self.CFG["verbose"])
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
- return self.process(*args, **kwargs) # Call the subclass-specific process method
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
- Initializes the SpeedEstimator object with speed estimation parameters and data structures.
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
- Processes an input frame to estimate object speeds based on tracking data.
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 (Union[str, int]): Name of the uploaded video file or webcam index.
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
- Initializes the Inference class, checking Streamlit requirements and setting up the model path.
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
- """Configures the Streamlit sidebar for model and inference settings."""
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
- """Handles video file uploads through the Streamlit interface."""
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
- """Configures the model and loads selected classes for inference."""
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
- """Performs real-time object detection inference on video or webcam feed."""
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
- Initializes the TrackZone class for tracking objects within a defined region in video streams.
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
- Processes the input frame to track objects within a defined region.
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, default is (30, 30).
16
+ vision_point (Tuple[int, int]): Coordinates (x, y) where vision will view objects and draw tracks.
17
17
 
18
18
  Methods:
19
- process: Processes the input image to detect objects, annotate them, and apply vision mapping.
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
- Initializes the VisionEye class for detecting objects and applying vision mapping.
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
- Performs object detection, vision mapping, and annotation on the input image.
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.
@@ -67,7 +67,7 @@ class BaseTrack:
67
67
 
68
68
  def __init__(self):
69
69
  """
70
- Initializes a new track with a unique ID and foundational tracking attributes.
70
+ Initialize a new track with a unique ID and foundational tracking attributes.
71
71
 
72
72
  Examples:
73
73
  Initialize a new track
@@ -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(feat): Update features vector and smooth it using exponential moving average.
32
- predict(): Predicts the mean and covariance using Kalman filter.
33
- re_activate(new_track, frame_id, new_id): Reactivates a track with updated features and optionally new ID.
34
- update(new_track, frame_id): Update the YOLOv8 instance with new track and frame ID.
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(stracks): Predicts the mean and covariance of multiple object tracks using shared Kalman filter.
37
- convert_coords(tlwh): Converts tlwh bounding box coordinates to xywh format.
38
- tlwh_to_xywh(tlwh): Convert bounding box to xywh format `(center x, center y, width, height)`.
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
- """Predicts the object's future state using the Kalman filter to update its mean and covariance."""
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
- """Reactivates a track with updated features and optionally assigns a new ID."""
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
- """Updates the YOLOv8 instance with new track information and the current frame ID."""
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
- """Returns the current bounding box position in `(top left x, top left y, width, height)` format."""
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
- """Predicts the mean and covariance for multiple object tracks using a shared Kalman filter."""
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
- """Converts tlwh bounding box coordinates to xywh format."""
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(): Returns an instance of KalmanFilterXYWH for object tracking.
160
- init_track(dets, scores, cls, img): Initialize track with detections, scores, and classes.
161
- get_dists(tracks, detections): Get distances between tracks and detections using IoU and (optionally) ReID.
162
- multi_predict(tracks): Predict and track multiple objects with YOLOv8 model.
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 YOLOv8 object with ReID module and GMC algorithm.
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
- """Returns an instance of KalmanFilterXYWH for predicting and updating object states in the tracking process."""
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
- """Calculates distances between tracks and detections using IoU and optionally ReID embeddings."""
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
- """Predicts the mean and covariance of multiple object tracks using a shared Kalman filter."""
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
- """Resets the BOTSORT tracker to its initial state, clearing all tracked objects and internal states."""
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 that is used across all STrack instances for prediction.
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
- Responsible for initializing, updating, and managing the tracks for detected objects in a video sequence.
240
- It maintains the state of tracked, lost, and removed tracks over frames, utilizes Kalman filtering for predicting
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.
@@ -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