`ultralytics 8.0.26` new YOLOv5u models (#771)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Adrian Boguszewski <adrian.boguszewski@intel.com>
single_channel
Glenn Jocher 2 years ago committed by GitHub
parent b83374b42d
commit fa8811dcee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -29,7 +29,7 @@ repos:
hooks: hooks:
- id: pyupgrade - id: pyupgrade
name: Upgrade code name: Upgrade code
args: [ --py37-plus ] args: [--py37-plus]
# - repo: https://github.com/PyCQA/isort # - repo: https://github.com/PyCQA/isort
# rev: 5.11.4 # rev: 5.11.4

@ -3,7 +3,7 @@
# Image is CUDA-optimized for YOLOv8 single/multi-GPU training and inference # Image is CUDA-optimized for YOLOv8 single/multi-GPU training and inference
# Start FROM NVIDIA PyTorch image https://ngc.nvidia.com/catalog/containers/nvidia:pytorch # Start FROM NVIDIA PyTorch image https://ngc.nvidia.com/catalog/containers/nvidia:pytorch
FROM nvcr.io/nvidia/pytorch:22.12-py3 FROM nvcr.io/nvidia/pytorch:23.01-py3
# Downloads to user config dir # Downloads to user config dir
ADD https://ultralytics.com/assets/Arial.ttf https://ultralytics.com/assets/Arial.Unicode.ttf /root/.config/Ultralytics/ ADD https://ultralytics.com/assets/Arial.ttf https://ultralytics.com/assets/Arial.Unicode.ttf /root/.config/Ultralytics/
@ -26,7 +26,7 @@ RUN git clone https://github.com/ultralytics/ultralytics /usr/src/ultralytics
# Install pip packages # Install pip packages
RUN python -m pip install --upgrade pip wheel RUN python -m pip install --upgrade pip wheel
RUN pip install --no-cache ultralytics albumentations comet gsutil notebook 'opencv-python<4.6.0.66' RUN pip install --no-cache ultralytics albumentations comet gsutil notebook
# Set environment variables # Set environment variables
ENV OMP_NUM_THREADS=1 ENV OMP_NUM_THREADS=1

@ -30,7 +30,7 @@ RUN pip install --no-cache ultralytics gsutil notebook \
tensorflow-aarch64 tensorflow-aarch64
# tensorflowjs \ # tensorflowjs \
# onnx onnx-simplifier onnxruntime \ # onnx onnx-simplifier onnxruntime \
# coremltools openvino-dev \ # coremltools openvino-dev>=2022.3 \
# Cleanup # Cleanup
ENV DEBIAN_FRONTEND teletype ENV DEBIAN_FRONTEND teletype

@ -28,7 +28,7 @@ COPY requirements.txt .
RUN python3 -m pip install --upgrade pip wheel RUN python3 -m pip install --upgrade pip wheel
RUN pip install --no-cache ultralytics albumentations gsutil notebook \ RUN pip install --no-cache ultralytics albumentations gsutil notebook \
coremltools onnx onnx-simplifier onnxruntime tensorflow-cpu \ coremltools onnx onnx-simplifier onnxruntime tensorflow-cpu \
# openvino-dev tensorflowjs \ # openvino-dev>=2022.3 tensorflowjs \
--extra-index-url https://download.pytorch.org/whl/cpu --extra-index-url https://download.pytorch.org/whl/cpu
# Cleanup # Cleanup

@ -67,7 +67,7 @@
"import ultralytics\n", "import ultralytics\n",
"ultralytics.checks()" "ultralytics.checks()"
], ],
"execution_count": 1, "execution_count": null,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
@ -116,7 +116,7 @@
"# Run inference on an image with YOLOv8n\n", "# Run inference on an image with YOLOv8n\n",
"!yolo predict model=yolov8n.pt source='https://ultralytics.com/images/zidane.jpg'" "!yolo predict model=yolov8n.pt source='https://ultralytics.com/images/zidane.jpg'"
], ],
"execution_count": 2, "execution_count": null,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
@ -183,7 +183,7 @@
"# Validate YOLOv8n on COCO128 val\n", "# Validate YOLOv8n on COCO128 val\n",
"!yolo val model=yolov8n.pt data=coco128.yaml" "!yolo val model=yolov8n.pt data=coco128.yaml"
], ],
"execution_count": 3, "execution_count": null,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
@ -306,7 +306,7 @@
"# Train YOLOv8n on COCO128 for 3 epochs\n", "# Train YOLOv8n on COCO128 for 3 epochs\n",
"!yolo train model=yolov8n.pt data=coco128.yaml epochs=3 imgsz=640" "!yolo train model=yolov8n.pt data=coco128.yaml epochs=3 imgsz=640"
], ],
"execution_count": 4, "execution_count": null,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
@ -495,7 +495,7 @@
"id": "CYIjW4igCjqD", "id": "CYIjW4igCjqD",
"outputId": "69cab2fb-cbfa-4acf-8e29-9c4fb6f4a38f" "outputId": "69cab2fb-cbfa-4acf-8e29-9c4fb6f4a38f"
}, },
"execution_count": 5, "execution_count": null,
"outputs": [ "outputs": [
{ {
"output_type": "stream", "output_type": "stream",
@ -666,6 +666,19 @@
], ],
"execution_count": null, "execution_count": null,
"outputs": [] "outputs": []
},
{
"cell_type": "code",
"source": [
"# Validate multiple models\n",
"for x in 'nsmlx':\n",
" !yolo val model=yolov8{x}.pt data=coco.yaml"
],
"metadata": {
"id": "Wdc6t_bfzDDk"
},
"execution_count": null,
"outputs": []
} }
] ]
} }

