ultralytics 8.3.3__py3-none-any.whl → 8.3.5__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.

Potentially problematic release.


This version of ultralytics might be problematic. Click here for more details.

tests/test_solutions.py CHANGED
@@ -19,7 +19,7 @@ def test_major_solutions():
19
19
  cap = cv2.VideoCapture("solutions_ci_demo.mp4")
20
20
  assert cap.isOpened(), "Error reading video file"
21
21
  region_points = [(20, 400), (1080, 404), (1080, 360), (20, 360)]
22
- counter = solutions.ObjectCounter(reg_pts=region_points, names=names, view_img=False)
22
+ # counter = solutions.ObjectCounter(reg_pts=region_points, names=names, view_img=False)
23
23
  heatmap = solutions.Heatmap(colormap=cv2.COLORMAP_PARULA, names=names, view_img=False)
24
24
  speed = solutions.SpeedEstimator(reg_pts=region_points, names=names, view_img=False)
25
25
  queue = solutions.QueueManager(names=names, reg_pts=region_points, view_img=False)
@@ -29,7 +29,7 @@ def test_major_solutions():
29
29
  break
30
30
  original_im0 = im0.copy()
31
31
  tracks = model.track(im0, persist=True, show=False)
32
- _ = counter.start_counting(original_im0.copy(), tracks)
32
+ # _ = counter.start_counting(original_im0.copy(), tracks)
33
33
  _ = heatmap.generate_heatmap(original_im0.copy(), tracks)
34
34
  _ = speed.estimate_speed(original_im0.copy(), tracks)
35
35
  _ = queue.process_queue(original_im0.copy(), tracks)
ultralytics/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
- __version__ = "8.3.3"
3
+ __version__ = "8.3.5"
4
4
 
5
5
  import os
6
6
 
@@ -1,7 +1,7 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
  # Default training settings and hyperparameters for medium-augmentation COCO training
3
3
 
4
- task: detect # (str) YOLO task, i.e. detect, segment, classify, pose
4
+ task: detect # (str) YOLO task, i.e. detect, segment, classify, pose, obb
5
5
  mode: train # (str) YOLO mode, i.e. train, val, predict, export, track, benchmark
6
6
 
7
7
  # Train settings -------------------------------------------------------------------------------------------------------
@@ -0,0 +1,12 @@
1
+ # Ultralytics YOLO 🚀, AGPL-3.0 license
2
+
3
+ # Configuration for Ultralytics Solutions
4
+
5
+ model: "yolo11n.pt" # The Ultralytics YOLO11 model to be used (e.g., yolo11n.pt for YOLO11 nano version)
6
+
7
+ region: # Object counting, queue or speed estimation region points
8
+ line_width: 2 # Thickness of the lines used to draw regions on the image/video frames
9
+ show: True # Flag to control whether to display output image or not
10
+ show_in: True # Flag to display objects moving *into* the defined region
11
+ show_out: True # Flag to display objects moving *out of* the defined region
12
+ classes: # To count specific classes
ultralytics/data/base.py CHANGED
@@ -90,13 +90,15 @@ class BaseDataset(Dataset):
90
90
  self.ims, self.im_hw0, self.im_hw = [None] * self.ni, [None] * self.ni, [None] * self.ni
91
91
  self.npy_files = [Path(f).with_suffix(".npy") for f in self.im_files]
92
92
  self.cache = cache.lower() if isinstance(cache, str) else "ram" if cache is True else None
93
- if (self.cache == "ram" and self.check_cache_ram()) or self.cache == "disk":
94
- if self.cache == "ram" and hyp.deterministic:
93
+ if self.cache == "ram" and self.check_cache_ram():
94
+ if hyp.deterministic:
95
95
  LOGGER.warning(
96
96
  "WARNING ⚠️ cache='ram' may produce non-deterministic training results. "
97
97
  "Consider cache='disk' as a deterministic alternative if your disk space allows."
98
98
  )
99
99
  self.cache_images()
100
+ elif self.cache == "disk" and self.check_cache_disk():
101
+ self.cache_images()
100
102
 
101
103
  # Transforms
102
104
  self.transforms = self.build_transforms(hyp=hyp)
@@ -206,25 +208,55 @@ class BaseDataset(Dataset):
206
208
  if not f.exists():
207
209
  np.save(f.as_posix(), cv2.imread(self.im_files[i]), allow_pickle=False)
208
210
 
211
+ def check_cache_disk(self, safety_margin=0.5):
212
+ """Check image caching requirements vs available disk space."""
213
+ import shutil
214
+
215
+ b, gb = 0, 1 << 30 # bytes of cached images, bytes per gigabytes
216
+ n = min(self.ni, 30) # extrapolate from 30 random images
217
+ for _ in range(n):
218
+ im_file = random.choice(self.im_files)
219
+ im = cv2.imread(im_file)
220
+ if im is None:
221
+ continue
222
+ b += im.nbytes
223
+ if not os.access(Path(im_file).parent, os.W_OK):
224
+ self.cache = None
225
+ LOGGER.info(f"{self.prefix}Skipping caching images to disk, directory not writeable ⚠️")
226
+ return False
227
+ disk_required = b * self.ni / n * (1 + safety_margin) # bytes required to cache dataset to disk
228
+ total, used, free = shutil.disk_usage(Path(self.im_files[0]).parent)
229
+ if disk_required > free:
230
+ self.cache = None
231
+ LOGGER.info(
232
+ f"{self.prefix}{disk_required / gb:.1f}GB disk space required, "
233
+ f"with {int(safety_margin * 100)}% safety margin but only "
234
+ f"{free / gb:.1f}/{total / gb:.1f}GB free, not caching images to disk ⚠️"
235
+ )
236
+ return False
237
+ return True
238
+
209
239
  def check_cache_ram(self, safety_margin=0.5):
210
240
  """Check image caching requirements vs available memory."""
211
241
  b, gb = 0, 1 << 30 # bytes of cached images, bytes per gigabytes
212
242
  n = min(self.ni, 30) # extrapolate from 30 random images
213
243
  for _ in range(n):
214
244
  im = cv2.imread(random.choice(self.im_files)) # sample image
245
+ if im is None:
246
+ continue
215
247
  ratio = self.imgsz / max(im.shape[0], im.shape[1]) # max(h, w) # ratio
216
248
  b += im.nbytes * ratio**2
217
249
  mem_required = b * self.ni / n * (1 + safety_margin) # GB required to cache dataset into RAM
218
250
  mem = psutil.virtual_memory()
219
- success = mem_required < mem.available # to cache or not to cache, that is the question
220
- if not success:
251
+ if mem_required > mem.available:
221
252
  self.cache = None
222
253
  LOGGER.info(
223
254
  f"{self.prefix}{mem_required / gb:.1f}GB RAM required to cache images "
224
255
  f"with {int(safety_margin * 100)}% safety margin but only "
225
256
  f"{mem.available / gb:.1f}/{mem.total / gb:.1f}GB available, not caching images ⚠️"
226
257
  )
227
- return success
258
+ return False
259
+ return True
228
260
 
229
261
  def set_rectangle(self):
230
262
  """Sets the shape of bounding boxes for YOLO detections as rectangles."""
ultralytics/data/utils.py CHANGED
@@ -216,7 +216,7 @@ def polygons2masks_overlap(imgsz, segments, downsample_ratio=1):
216
216
  ms = []
217
217
  for si in range(len(segments)):
218
218
  mask = polygon2mask(imgsz, [segments[si].reshape(-1)], downsample_ratio=downsample_ratio, color=1)
219
- ms.append(mask)
219
+ ms.append(mask.astype(masks.dtype))
220
220
  areas.append(mask.sum())
221
221
  areas = np.asarray(areas)
222
222
  index = np.argsort(-areas)
@@ -452,12 +452,12 @@ class HUBDatasetStats:
452
452
  path = Path(path).resolve()
453
453
  LOGGER.info(f"Starting HUB dataset checks for {path}....")
454
454
 
455
- self.task = task # detect, segment, pose, classify
455
+ self.task = task # detect, segment, pose, classify, obb
456
456
  if self.task == "classify":
457
457
  unzip_dir = unzip_file(path)
458
458
  data = check_cls_dataset(unzip_dir)
459
459
  data["path"] = unzip_dir
460
- else: # detect, segment, pose
460
+ else: # detect, segment, pose, obb
461
461
  _, data_dir, yaml_path = self._unzip(Path(path))
462
462
  try:
463
463
  # Load YAML with checks
@@ -178,6 +178,16 @@ class Exporter:
178
178
  if fmt in {"mlmodel", "mlpackage", "mlprogram", "apple", "ios", "coreml"}: # 'coreml' aliases
179
179
  fmt = "coreml"
180
180
  fmts = tuple(export_formats()["Argument"][1:]) # available export formats
181
+ if fmt not in fmts:
182
+ import difflib
183
+
184
+ # Get the closest match if format is invalid
185
+ matches = difflib.get_close_matches(fmt, fmts, n=1, cutoff=0.6) # 60% similarity required to match
186
+ if matches:
187
+ LOGGER.warning(f"WARNING ⚠️ Invalid export format='{fmt}', updating to format='{matches[0]}'")
188
+ fmt = matches[0]
189
+ else:
190
+ raise ValueError(f"Invalid export format='{fmt}'. Valid formats are {fmts}")
181
191
  flags = [x == fmt for x in fmts]
182
192
  if sum(flags) != 1:
183
193
  raise ValueError(f"Invalid export format='{fmt}'. Valid formats are {fmts}")
@@ -12,7 +12,7 @@ import os
12
12
  import subprocess
13
13
  import time
14
14
  import warnings
15
- from copy import deepcopy
15
+ from copy import copy, deepcopy
16
16
  from datetime import datetime, timedelta
17
17
  from pathlib import Path
18
18
 
@@ -749,7 +749,7 @@ class BaseTrainer:
749
749
  self.train_loader.dataset.mosaic = False
750
750
  if hasattr(self.train_loader.dataset, "close_mosaic"):
751
751
  LOGGER.info("Closing dataloader mosaic")
752
- self.train_loader.dataset.close_mosaic(hyp=self.args)
752
+ self.train_loader.dataset.close_mosaic(hyp=copy(self.args))
753
753
 
754
754
  def build_optimizer(self, model, name="auto", lr=0.001, momentum=0.9, decay=1e-5, iterations=1e5):
755
755
  """
@@ -119,6 +119,8 @@ class BaseValidator:
119
119
  self.args.plots &= trainer.stopper.possible_stop or (trainer.epoch == trainer.epochs - 1)
120
120
  model.eval()
121
121
  else:
122
+ if str(self.args.model).endswith(".yaml"):
123
+ LOGGER.warning("WARNING ⚠️ validating an untrained model YAML will result in 0 mAP.")
122
124
  callbacks.add_integration_callbacks(self)
123
125
  model = AutoBackend(
124
126
  weights=model or self.args.model,
@@ -196,6 +196,7 @@ class Predictor(BasePredictor):
196
196
  bboxes = self.prompts.pop("bboxes", bboxes)
197
197
  points = self.prompts.pop("points", points)
198
198
  masks = self.prompts.pop("masks", masks)
199
+ labels = self.prompts.pop("labels", labels)
199
200
 
200
201
  if all(i is None for i in [bboxes, points, masks]):
201
202
  return self.generate(im, *args, **kwargs)
@@ -19,10 +19,7 @@ class Heatmap:
19
19
  def __init__(
20
20
  self,
21
21
  names,
22
- imw=0,
23
- imh=0,
24
22
  colormap=cv2.COLORMAP_JET,
25
- heatmap_alpha=0.5,
26
23
  view_img=False,
27
24
  view_in_counts=True,
28
25
  view_out_counts=True,
@@ -33,7 +30,6 @@ class Heatmap:
33
30
  region_thickness=5,
34
31
  line_dist_thresh=15,
35
32
  line_thickness=2,
36
- decay_factor=0.99,
37
33
  shape="circle",
38
34
  ):
39
35
  """Initializes the heatmap class with default values for Visual, Image, track, count and heatmap parameters."""
@@ -46,8 +42,6 @@ class Heatmap:
46
42
  self.names = names # Classes names
47
43
 
48
44
  # Image information
49
- self.imw = imw
50
- self.imh = imh
51
45
  self.im0 = None
52
46
  self.tf = line_thickness
53
47
  self.view_in_counts = view_in_counts
@@ -56,7 +50,6 @@ class Heatmap:
56
50
  # Heatmap colormap and heatmap np array
57
51
  self.colormap = colormap
58
52
  self.heatmap = None
59
- self.heatmap_alpha = heatmap_alpha
60
53
 
61
54
  # Predict/track information
62
55
  self.boxes = []
@@ -79,9 +72,6 @@ class Heatmap:
79
72
  self.count_bg_color = count_bg_color
80
73
  self.cls_txtdisplay_gap = 50
81
74
 
82
- # Decay factor
83
- self.decay_factor = decay_factor
84
-
85
75
  # Check if environment supports imshow
86
76
  self.env_check = check_imshow(warn=True)
87
77
 
@@ -133,7 +123,7 @@ class Heatmap:
133
123
  self.heatmap = np.zeros((int(self.im0.shape[0]), int(self.im0.shape[1])), dtype=np.float32)
134
124
  self.initialized = True
135
125
 
136
- self.heatmap *= self.decay_factor # decay factor
126
+ self.heatmap *= 0.99 # decay factor
137
127
 
138
128
  self.extract_results(tracks)
139
129
  self.annotator = Annotator(self.im0, self.tf, None)
@@ -239,7 +229,7 @@ class Heatmap:
239
229
  # Normalize, apply colormap to heatmap and combine with original image
240
230
  heatmap_normalized = cv2.normalize(self.heatmap, None, 0, 255, cv2.NORM_MINMAX)
241
231
  heatmap_colored = cv2.applyColorMap(heatmap_normalized.astype(np.uint8), self.colormap)
242
- self.im0 = cv2.addWeighted(self.im0, 1 - self.heatmap_alpha, heatmap_colored, self.heatmap_alpha, 0)
232
+ self.im0 = cv2.addWeighted(self.im0, 0.5, heatmap_colored, 0.5, 0)
243
233
 
244
234
  if self.env_check and self.view_img:
245
235
  self.display_frames()
@@ -1,243 +1,129 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
- from collections import defaultdict
3
+ from shapely.geometry import LineString, Point
4
4
 
5
- import cv2
6
-
7
- from ultralytics.utils.checks import check_imshow, check_requirements
5
+ from ultralytics.solutions.solutions import BaseSolution # Import a parent class
8
6
  from ultralytics.utils.plotting import Annotator, colors
9
7
 
10
- check_requirements("shapely>=2.0.0")
11
8
 
12
- from shapely.geometry import LineString, Point, Polygon
9
+ class ObjectCounter(BaseSolution):
10
+ """A class to manage the counting of objects in a real-time video stream based on their tracks."""
13
11
 
12
+ def __init__(self, **kwargs):
13
+ """Initialization function for Count class, a child class of BaseSolution class, can be used for counting the
14
+ objects.
15
+ """
16
+ super().__init__(**kwargs)
14
17
 
15
- class ObjectCounter:
16
- """A class to manage the counting of objects in a real-time video stream based on their tracks."""
18
+ self.in_count = 0 # Counter for objects moving inward
19
+ self.out_count = 0 # Counter for objects moving outward
20
+ self.counted_ids = [] # List of IDs of objects that have been counted
21
+ self.classwise_counts = {} # Dictionary for counts, categorized by object class
17
22
 
18
- def __init__(
19
- self,
20
- names,
21
- reg_pts=None,
22
- line_thickness=2,
23
- view_img=False,
24
- view_in_counts=True,
25
- view_out_counts=True,
26
- draw_tracks=False,
27
- ):
23
+ self.initialize_region() # Setup region and counting areas
24
+
25
+ self.show_in = self.CFG["show_in"]
26
+ self.show_out = self.CFG["show_out"]
27
+
28
+ def count_objects(self, track_line, box, track_id, prev_position, cls):
28
29
  """