@ -31,7 +31,7 @@ seaborn>=0.11.0
# scikit-learn==0.19.2 # CoreML quantization # scikit-learn==0.19.2 # CoreML quantization
# tensorflow>=2.4.1 # TF exports (-cpu, -aarch64, -macos) # tensorflow>=2.4.1 # TF exports (-cpu, -aarch64, -macos)
# tensorflowjs>=3.9.0 # TF.js export # tensorflowjs>=3.9.0 # TF.js export
# openvino-dev>=2022.1 # OpenVINO export # openvino-dev>=2022.3 # OpenVINO export
# Extras -------------------------------------- # Extras --------------------------------------
ipython # interactive notebook ipython # interactive notebook

@ -150,14 +150,14 @@ def test_predict_callback_and_setup():
# results -> List[batch_size] # results -> List[batch_size]
path, _, im0s, _, _ = predictor.batch path, _, im0s, _, _ = predictor.batch
# print('on_predict_batch_end', im0s[0].shape) # print('on_predict_batch_end', im0s[0].shape)
bs = [predictor.bs for i in range(0, len(path))] bs = [predictor.bs for _ in range(len(path))]
predictor.results = zip(predictor.results, im0s, bs) predictor.results = zip(predictor.results, im0s, bs)
model = YOLO("yolov8n.pt") model = YOLO("yolov8n.pt")
model.add_callback("on_predict_batch_end", on_predict_batch_end) model.add_callback("on_predict_batch_end", on_predict_batch_end)
dataset = load_inference_source(source=SOURCE, transforms=model.transforms) dataset = load_inference_source(source=SOURCE, transforms=model.transforms)
bs = dataset.bs # access predictor properties bs = dataset.bs # noqa access predictor properties
results = model.predict(dataset, stream=True) # source already setup results = model.predict(dataset, stream=True) # source already setup
for _, (result, im0, bs) in enumerate(results): for _, (result, im0, bs) in enumerate(results):
print('test_callback', im0.shape) print('test_callback', im0.shape)

@ -1,6 +1,6 @@
# Ultralytics YOLO 🚀, GPL-3.0 license # Ultralytics YOLO 🚀, GPL-3.0 license
__version__ = "8.0.25" __version__ = "8.0.26"
from ultralytics.yolo.engine.model import YOLO from ultralytics.yolo.engine.model import YOLO
from ultralytics.yolo.utils import ops from ultralytics.yolo.utils import ops

@ -148,7 +148,7 @@ def argument_error(arg):
return SyntaxError(f"'{arg}' is not a valid YOLO argument.\n{CLI_HELP_MSG}") return SyntaxError(f"'{arg}' is not a valid YOLO argument.\n{CLI_HELP_MSG}")
def entrypoint(debug=False): def entrypoint(debug=''):
""" """
This function is the ultralytics package entrypoint, it's responsible for parsing the command line arguments passed This function is the ultralytics package entrypoint, it's responsible for parsing the command line arguments passed
to the package. to the package.
@ -163,7 +163,7 @@ def entrypoint(debug=False):
It uses the package's default cfg and initializes it using the passed overrides. It uses the package's default cfg and initializes it using the passed overrides.
Then it calls the CLI function with the composed cfg Then it calls the CLI function with the composed cfg
""" """
args = ['train', 'model=yolov8n.pt', 'data=coco128.yaml', 'imgsz=32', 'epochs=1'] if debug else sys.argv[1:] args = (debug.split(' ') if debug else sys.argv)[1:]
if not args: # no arguments passed if not args: # no arguments passed
LOGGER.info(CLI_HELP_MSG) LOGGER.info(CLI_HELP_MSG)
return return
@ -275,4 +275,5 @@ def copy_default_cfg():
if __name__ == '__main__': if __name__ == '__main__':
entrypoint(debug=True) # entrypoint(debug='yolo predict model=yolov8n.pt')
entrypoint(debug='')