29
- Initializes the ObjectCounter with various tracking and counting parameters.
30
+ Helper function to count objects within a polygonal region.
30
31
 
31
32
  Args:
32
- names (dict): Dictionary of class names.
33
- reg_pts (list): List of points defining the counting region.
34
- line_thickness (int): Line thickness for bounding boxes.
35
- view_img (bool): Flag to control whether to display the video stream.
36
- view_in_counts (bool): Flag to control whether to display the in counts on the video stream.
37
- view_out_counts (bool): Flag to control whether to display the out counts on the video stream.
38
- draw_tracks (bool): Flag to control whether to draw the object tracks.
33
+ track_line (dict): last 30 frame track record
34
+ box (list): Bounding box data for specific track in current frame
35
+ track_id (int): track ID of the object
36
+ prev_position (tuple): last frame position coordinates of the track
37
+ cls (int): Class index for classwise count updates
39
38
  """
40
- # Mouse events
41
- self.is_drawing = False
42
- self.selected_point = None
43
-
44
- # Region & Line Information
45
- self.reg_pts = [(20, 400), (1260, 400)] if reg_pts is None else reg_pts
46
- self.counting_region = None
47
-
48
- # Image and annotation Information
49
- self.im0 = None
50
- self.tf = line_thickness
51
- self.view_img = view_img
52
- self.view_in_counts = view_in_counts
53
- self.view_out_counts = view_out_counts
54
-
55
- self.names = names # Classes names
56
- self.window_name = "Ultralytics YOLOv8 Object Counter"
57
-
58
- # Object counting Information
59
- self.in_counts = 0
60
- self.out_counts = 0
61
- self.count_ids = []
62
- self.class_wise_count = {}
63
-
64
- # Tracks info
65
- self.track_history = defaultdict(list)
66
- self.draw_tracks = draw_tracks
67
-
68
- # Check if environment supports imshow
69
- self.env_check = check_imshow(warn=True)
70
-
71
- # Initialize counting region
72
- if len(self.reg_pts) == 2:
73
- print("Line Counter Initiated.")
74
- self.counting_region = LineString(self.reg_pts)
75
- elif len(self.reg_pts) >= 3:
76
- print("Polygon Counter Initiated.")
77
- self.counting_region = Polygon(self.reg_pts)
78
- else:
79
- print("Invalid Region points provided, region_points must be 2 for lines or >= 3 for polygons.")
80
- print("Using Line Counter Now")
81
- self.counting_region = LineString(self.reg_pts)
82
-
83
- # Define the counting line segment
84
- self.counting_line_segment = LineString(
85
- [
86
- (self.reg_pts[0][0], self.reg_pts[0][1]),
87
- (self.reg_pts[1][0], self.reg_pts[1][1]),
88
- ]
89
- )
90
-
91
- def mouse_event_for_region(self, event, x, y, flags, params):
39
+ if prev_position is None or track_id in self.counted_ids:
40
+ return
41
+
42
+ centroid = self.r_s.centroid
43
+ dx = (box[0] - prev_position[0]) * (centroid.x - prev_position[0])
44
+ dy = (box[1] - prev_position[1]) * (centroid.y - prev_position[1])
45
+
46
+ if len(self.region) >= 3 and self.r_s.contains(Point(track_line[-1])):
47
+ self.counted_ids.append(track_id)
48
+ # For polygon region
49
+ if dx > 0:
50
+ self.in_count += 1
51
+ self.classwise_counts[self.names[cls]]["IN"] += 1
52
+ else:
53
+ self.out_count += 1
54
+ self.classwise_counts[self.names[cls]]["OUT"] += 1
55
+
56
+ elif len(self.region) < 3 and LineString([prev_position, box[:2]]).intersects(self.l_s):
57
+ self.counted_ids.append(track_id)
58
+ # For linear region
59
+ if dx > 0 and dy > 0:
60
+ self.in_count += 1
61
+ self.classwise_counts[self.names[cls]]["IN"] += 1
62
+ else:
63
+ self.out_count += 1
64
+ self.classwise_counts[self.names[cls]]["OUT"] += 1
65
+
66
+ def store_classwise_counts(self, cls):
92
67
  """
93
- Handles mouse events for defining and moving the counting region in a real-time video stream.
68
+ Initialize class-wise counts if not already present.
94
69
 
95
70
  Args:
96
- event (int): The type of mouse event (e.g., cv2.EVENT_MOUSEMOVE, cv2.EVENT_LBUTTONDOWN, etc.).
97
- x (int): The x-coordinate of the mouse pointer.
98
- y (int): The y-coordinate of the mouse pointer.
99
- flags (int): Any associated event flags (e.g., cv2.EVENT_FLAG_CTRLKEY, cv2.EVENT_FLAG_SHIFTKEY, etc.).
100
- params (dict): Additional parameters for the function.
71
+ cls (int): Class index for classwise count updates
101
72
  """
102
- if event == cv2.EVENT_LBUTTONDOWN:
103
- for i, point in enumerate(self.reg_pts):
104
- if (
105
- isinstance(point, (tuple, list))
106
- and len(point) >= 2
107
- and (abs(x - point[0]) < 10 and abs(y - point[1]) < 10)
108
- ):
109
- self.selected_point = i
110
- self.is_drawing = True
111
- break
112
-
113
- elif event == cv2.EVENT_MOUSEMOVE:
114
- if self.is_drawing and self.selected_point is not None:
115
- self.reg_pts[self.selected_point] = (x, y)
116
- self.counting_region = Polygon(self.reg_pts)
117
-
118
- elif event == cv2.EVENT_LBUTTONUP:
119
- self.is_drawing = False
120
- self.selected_point = None
121
-
122
- def extract_and_process_tracks(self, tracks):
123
- """Extracts and processes tracks for object counting in a video stream."""
124
- # Annotator Init and region drawing
125
- annotator = Annotator(self.im0, self.tf, self.names)
126
-
127
- # Draw region or line
128
- annotator.draw_region(reg_pts=self.reg_pts, color=(104, 0, 123), thickness=self.tf * 2)
129
-
130
- # Extract tracks for OBB or object detection
131
- track_data = tracks[0].obb or tracks[0].boxes
132
-
133
- if track_data and track_data.id is not None:
134
- boxes = track_data.xyxy.cpu()
135
- clss = track_data.cls.cpu().tolist()
136
- track_ids = track_data.id.int().cpu().tolist()
137
-
138
- # Extract tracks
139
- for box, track_id, cls in zip(boxes, track_ids, clss):
140
- # Draw bounding box
141
- annotator.box_label(box, label=self.names[cls], color=colors(int(track_id), True))
142
-
143
- # Store class info
144
- if self.names[cls] not in self.class_wise_count:
145
- self.class_wise_count[self.names[cls]] = {"IN": 0, "OUT": 0}
146
-
147
- # Draw Tracks
148
- track_line = self.track_history[track_id]
149
- track_line.append((float((box[0] + box[2]) / 2), float((box[1] + box[3]) / 2)))
150
- if len(track_line) > 30:
151
- track_line.pop(0)
152
-
153
- # Draw track trails
154
- if self.draw_tracks:
155
- annotator.draw_centroid_and_tracks(
156
- track_line,
157
- color=colors(int(track_id), True),
158
- track_thickness=self.tf,
159
- )
73
+ if self.names[cls] not in self.classwise_counts:
74
+ self.classwise_counts[self.names[cls]] = {"IN": 0, "OUT": 0}
160
75
 
161
- prev_position = self.track_history[track_id][-2] if len(self.track_history[track_id]) > 1 else None
76
+ def display_counts(self, im0):
77
+ """
78
+ Helper function to display object counts on the frame.
162
79
 
163
- # Count objects in any polygon
164
- if len(self.reg_pts) >= 3:
165
- is_inside = self.counting_region.contains(Point(track_line[-1]))
166
-
167
- if prev_position is not None and is_inside and track_id not in self.count_ids:
168
- self.count_ids.append(track_id)
169
-
170
- if (box[0] - prev_position[0]) * (self.counting_region.centroid.x - prev_position[0]) > 0:
171
- self.in_counts += 1
172
- self.class_wise_count[self.names[cls]]["IN"] += 1
173
- else:
174
- self.out_counts += 1
175
- self.class_wise_count[self.names[cls]]["OUT"] += 1
176
-
177
- # Count objects using line
178
- elif len(self.reg_pts) == 2:
179
- if (
180
- prev_position is not None
181
- and track_id not in self.count_ids
182
- and LineString([(prev_position[0], prev_position[1]), (box[0], box[1])]).intersects(
183
- self.counting_line_segment
184
- )
185
- ):
186
- self.count_ids.append(track_id)
187
-
188
- # Determine the direction of movement (IN or OUT)
189
- dx = (box[0] - prev_position[0]) * (self.counting_region.centroid.x - prev_position[0])
190
- dy = (box[1] - prev_position[1]) * (self.counting_region.centroid.y - prev_position[1])
191
- if dx > 0 and dy > 0:
192
- self.in_counts += 1
193
- self.class_wise_count[self.names[cls]]["IN"] += 1
194
- else:
195
- self.out_counts += 1
196
- self.class_wise_count[self.names[cls]]["OUT"] += 1
197
-
198
- labels_dict = {}
199
-
200
- for key, value in self.class_wise_count.items():
201
- if value["IN"] != 0 or value["OUT"] != 0:
202
- if not self.view_in_counts and not self.view_out_counts:
203
- continue
204
- elif not self.view_in_counts:
205
- labels_dict[str.capitalize(key)] = f"OUT {value['OUT']}"
206
- elif not self.view_out_counts:
207
- labels_dict[str.capitalize(key)] = f"IN {value['IN']}"
208
- else:
209
- labels_dict[str.capitalize(key)] = f"IN {value['IN']} OUT {value['OUT']}"
80
+ Args:
81
+ im0 (ndarray): The input image or frame
82
+ """
83
+ labels_dict = {
84
+ str.capitalize(key): f"{'IN ' + str(value['IN']) if self.show_in else ''} "
85
+ f"{'OUT ' + str(value['OUT']) if self.show_out else ''}".strip()
86
+ for key, value in self.classwise_counts.items()
87
+ if value["IN"] != 0 or value["OUT"] != 0
88
+ }
210
89
 
211
90
  if labels_dict:
212
- annotator.display_analytics(self.im0, labels_dict, (104, 31, 17), (255, 255, 255), 10)
213
-
214
- def display_frames(self):
215
- """Displays the current frame with annotations and regions in a window."""
216
- if self.env_check:
217
- cv2.namedWindow(self.window_name)
218
- if len(self.reg_pts) == 4: # only add mouse event If user drawn region
219
- cv2.setMouseCallback(self.window_name, self.mouse_event_for_region, {"region_points": self.reg_pts})
220
- cv2.imshow(self.window_name, self.im0)
221
- # Break Window
222
- if cv2.waitKey(1) & 0xFF == ord("q"):
223
- return
224
-
225
- def start_counting(self, im0, tracks):
91
+ self.annotator.display_analytics(im0, labels_dict, (104, 31, 17), (255, 255, 255), 10)
92
+
93
+ def count(self, im0):
226
94
  """
227
- Main function to start the object counting process.
95
+ Processes input data (frames or object tracks) and updates counts.
228
96
 
229
97
  Args:
230
- im0 (ndarray): Current frame from the video stream.
231
- tracks (list): List of tracks obtained from the object tracking process.
98
+ im0 (ndarray): The input image that will be used for processing
99
+ Returns
100
+ im0 (ndarray): The processed image for more usage
232
101
  """
233
- self.im0 = im0 # store image
234
- self.extract_and_process_tracks(tracks) # draw region even if no objects
235
-
236
- if self.view_img:
237
- self.display_frames()
238
- return self.im0
102
+ self.annotator = Annotator(im0, line_width=self.line_width) # Initialize annotator
103
+ self.extract_tracks(im0) # Extract tracks
104
+
105
+ self.annotator.draw_region(
106
+ reg_pts=self.region, color=(104, 0, 123), thickness=self.line_width * 2
107
+ ) # Draw region
108
+
109
+ # Iterate over bounding boxes, track ids and classes index
110
+ if self.track_data is not None and self.track_data.id is not None:
111
+ for box, track_id, cls in zip(self.boxes, self.track_ids, self.clss):
112
+ # Draw bounding box and counting region
113
+ self.annotator.box_label(box, label=self.names[cls], color=colors(track_id, True))
114
+ self.store_tracking_history(track_id, box) # Store track history
115
+ self.store_classwise_counts(cls) # store classwise counts in dict
116
+
117
+ # Draw centroid of objects
118
+ self.annotator.draw_centroid_and_tracks(
119
+ self.track_line, color=colors(int(track_id), True), track_thickness=self.line_width
120
+ )
121
+
122
+ # store previous position of track for object counting
123
+ prev_position = self.track_history[track_id][-2] if len(self.track_history[track_id]) > 1 else None
124
+ self.count_objects(self.track_line, box, track_id, prev_position, cls) # Perform object counting
239
125
 
126
+ self.display_counts(im0) # Display the counts on the frame
127
+ self.display_output(im0) # display output with base class function
240
128
 
241
- if __name__ == "__main__":
242
- classes_names = {0: "person", 1: "car"} # example class names
243
- ObjectCounter(classes_names)
129
+ return im0 # return output image for more usage
@@ -0,0 +1,88 @@
1
+ # Ultralytics YOLO 🚀, AGPL-3.0 license
2
+
3
+ from collections import defaultdict
4
+ from pathlib import Path
5
+
6
+ import cv2
7
+ from shapely.geometry import LineString, Polygon
8
+
9
+ from ultralytics import YOLO
10
+ from ultralytics.utils import yaml_load
11
+ from ultralytics.utils.checks import check_imshow
12
+
13
+ DEFAULT_SOL_CFG_PATH = Path(__file__).resolve().parents[1] / "cfg/solutions/default.yaml"
14
+
15
+
16
+ class BaseSolution:
17
+ """A class to manage all the Ultralytics Solutions: https://docs.ultralytics.com/solutions/."""
18
+
19
+ def __init__(self, **kwargs):
20
+ """
21
+ Base initializer for all solutions.
22
+
23
+ Child classes should call this with necessary parameters.
24
+ """
25
+ # Load config and update with args
26
+ self.CFG = yaml_load(DEFAULT_SOL_CFG_PATH)
27
+ self.CFG.update(kwargs)
28
+ print("Ultralytics Solutions: ✅", self.CFG)
29
+
30
+ self.region = self.CFG["region"] # Store region data for other classes usage
31
+ self.line_width = self.CFG["line_width"] # Store line_width for usage
32
+
33
+ # Load Model and store classes names
34
+ self.model = YOLO(self.CFG["model"])
35
+ self.names = self.model.names
36
+
37
+ # Initialize environment and region setup
38
+ self.env_check = check_imshow(warn=True)
39
+ self.track_history = defaultdict(list)
40
+
41
+ def extract_tracks(self, im0):
42
+ """
43
+ Apply object tracking and extract tracks.
44
+
45
+ Args:
46
+ im0 (ndarray): The input image or frame
47
+ """
48
+ self.tracks = self.model.track(source=im0, persist=True, classes=self.CFG["classes"])
49
+
50
+ # Extract tracks for OBB or object detection
51
+ self.track_data = self.tracks[0].obb or self.tracks[0].boxes
52
+
53
+ if self.track_data and self.track_data.id is not None:
54
+ self.boxes = self.track_data.xyxy.cpu()
55
+ self.clss = self.track_data.cls.cpu().tolist()
56
+ self.track_ids = self.track_data.id.int().cpu().tolist()
57
+
58
+ def store_tracking_history(self, track_id, box):
59
+ """
60
+ Store object tracking history.
61
+
62
+ Args:
63
+ track_id (int): The track ID of the object
64
+ box (list): Bounding box coordinates of the object
65
+ """
66
+ # Store tracking history
67
+ self.track_line = self.track_history[track_id]
68
+ self.track_line.append(((box[0] + box[2]) / 2, (box[1] + box[3]) / 2))
69
+ if len(self.track_line) > 30:
70
+ self.track_line.pop(0)
71
+
72
+ def initialize_region(self):
73
+ """Initialize the counting region and line segment based on config."""
74
+ self.region = [(20, 400), (1260, 400)] if self.region is None else self.region
75
+ self.r_s = Polygon(self.region) if len(self.region) >= 3 else LineString(self.region)
76
+ self.l_s = LineString([(self.region[0][0], self.region[0][1]), (self.region[1][0], self.region[1][1])])
77
+
78
+ def display_output(self, im0):
79
+ """
80
+ Display the results of the processing, which could involve showing frames, printing counts, or saving results.
81
+
82
+ Args:
83
+ im0 (ndarray): The input image or frame
84
+ """
85
+ if self.CFG.get("show") and self.env_check:
86
+ cv2.imshow("Ultralytics Solutions", im0)
87
+ if cv2.waitKey(1) & 0xFF == ord("q"):
88
+ return
@@ -61,8 +61,8 @@ HELP_MSG = """
61
61
  from ultralytics import YOLO
62
62
 
63
63
  # Load a model
64
- model = YOLO("yolov8n.yaml") # build a new model from scratch
65
- model = YOLO("yolov8n.pt") # load a pretrained model (recommended for training)
64
+ model = YOLO("yolo11n.yaml") # build a new model from scratch
65
+ model = YOLO("yolo11n.pt") # load a pretrained model (recommended for training)
66
66
 
67
67
  # Use the model
68
68
  results = model.train(data="coco8.yaml", epochs=3) # train the model
@@ -77,21 +77,21 @@ HELP_MSG = """
77
77
  yolo TASK MODE ARGS
78
78
 
79
79
  Where TASK (optional) is one of [detect, segment, classify, pose, obb]
80
- MODE (required) is one of [train, val, predict, export, benchmark]
80
+ MODE (required) is one of [train, val, predict, export, track, benchmark]
81
81
  ARGS (optional) are any number of custom "arg=value" pairs like "imgsz=320" that override defaults.
82
82
  See all ARGS at https://docs.ultralytics.com/usage/cfg or with "yolo cfg"
83
83
 
84
84
  - Train a detection model for 10 epochs with an initial learning_rate of 0.01
85
- yolo detect train data=coco8.yaml model=yolov8n.pt epochs=10 lr0=0.01
85
+ yolo detect train data=coco8.yaml model=yolo11n.pt epochs=10 lr0=0.01
86
86
 
87
87
  - Predict a YouTube video using a pretrained segmentation model at image size 320:
88
- yolo segment predict model=yolov8n-seg.pt source='https://youtu.be/LNwODJXcvt4' imgsz=320
88
+ yolo segment predict model=yolo11n-seg.pt source='https://youtu.be/LNwODJXcvt4' imgsz=320
89
89
 
90
90
  - Val a pretrained detection model at batch-size 1 and image size 640:
91
- yolo detect val model=yolov8n.pt data=coco8.yaml batch=1 imgsz=640
91
+ yolo detect val model=yolo11n.pt data=coco8.yaml batch=1 imgsz=640
92
92
 
93
- - Export a YOLOv8n classification model to ONNX format at image size 224 by 128 (no TASK required)
94
- yolo export model=yolov8n-cls.pt format=onnx imgsz=224,128
93
+ - Export a YOLO11n classification model to ONNX format at image size 224 by 128 (no TASK required)
94
+ yolo export model=yolo11n-cls.pt format=onnx imgsz=224,128
95
95
 
96
96
  - Run special commands:
97
97
  yolo help