@ -13,7 +13,7 @@ import cv2
import numpy as np import numpy as np
import requests import requests
import torch import torch
from PIL import Image, ImageOps from PIL import Image
from ultralytics.yolo.data.augment import LetterBox from ultralytics.yolo.data.augment import LetterBox
from ultralytics.yolo.data.utils import IMG_FORMATS, VID_FORMATS from ultralytics.yolo.data.utils import IMG_FORMATS, VID_FORMATS
@ -50,7 +50,7 @@ class LoadStreams:
s = pafy.new(s).getbest(preftype="mp4").url # YouTube URL s = pafy.new(s).getbest(preftype="mp4").url # YouTube URL
s = eval(s) if s.isnumeric() else s # i.e. s = '0' local webcam s = eval(s) if s.isnumeric() else s # i.e. s = '0' local webcam
if s == 0 and (is_colab() or is_kaggle()): if s == 0 and (is_colab() or is_kaggle()):
raise NotImplementedError("'source=0' webcam not supported in Colab and Kaggle notebooks." raise NotImplementedError("'source=0' webcam not supported in Colab and Kaggle notebooks. "
"Try running 'source=0' in a local environment.") "Try running 'source=0' in a local environment.")
cap = cv2.VideoCapture(s) cap = cv2.VideoCapture(s)
if not cap.isOpened(): if not cap.isOpened():
@ -61,9 +61,11 @@ class LoadStreams:
self.frames[i] = max(int(cap.get(cv2.CAP_PROP_FRAME_COUNT)), 0) or float('inf') # infinite stream fallback self.frames[i] = max(int(cap.get(cv2.CAP_PROP_FRAME_COUNT)), 0) or float('inf') # infinite stream fallback
self.fps[i] = max((fps if math.isfinite(fps) else 0) % 100, 0) or 30 # 30 FPS fallback self.fps[i] = max((fps if math.isfinite(fps) else 0) % 100, 0) or 30 # 30 FPS fallback
_, self.imgs[i] = cap.read() # guarantee first frame success, self.imgs[i] = cap.read() # guarantee first frame
if not success or self.imgs[i] is None:
raise ConnectionError(f'{st}Failed to read images from {s}')
self.threads[i] = Thread(target=self.update, args=([i, cap, s]), daemon=True) self.threads[i] = Thread(target=self.update, args=([i, cap, s]), daemon=True)
LOGGER.info(f"{st} Success ({self.frames[i]} frames {w}x{h} at {self.fps[i]:.2f} FPS)") LOGGER.info(f"{st}Success ({self.frames[i]} frames of shape {w}x{h} at {self.fps[i]:.2f} FPS)")
self.threads[i].start() self.threads[i].start()
LOGGER.info('') # newline LOGGER.info('') # newline
@ -221,15 +223,15 @@ class LoadImages:
self.mode = 'video' self.mode = 'video'
for _ in range(self.vid_stride): for _ in range(self.vid_stride):
self.cap.grab() self.cap.grab()
ret_val, im0 = self.cap.retrieve() success, im0 = self.cap.retrieve()
while not ret_val: while not success:
self.count += 1 self.count += 1
self.cap.release() self.cap.release()
if self.count == self.nf: # last video if self.count == self.nf: # last video
raise StopIteration raise StopIteration
path = self.files[self.count] path = self.files[self.count]
self._new_video(path) self._new_video(path)
ret_val, im0 = self.cap.read() success, im0 = self.cap.read()
self.frame += 1 self.frame += 1
# im0 = self._cv2_rotate(im0) # for use if cv2 autorotation is False # im0 = self._cv2_rotate(im0) # for use if cv2 autorotation is False
@ -330,14 +332,14 @@ def autocast_list(source):
Merges a list of source of different types into a list of numpy arrays or PIL images Merges a list of source of different types into a list of numpy arrays or PIL images
""" """
files = [] files = []
for _, im in enumerate(source): for im in source:
if isinstance(im, (str, Path)): # filename or uri if isinstance(im, (str, Path)): # filename or uri
files.append(Image.open(requests.get(im, stream=True).raw if str(im).startswith('http') else im)) files.append(Image.open(requests.get(im, stream=True).raw if str(im).startswith('http') else im))
elif isinstance(im, (Image.Image, np.ndarray)): # PIL or np Image elif isinstance(im, (Image.Image, np.ndarray)): # PIL or np Image
files.append(im) files.append(im)
else: else:
raise Exception( raise TypeError(f"type {type(im).__name__} is not a supported Ultralytics prediction source type. \n"
"Unsupported type encountered! See docs for supported types https://docs.ultralytics.com/predict") f"See https://docs.ultralytics.com/predict for supported source types.")
return files return files