@@ -1030,6 +1030,7 @@ def set_sentry():
1030
1030
  sentry_sdk.init(
1031
1031
  dsn="https://888e5a0778212e1d0314c37d4b9aae5d@o4504521589325824.ingest.us.sentry.io/4504521592406016",
1032
1032
  debug=False,
1033
+ auto_enabling_integrations=False,
1033
1034
  traces_sample_rate=1.0,
1034
1035
  release=__version__,
1035
1036
  environment="production", # 'dev' or 'production'
@@ -170,6 +170,8 @@ def select_device(device="", batch=0, newline=False, verbose=True):
170
170
  elif device: # non-cpu device requested
171
171
  if device == "cuda":
172
172
  device = "0"
173
+ if "," in device:
174
+ device = ",".join([x for x in device.split(",") if x]) # remove sequential commas, i.e. "0,,1" -> "0,1"
173
175
  visible = os.environ.get("CUDA_VISIBLE_DEVICES", None)
174
176
  os.environ["CUDA_VISIBLE_DEVICES"] = device # set environment variable - must be before assert is_available()
175
177
  if not (torch.cuda.is_available() and torch.cuda.device_count() >= len(device.split(","))):
@@ -191,7 +193,7 @@ def select_device(device="", batch=0, newline=False, verbose=True):
191
193
  )
192
194
 
193
195
  if not cpu and not mps and torch.cuda.is_available(): # prefer GPU if available
194
- devices = device.split(",") if device else "0" # range(torch.cuda.device_count()) # i.e. 0,1,6,7
196
+ devices = device.split(",") if device else "0" # i.e. "0,1" -> ["0", "1"]
195
197
  n = len(devices) # device count
196
198
  if n > 1: # multi-GPU
197
199
  if batch < 1:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ultralytics
3
- Version: 8.3.3
3
+ Version: 8.3.5
4
4
  Summary: Ultralytics YOLO for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
5
5
  Author: Ayush Chaurasia
6
6
  Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>, Jing Qiu <jing.qiu@ultralytics.com>
@@ -33,7 +33,7 @@ Classifier: Operating System :: Microsoft :: Windows
33
33
  Requires-Python: >=3.8
34
34
  Description-Content-Type: text/markdown
35
35
  License-File: LICENSE
36
- Requires-Dist: numpy<2.0.0,>=1.23.0
36
+ Requires-Dist: numpy>=1.23.0
37
37
  Requires-Dist: matplotlib>=3.3.0
38
38
  Requires-Dist: opencv-python>=4.6.0
39
39
  Requires-Dist: pillow>=7.1.2
@@ -76,6 +76,7 @@ Requires-Dist: numpy==1.23.5; platform_machine == "aarch64" and extra == "export
76
76
  Requires-Dist: h5py!=3.11.0; platform_machine == "aarch64" and extra == "export"
77
77
  Requires-Dist: tensorstore>=0.1.63; (platform_machine == "aarch64" and python_version >= "3.9") and extra == "export"
78
78
  Requires-Dist: coremltools>=7.0; (platform_system != "Windows" and python_version <= "3.11") and extra == "export"
79
+ Requires-Dist: scikit-learn>=1.3.2; (platform_system != "Windows" and python_version <= "3.11") and extra == "export"
79
80
  Provides-Extra: extra
80
81
  Requires-Dist: hub-sdk>=0.0.12; extra == "extra"
81
82
  Requires-Dist: ipython; extra == "extra"
@@ -7,12 +7,12 @@ tests/test_explorer.py,sha256=9EeMtt4-K3-MeGnAc7NemTg3uTo-Xr6AYJlTJZJJeF8,2572
7
7
  tests/test_exports.py,sha256=fpTKEVBUGLF3WiZPNKRs-IEcIY4cfxgvgKjUNfodjww,8042
8
8
  tests/test_integrations.py,sha256=f5-QCUk1SU_-qn4mBCZwS3GN3tXEBIIXo4z2EhExbHw,6126
9
9
  tests/test_python.py,sha256=I1RRdCwLdrc3jX06huVxct8HX8ccQOmQgVpuEflRl0U,23560
10
- tests/test_solutions.py,sha256=eAaLf1wM7IJ6DjT7NEw6sRaeDuTX0ZgsTjrI33XFCXE,3300
11
- ultralytics/__init__.py,sha256=EBK5aoP9DP2M_QXggxoUlGqceIsrS3Pv0LXlAQforQU,693
10
+ tests/test_solutions.py,sha256=Hjedlp6Qkqb4zyQ0y3DvfNValcguOMl8xbrDVpIFPfU,3304
11
+ ultralytics/__init__.py,sha256=cPwEVFFgAAExxMMRGjRidE4mFdGDLx7Pr-tKFsQX5E4,693
12
12
  ultralytics/assets/bus.jpg,sha256=wCAZxJecGR63Od3ZRERe9Aja1Weayrb9Ug751DS_vGM,137419
13
13
  ultralytics/assets/zidane.jpg,sha256=Ftc4aeMmen1O0A3o6GCDO9FlfBslLpTAw0gnetx7bts,50427
14
14
  ultralytics/cfg/__init__.py,sha256=62PSSAa0W4-gAEcRNKoKbcxUWBeFNs0ss2O4XJQhOPY,33145
15
- ultralytics/cfg/default.yaml,sha256=tkBn3c6duKGFyENuULkWessAqaaxo9atuOxXq3XbItM,8314
15
+ ultralytics/cfg/default.yaml,sha256=ul49zgSzTegMmc8CFeu9tXkWNvQhETdZMa9EgDNSnY4,8319
16
16
  ultralytics/cfg/datasets/Argoverse.yaml,sha256=FyeuJT5CHq_9d4hlfAf0kpZlnbUMO0S--UJ1yIqcdKk,3134
17
17
  ultralytics/cfg/datasets/DOTAv1.5.yaml,sha256=QVfp_Qp-4rukuicaB4qx86NxSHM8Mrzym8l_fIDo8gw,1195
18
18
  ultralytics/cfg/datasets/DOTAv1.yaml,sha256=sxe2P7nY-cCPufH3G1pymnQVtNoGH1y0ETG5CyWfK9g,1165
@@ -86,31 +86,32 @@ ultralytics/cfg/models/v9/yolov9e.yaml,sha256=dhaR47WxuLOrZWDCceS4bQG00sQdrMc8FQ
86
86
  ultralytics/cfg/models/v9/yolov9m.yaml,sha256=l6CmivzNu44sRVmkQXk4-tXflbV1nWnk5MSc8su2vhs,1311
87
87
  ultralytics/cfg/models/v9/yolov9s.yaml,sha256=lPWcu-6ub1kCBD6zIDFwthYZ3RvdJfODWKy3vEQWRjo,1291
88
88
  ultralytics/cfg/models/v9/yolov9t.yaml,sha256=qL__kr6GoefpQWP4jV0jdzwTp46bdFUcqtPRnfDbkY8,1275
89
+ ultralytics/cfg/solutions/default.yaml,sha256=Z3hzSeoEhsVuGGc2WMVRAYukuXFGqKjAIefL6JS8P8k,599
89
90
  ultralytics/cfg/trackers/botsort.yaml,sha256=8B0xNbnG_E-9DCUpap72PWkUgBb1AjuApEn7gHiVngE,916