@ -1,22 +1,18 @@
#!/bin/bash #!/bin/bash
# Ultralytics YOLO 🚀, GPL-3.0 license # Ultralytics YOLO 🚀, GPL-3.0 license
# Download latest models from https://github.com/ultralytics/yolov5/releases # Download latest models from https://github.com/ultralytics/assets/releases
# Example usage: bash data/scripts/download_weights.sh # Example usage: bash ultralytics/yolo/data/scripts/download_weights.sh
# parent # parent
# └── yolov5 # └── weights
# ├── yolov5s.pt ← downloads here # ├── yolov8n.pt ← downloads here
# ├── yolov5m.pt # ├── yolov8s.pt
# └── ... # └── ...
python - <<EOF python - <<EOF
from utils.downloads import attempt_download from ultralytics.yolo.utils.downloads import attempt_download_asset
p5 = list('nsmlx') # P5 models assets = [f'yolov8{size}{suffix}.pt' for size in 'nsmlx' for suffix in ('', '-cls', '-seg')]
p6 = [f'{x}6' for x in p5] # P6 models for x in assets:
cls = [f'{x}-cls' for x in p5] # classification models attempt_download_asset(f'weights/{x}')
seg = [f'{x}-seg' for x in p5] # classification models
for x in p5 + p6 + cls + seg:
attempt_download(f'weights/yolov5{x}.pt')
EOF EOF

@ -319,15 +319,20 @@ class Exporter:
@try_export @try_export
def _export_openvino(self, prefix=colorstr('OpenVINO:')): def _export_openvino(self, prefix=colorstr('OpenVINO:')):
# YOLOv8 OpenVINO export # YOLOv8 OpenVINO export
check_requirements('openvino-dev') # requires openvino-dev: https://pypi.org/project/openvino-dev/ check_requirements('openvino-dev>=2022.3') # requires openvino-dev: https://pypi.org/project/openvino-dev/
import openvino.runtime as ov # noqa import openvino.runtime as ov # noqa
from openvino.tools import mo # noqa
LOGGER.info(f'\n{prefix} starting export with openvino {ov.__version__}...') LOGGER.info(f'\n{prefix} starting export with openvino {ov.__version__}...')
f = str(self.file).replace(self.file.suffix, f'_openvino_model{os.sep}') f = str(self.file).replace(self.file.suffix, f'_openvino_model{os.sep}')
f_onnx = self.file.with_suffix('.onnx') f_onnx = self.file.with_suffix('.onnx')
f_ov = str(Path(f) / self.file.with_suffix('.xml').name)
cmd = f"mo --input_model {f_onnx} --output_dir {f} {'--compress_to_fp16' * self.args.half}" ov_model = mo.convert_model(f_onnx,
subprocess.run(cmd.split(), check=True, env=os.environ) # export model_name=self.pretty_name,
framework="onnx",
compress_to_fp16=self.args.half) # export
ov.serialize(ov_model, f_ov) # save
yaml_save(Path(f) / self.file.with_suffix('.yaml').name, self.metadata) # add metadata.yaml yaml_save(Path(f) / self.file.with_suffix('.yaml').name, self.metadata) # add metadata.yaml
return f, None return f, None

@ -58,7 +58,13 @@ def check_imgsz(imgsz, stride=32, min_dim=1, floor=0):
stride = int(stride.max() if isinstance(stride, torch.Tensor) else stride) stride = int(stride.max() if isinstance(stride, torch.Tensor) else stride)
# Convert image size to list if it is an integer # Convert image size to list if it is an integer
imgsz = [imgsz] if isinstance(imgsz, int) else list(imgsz) if isinstance(imgsz, int):
imgsz = [imgsz]
elif isinstance(imgsz, (list, tuple)):
imgsz = list(imgsz)
else:
raise TypeError(f"'imgsz={imgsz}' is of invalid type {type(imgsz).__name__}. "
f"Valid imgsz types are int i.e. 'imgsz=640' or list i.e. 'imgsz=[640,640]'")
# Make image size a multiple of the stride # Make image size a multiple of the stride
sz = [max(math.ceil(x / stride) * stride, floor) for x in imgsz] sz = [max(math.ceil(x / stride) * stride, floor) for x in imgsz]