90
91
  ultralytics/cfg/trackers/bytetrack.yaml,sha256=8vpTZ2x9mhRXJymoJvs1G8kTXo_HxbSwHup2FQALT3A,721
91
92
  ultralytics/data/__init__.py,sha256=VGe-ATG7j35F4A4r8Jmzffjlhve4JAJPgRa5ahKTU18,616
92
93
  ultralytics/data/annotator.py,sha256=PniOxH2MScWKp539vuufk69uG1JsltDB5OMCUhxn2QY,2489
93
94
  ultralytics/data/augment.py,sha256=YCLrwx1mRGeidggo_7GeINay8KdxACqREHJofZeaTHA,120430
94
- ultralytics/data/base.py,sha256=zi_1nnJb29gBqY3jrvbMCwh6RPpXhr08DQ2BQ2_dhTo,13835
95
+ ultralytics/data/base.py,sha256=ZCIhAyFfxXVp5fVnYD8mwbksNALJTayBKIR5FKGV7ZM,15168
95
96
  ultralytics/data/build.py,sha256=AfMmz0sHIYmwry_90tEJFRk_kz0S3SolScVXqYHiT08,7261
96
97
  ultralytics/data/converter.py,sha256=DjJ0atku2aKW0iS1PZPNX8V6WTrZ-CHZT6hopE1HSjI,21385
97
98
  ultralytics/data/dataset.py,sha256=IS07ulk7rXPZ-SW_rjYF9mS-TxPXOY9bbo5jqfcwPqM,22874
98
99
  ultralytics/data/loaders.py,sha256=JF2Z_ESK6RweavOuYWejYSGJwmqINb5hNwwCb3AAf0M,24094
99
100
  ultralytics/data/split_dota.py,sha256=yOtypHoY5HvIVBKZgFXdfj2tuCLLEBnMwNfAeG94Eik,10680
100
- ultralytics/data/utils.py,sha256=GVTtZlFE8Q9RlNJ19Er_CdxenjeDbvQerU1jKOs76S4,31042
101
+ ultralytics/data/utils.py,sha256=FQhceOiQOuhyDKCeX-ovEBBr2fO7cFbcVaAUp-nk3CM,31072
101
102
  ultralytics/data/explorer/__init__.py,sha256=-Y3m1ZedepOQUv_KW82zaGxvU_PSHcuwUTFqG9BhAr4,113
102
103
  ultralytics/data/explorer/explorer.py,sha256=JWmLHHhp68h2q3vx4poBou5RYoAX3R89yihR50YLDb0,18881
103
104
  ultralytics/data/explorer/utils.py,sha256=EvvukQiQUTBrsZznmMnyEX2EqTuwZo_Geyc8yfi8NIA,7085
104
105
  ultralytics/data/explorer/gui/__init__.py,sha256=mHtJuK4hwF8cuV-VHDc7tp6u6D1gHz2Z7JI8grmQDTs,42
105
106
  ultralytics/data/explorer/gui/dash.py,sha256=vZ476NaUH4FKU08rAJ1K9WNyKtg0soMyJJxqg176yWc,10498
106
107
  ultralytics/engine/__init__.py,sha256=mHtJuK4hwF8cuV-VHDc7tp6u6D1gHz2Z7JI8grmQDTs,42
107
- ultralytics/engine/exporter.py,sha256=BFYvv763kbEm5q0-AYIh979vL0ccU4RNvON2w8qtm1s,57019
108
+ ultralytics/engine/exporter.py,sha256=qhuPMBjBDVj9Qaa2qJYR954a-YS4BJtVN9jJeyFzyOg,57527
108
109
  ultralytics/engine/model.py,sha256=TDuy9JzzyvOaq5aKVljL_MFRKBDMCFwaLo3JD_d45CU,51462
109
110
  ultralytics/engine/predictor.py,sha256=MgMWHUJdRcVCaVmOyvdy2Gjk_EyRHv-ar0SSGxQe8F4,17471
110
111
  ultralytics/engine/results.py,sha256=8RJlN8J-_9w-mrDZm9wC-DZJTPBS7v1c_r_R173QyRM,75043
111
- ultralytics/engine/trainer.py,sha256=lBMKJDpu8owE0eeNkAsYszbAROk-WOB3vlhoGB1Vicc,36971
112
+ ultralytics/engine/trainer.py,sha256=O2xCZ6mriLfPhU2IRe8XCCyZiI5A_AknjpQw3O5bAIE,36983
112
113
  ultralytics/engine/tuner.py,sha256=gPqDTHH7vRB2O3YyH26m1BjVKbXxuA2XAlPRzTKFZsc,11838
113
- ultralytics/engine/validator.py,sha256=483Ad87Irk7IBlJNLu2SQAJsb7YriALTX9GIgriCmRg,14650
114
+ ultralytics/engine/validator.py,sha256=2C_qXI36Z9rLOpmS0YR8Qe3ka4p23YiH2w5ai7-XBwE,14811
114
115
  ultralytics/hub/__init__.py,sha256=3SKvZ5aRina3h94xMPQIB3D4maF62qFcyIqPPHRHNAc,5644
115
116
  ultralytics/hub/auth.py,sha256=kDLakGa2NbzvMAeXc2UdzZ65r0AH-XeM_JfsDY97WGk,5545
116
117
  ultralytics/hub/session.py,sha256=2KznO5kX14HFZ2-Ct9LoG312sdHuigQSLZb58MGvbJY,16411
@@ -135,7 +136,7 @@ ultralytics/models/sam/__init__.py,sha256=o4_D6y8YJlOXIK7Lwo9RHnIJJ9xoFNi4zK99QS
135
136
  ultralytics/models/sam/amg.py,sha256=GrmO_8YfIDt_QkPEMF_WFjPZkhwhf7iwx7ig8JgOUnE,8709
136
137
  ultralytics/models/sam/build.py,sha256=np9vP7AETCZA2Wdds-uj2eQKVnpHQaVpRrE2-U2uMTI,12153
137
138
  ultralytics/models/sam/model.py,sha256=2KFUp8SHiqOgwUjkdqdau0oduJwKQxm4N9GHWjdhUFo,7382
138
- ultralytics/models/sam/predict.py,sha256=unsoNrEx6pexKD28-HTpALa02PtNtE4e2ERdzs9qbYw,38556
139
+ ultralytics/models/sam/predict.py,sha256=_spP0uYNFzUnybwBvzZhF3iEMwvAi6bxryRdUwxwweM,38608
139
140
  ultralytics/models/sam/modules/__init__.py,sha256=mHtJuK4hwF8cuV-VHDc7tp6u6D1gHz2Z7JI8grmQDTs,42
140
141
  ultralytics/models/sam/modules/blocks.py,sha256=Q-KwhFbdyZhl1tjG_kP2LcQkZbzoNt618i-NRrKNx2Y,45919
141
142
  ultralytics/models/sam/modules/decoders.py,sha256=mODsqnTN_CjE3H0Sh9cd8PfTnHANPjGB1bjqHxfezSg,25830
@@ -187,10 +188,11 @@ ultralytics/solutions/__init__.py,sha256=6RDeXWO1QSaMgCq8YrWXaj2xvPw2sJwJL_a0dgj
187
188
  ultralytics/solutions/ai_gym.py,sha256=MgD_4DciCqXquM2Y6yjIIRkGWIg3rNfSuXrFqYzOCaI,4719
188
189
  ultralytics/solutions/analytics.py,sha256=bGuZes11D7DNiTsHdwu6PJ0QA0vCiqMMAtZ7NyEkshY,11568
189
190
  ultralytics/solutions/distance_calculation.py,sha256=o_DAHk4JX8n2Vt7E68MX67mREOBZuy5skbXtVZ6iu_4,5228
190
- ultralytics/solutions/heatmap.py,sha256=oEVivA4KAK6z0wA5Ca_a2qTckQN8tCt9MCpsPREeNnk,10375
191
- ultralytics/solutions/object_counter.py,sha256=U66uvv_6QSol4-LY1E9JOZnYRYbek5Kz3N7Cgzh6FuA,9982
191
+ ultralytics/solutions/heatmap.py,sha256=mSssM7bZa_MTx5404tQPL0TMZRguowQa4DSAbcpivRM,10090
192
+ ultralytics/solutions/object_counter.py,sha256=lBSWW0Ev6FOeV1MQNESBpub9Wzyulb9s1VBGbRRd8Sk,5485
192
193
  ultralytics/solutions/parking_management.py,sha256=VgYyhoSEo7fnPegIhNUqnFL0jlMEevALx0QQbzJ3vGI,9049
193
194
  ultralytics/solutions/queue_management.py,sha256=yKPGc2-fN-lMpNddkxjN7xYGIJwMdoU-VIDRxQ1KPow,4869
195
+ ultralytics/solutions/solutions.py,sha256=bIt32FLj4ny5kG43bUKZiwyh-7qye6NOApxAvioklIA,3248
194
196
  ultralytics/solutions/speed_estimation.py,sha256=c9OPGpDU9x6Dj4SobNc-sO90EZTPTGeKkW5u6C6Zj7g,4623
195
197
  ultralytics/solutions/streamlit_inference.py,sha256=qA2EtwUC7ADOQ8P-zs3VPyrIoRArhcZz9CxkFbH63bw,5699
196
198
  ultralytics/trackers/__init__.py,sha256=j72IgH2dZHQArMPK4YwcV5ieIw94fYvlGdQjB9cOQKw,227
@@ -202,7 +204,7 @@ ultralytics/trackers/utils/__init__.py,sha256=mHtJuK4hwF8cuV-VHDc7tp6u6D1gHz2Z7J
202
204
  ultralytics/trackers/utils/gmc.py,sha256=VcURuY041qGCeWUGMxHZBr10T16LtcMqyv7AmTfE1MY,14557
203
205
  ultralytics/trackers/utils/kalman_filter.py,sha256=cH9zD3fwkuezP97H9mw8cSBN7a8hHKx_Sx1j7t3oYGs,21349
204
206
  ultralytics/trackers/utils/matching.py,sha256=3Ie1WNNRZ4_q3365F03XD7Nr9juZB_08mw4yUKC3w74,7162
205
- ultralytics/utils/__init__.py,sha256=R2VpuwIfwpTSTX2T_MFdW1tNdX27FZW5XAH984tjR1Q,48834
207
+ ultralytics/utils/__init__.py,sha256=pdYHDaJMacya7WWq5RNEw-UmidG3i0kQyWrbFNnAVtc,48887
206
208
  ultralytics/utils/autobatch.py,sha256=AXboYfNSnTGsYj5FmgGYPQd0crfkeleyms6QXQfZGQ4,4194
207
209
  ultralytics/utils/benchmarks.py,sha256=8FYp5WPzcxcDaeg8ol2sgzRBHVGYatEO7f3MrmPF6nI,25097
208
210
  ultralytics/utils/checks.py,sha256=tiwVY1SCf7AlDOUQDh6fJlmhQ3CxQEqLUrXRvwRBoKs,28998
@@ -217,7 +219,7 @@ ultralytics/utils/ops.py,sha256=dsXNdyrYx_p6io6zezig9p84dxS7U-10vceHNVu2IL0,3288
217
219
  ultralytics/utils/patches.py,sha256=J-iOwIRbfUs-inBZerhnXby5tUKjYcOIyvhLTS352JE,3270
218
220
  ultralytics/utils/plotting.py,sha256=Sqs9Q7mhenCsFed_oyw_64wgvd0TTae9L3Lc4g2_lSI,62296
219
221
  ultralytics/utils/tal.py,sha256=ECsu95xEqOItmxMDN4YTD3FsUiIsQNWy0pZC3TfvFfk,16877
220
- ultralytics/utils/torch_utils.py,sha256=tqOyNnUZbLBOIueSWwljZua65cz6_RvClxYv8gNHIw0,29673
222
+ ultralytics/utils/torch_utils.py,sha256=RsTzm3__J4K1OUaxqc32O9WT6azcl4hPNkDdxhEp3q4,29792
221
223
  ultralytics/utils/triton.py,sha256=gg1finxno_tY2Ge9PMhmu7PI9wvoFZoiicdT4Bhqv3w,3936
222
224
  ultralytics/utils/tuner.py,sha256=AtEtK6pOt9xVTyx864OpNRVxNdAxz5aKHzveiXwkD1A,6250
223
225
  ultralytics/utils/callbacks/__init__.py,sha256=YrWqC3BVVaTLob4iCPR6I36mUxIUOpPJW7B_LjT78Qw,214
@@ -231,9 +233,9 @@ ultralytics/utils/callbacks/neptune.py,sha256=5Z3ua5YBTUS56FH8VQKQG1aaIo9fH8GEyz
231
233
  ultralytics/utils/callbacks/raytune.py,sha256=ODVYzy-CoM4Uge0zjkh3Hnh9nF2M0vhDrSenXnvcizw,705
232
234
  ultralytics/utils/callbacks/tensorboard.py,sha256=0kn4IR10no99UCIheojWRujgybmUHSx5fPI6Vsq6l_g,4135
233
235
  ultralytics/utils/callbacks/wb.py,sha256=9-fjQIdLjr3b73DTE3rHO171KvbH1VweJ-bmbv-rqTw,6747
234
- ultralytics-8.3.3.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
235
- ultralytics-8.3.3.dist-info/METADATA,sha256=K4q0V89-JTwWjGWue29_CsVQH9AhLpZVmt3b61x-iMc,34574
236
- ultralytics-8.3.3.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
237
- ultralytics-8.3.3.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
238
- ultralytics-8.3.3.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
239
- ultralytics-8.3.3.dist-info/RECORD,,
236
+ ultralytics-8.3.5.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
237
+ ultralytics-8.3.5.dist-info/METADATA,sha256=vRIip27lGy6ai-vDDQrkLt_2hjxmd6TbIeur2uCcNdI,34685
238
+ ultralytics-8.3.5.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
239
+ ultralytics-8.3.5.dist-info/entry_points.txt,sha256=YM_wiKyTe9yRrsEfqvYolNO5ngwfoL4-NwgKzc8_7sI,93
240
+ ultralytics-8.3.5.dist-info/top_level.txt,sha256=XP49TwiMw4QGsvTLSYiJhz1xF_k7ev5mQ8jJXaXi45Q,12
241
+ ultralytics-8.3.5.dist-info/RECORD,,