@ -1,6 +1,7 @@
# Ultralytics YOLO 🚀, GPL-3.0 license # Ultralytics YOLO 🚀, GPL-3.0 license
import contextlib import contextlib
import re
import subprocess import subprocess
from itertools import repeat from itertools import repeat
from multiprocessing.pool import ThreadPool from multiprocessing.pool import ThreadPool
@ -118,7 +119,18 @@ def attempt_download_asset(file, repo='ultralytics/assets', release='v0.0.0'):
response = requests.get(f'https://api.github.com/repos/{repository}/releases/{version}').json() # github api response = requests.get(f'https://api.github.com/repos/{repository}/releases/{version}').json() # github api
return response['tag_name'], [x['name'] for x in response['assets']] # tag, assets return response['tag_name'], [x['name'] for x in response['assets']] # tag, assets
file = Path(str(file).strip().replace("'", '')) # YOLOv3/5u updates
file = str(file)
if 'yolov3' in file or 'yolov5' in file and 'u' not in file:
original_file = file
file = re.sub(r"(.*yolov5([nsmlx]))\.pt", "\\1u.pt", file) # i.e. yolov5n.pt -> yolov5nu.pt
file = re.sub(r"(.*yolov3(|-tiny|-spp))\.pt", "\\1u.pt", file) # i.e. yolov3-spp.pt -> yolov3-sppu.pt
if file != original_file:
LOGGER.info(f"PRO TIP 💡 Replace 'model={original_file}' with new 'model={file}'.\nYOLOv5 'u' models are "
f"trained with https://github.com/ultralytics/ultralytics and feature improved performance vs "
f"standard YOLOv5 models trained with https://github.com/ultralytics/yolov5.\n")
file = Path(file.strip().replace("'", ''))
if file.exists(): if file.exists():
return str(file) return str(file)
elif (SETTINGS['weights_dir'] / file).exists(): elif (SETTINGS['weights_dir'] / file).exists():
@ -136,7 +148,9 @@ def attempt_download_asset(file, repo='ultralytics/assets', release='v0.0.0'):
return file return file
# GitHub assets # GitHub assets
assets = [f'yolov8{size}{suffix}.pt' for size in 'nsmlx' for suffix in ('', '6', '-cls', '-seg')] # default assets = [f'yolov8{size}{suffix}.pt' for size in 'nsmlx' for suffix in ('', '6', '-cls', '-seg')] + \
[f'yolov5{size}u.pt' for size in 'nsmlx'] + \
[f'yolov3{size}u.pt' for size in ('', '-spp', '-tiny')]
try: try:
tag, assets = github_assets(repo, release) tag, assets = github_assets(repo, release)
except Exception: except Exception:

@ -72,15 +72,11 @@ class SegmentationPredictor(DetectionPredictor):
im_gpu=torch.as_tensor(im0, dtype=torch.float16).to(self.device).permute(2, 0, 1).flip(0).contiguous() / im_gpu=torch.as_tensor(im0, dtype=torch.float16).to(self.device).permute(2, 0, 1).flip(0).contiguous() /
255 if self.args.retina_masks else im[idx]) 255 if self.args.retina_masks else im[idx])
# Segments
if self.args.save_txt:
segments = mask.segments
# Write results # Write results
for j, d in enumerate(reversed(det)): for j, d in enumerate(reversed(det)):
cls, conf = d.cls.squeeze(), d.conf.squeeze() cls, conf = d.cls.squeeze(), d.conf.squeeze()
if self.args.save_txt: # Write to file if self.args.save_txt: # Write to file
seg = segments[j].copy() seg = mask.segments[len(det) - j - 1].copy() # reversed mask.segments
seg = seg.reshape(-1) # (n,2) to (n*2) seg = seg.reshape(-1) # (n,2) to (n*2)
line = (cls, *seg, conf) if self.args.save_conf else (cls, *seg) # label format line = (cls, *seg, conf) if self.args.save_conf else (cls, *seg) # label format
with open(f'{self.txt_path}.txt', 'a') as f: with open(f'{self.txt_path}.txt', 'a') as f:

Loading…
Cancel
Save