mirror of
https://github.com/THU-MIG/yolov10.git
synced 2025-05-22 21:04:21 +08:00
ultralytics 8.0.182
remove deprecated pkg_resources
(#4979)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
0cf82f5040
commit
28569ced8a
27
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
27
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@ -25,13 +25,14 @@ body:
|
||||
Please select the part of YOLOv8 where you found the bug.
|
||||
multiple: true
|
||||
options:
|
||||
- "Training"
|
||||
- "Validation"
|
||||
- "Detection"
|
||||
- "Install"
|
||||
- "Train"
|
||||
- "Val"
|
||||
- "Predict"
|
||||
- "Export"
|
||||
- "PyTorch Hub"
|
||||
- "Multi-GPU"
|
||||
- "Evolution"
|
||||
- "Augmentation"
|
||||
- "Hyperparameter Tuning"
|
||||
- "Integrations"
|
||||
- "Other"
|
||||
validations:
|
||||
@ -51,9 +52,19 @@ body:
|
||||
label: Environment
|
||||
description: Please specify the software and hardware you used to produce the bug.
|
||||
placeholder: |
|
||||
- YOLO: Ultralytics YOLOv8.0.21 🚀 Python-3.8.10 torch-1.13.1+cu117 CUDA:0 (A100-SXM-80GB, 81251MiB)
|
||||
- OS: Ubuntu 20.04
|
||||
- Python: 3.8.10
|
||||
Paste output of `yolo checks` or `ultralytics.checks()` commands:
|
||||
```
|
||||
Ultralytics YOLOv8.0.181 🚀 Python-3.11.2 torch-2.0.1 CPU (Apple M2)
|
||||
Setup complete ✅ (8 CPUs, 16.0 GB RAM, 266.5/460.4 GB disk)
|
||||
|
||||
OS macOS-13.5.2
|
||||
Environment Jupyter
|
||||
Python 3.11.2
|
||||
Install git
|
||||
RAM 16.00 GB
|
||||
CPU Apple M2
|
||||
CUDA None
|
||||
```
|
||||
validations:
|
||||
required: false
|
||||
|
||||
|
@ -9,8 +9,8 @@ FROM ultralytics/ultralytics:latest
|
||||
WORKDIR /actions-runner
|
||||
|
||||
# Download and unpack the latest runner from https://github.com/actions/runner
|
||||
RUN FILENAME=actions-runner-linux-x64-2.308.0.tar.gz && \
|
||||
curl -o $FILENAME -L https://github.com/actions/runner/releases/download/v2.308.0/$FILENAME && \
|
||||
RUN FILENAME=actions-runner-linux-x64-2.309.0.tar.gz && \
|
||||
curl -o $FILENAME -L https://github.com/actions/runner/releases/download/v2.309.0/$FILENAME && \
|
||||
tar xzf $FILENAME && \
|
||||
rm $FILENAME
|
||||
|
||||
|
@ -9,6 +9,14 @@ keywords: Ultralytics, utility checks, ASCII, check_version, pip_update, check_p
|
||||
|
||||
Full source code for this file is available at [https://github.com/ultralytics/ultralytics/blob/main/ultralytics/utils/checks.py](https://github.com/ultralytics/ultralytics/blob/main/ultralytics/utils/checks.py). Help us fix any issues you see by submitting a [Pull Request](https://docs.ultralytics.com/help/contributing/) 🛠️. Thank you 🙏!
|
||||
|
||||
---
|
||||
## ::: ultralytics.utils.checks.parse_requirements
|
||||
<br><br>
|
||||
|
||||
---
|
||||
## ::: ultralytics.utils.checks.parse_version
|
||||
<br><br>
|
||||
|
||||
---
|
||||
## ::: ultralytics.utils.checks.is_ascii
|
||||
<br><br>
|
||||
@ -69,6 +77,10 @@ keywords: Ultralytics, utility checks, ASCII, check_version, pip_update, check_p
|
||||
## ::: ultralytics.utils.checks.check_yolo
|
||||
<br><br>
|
||||
|
||||
---
|
||||
## ::: ultralytics.utils.checks.collect_system_info
|
||||
<br><br>
|
||||
|
||||
---
|
||||
## ::: ultralytics.utils.checks.check_amp
|
||||
<br><br>
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Ultralytics YOLO 🚀, AGPL-3.0 license
|
||||
|
||||
__version__ = '8.0.181'
|
||||
__version__ = '8.0.182'
|
||||
|
||||
from ultralytics.models import RTDETR, SAM, YOLO
|
||||
from ultralytics.models.fastsam import FastSAM
|
||||
|
@ -333,7 +333,7 @@ def entrypoint(debug=''):
|
||||
|
||||
special = {
|
||||
'help': lambda: LOGGER.info(CLI_HELP_MSG),
|
||||
'checks': checks.check_yolo,
|
||||
'checks': checks.collect_system_info,
|
||||
'version': lambda: LOGGER.info(__version__),
|
||||
'settings': lambda: handle_yolo_settings(args[1:]),
|
||||
'cfg': lambda: yaml_print(DEFAULT_CFG_PATH),
|
||||
|
@ -143,6 +143,9 @@ class Exporter:
|
||||
_callbacks (list, optional): List of callback functions. Defaults to None.
|
||||
"""
|
||||
self.args = get_cfg(cfg, overrides)
|
||||
if self.args.format.lower() in ('coreml', 'mlmodel'): # fix attempt for protobuf<3.20.x errors
|
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' # must run before TensorBoard callback
|
||||
|
||||
self.callbacks = _callbacks or callbacks.get_default_callbacks()
|
||||
callbacks.add_integration_callbacks(self)
|
||||
|
||||
@ -155,7 +158,6 @@ class Exporter:
|
||||
if format in ('tensorrt', 'trt'): # 'engine' aliases
|
||||
format = 'engine'
|
||||
if format in ('mlmodel', 'mlpackage', 'mlprogram', 'apple', 'ios', 'coreml'): # 'coreml' aliases
|
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' # fix attempt for protobuf<3.20.x errors
|
||||
format = 'coreml'
|
||||
fmts = tuple(export_formats()['Argument'][1:]) # available export formats
|
||||
flags = [x == format for x in fmts]
|
||||
|
@ -143,7 +143,7 @@ class FastSAMPrompt:
|
||||
|
||||
save_path = Path(output) / result_name
|
||||
save_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
image = Image.frombytes('RGB', fig.canvas.get_width_height(), fig.canvas.tostring_rgb())
|
||||
image = Image.frombytes('RGB', fig.canvas.get_width_height(), fig.canvas.buffer_rgba())
|
||||
image.save(save_path)
|
||||
plt.close()
|
||||
pbar.set_description(f'Saving {result_name} to {save_path}')
|
||||
|
@ -213,11 +213,6 @@ def add_integration_callbacks(instance):
|
||||
from .wb import callbacks as wb_cb
|
||||
callbacks_list.extend([clear_cb, comet_cb, dvc_cb, mlflow_cb, neptune_cb, tune_cb, tb_cb, wb_cb])
|
||||
|
||||
# Load export callbacks (patch to avoid CoreML protobuf error)
|
||||
if 'Exporter' in instance.__class__.__name__:
|
||||
from .tensorboard import callbacks as tb_cb
|
||||
callbacks_list.append(tb_cb)
|
||||
|
||||
# Add the callbacks to the callbacks dictionary
|
||||
for callbacks in callbacks_list:
|
||||
for k, v in callbacks.items():
|
||||
|
@ -9,20 +9,60 @@ import platform
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from importlib.metadata import PackageNotFoundError, version
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import pkg_resources as pkg
|
||||
import requests
|
||||
import torch
|
||||
from matplotlib import font_manager
|
||||
|
||||
from ultralytics.utils import (ASSETS, AUTOINSTALL, LINUX, LOGGER, ONLINE, ROOT, USER_CONFIG_DIR, ThreadingLocked,
|
||||
TryExcept, clean_url, colorstr, downloads, emojis, is_colab, is_docker, is_jupyter,
|
||||
is_kaggle, is_online, is_pip_package, url2file)
|
||||
from ultralytics.utils import (ASSETS, AUTOINSTALL, LINUX, LOGGER, ONLINE, ROOT, USER_CONFIG_DIR, SimpleNamespace,
|
||||
ThreadingLocked, TryExcept, clean_url, colorstr, downloads, emojis, is_colab, is_docker,
|
||||
is_jupyter, is_kaggle, is_online, is_pip_package, url2file)
|
||||
|
||||
|
||||
def parse_requirements(file_path=ROOT.parent / 'requirements.txt'):
|
||||
"""
|
||||
Parse a requirements.txt file, ignoring lines that start with '#' and any text after '#'.
|
||||
|
||||
Args:
|
||||
file_path (Path): Path to the requirements.txt file.
|
||||
|
||||
Returns:
|
||||
(List[Dict[str, str]]): List of parsed requirements as dictionaries with `name` and `specifier` keys.
|
||||
"""
|
||||
|
||||
requirements = []
|
||||
for line in Path(file_path).read_text().splitlines():
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#'):
|
||||
line = line.split('#')[0].strip() # ignore inline comments
|
||||
match = re.match(r'([a-zA-Z0-9-_]+)([<>!=~]+.*)?', line)
|
||||
if match:
|
||||
requirements.append(SimpleNamespace(name=match[1], specifier=match[2].strip() if match[2] else ''))
|
||||
|
||||
return requirements
|
||||
|
||||
|
||||
def parse_version(v='0.0.0') -> tuple:
|
||||
"""
|
||||
Convert a version string to a tuple of integers, also returning any extra non-numeric string attached to the version.
|
||||
|
||||
Args:
|
||||
v (str): Version string, i.e. '2.0.1+cpu'
|
||||
|
||||
Returns:
|
||||
(tuple): Tuple of integers representing the numeric part of the version and the extra string, i.e. (2, 0, 1)
|
||||
"""
|
||||
correct = [True if x == '.' else x.isdigit() for x in v] # first non-number index
|
||||
if False in correct:
|
||||
v = v[:correct.index(False)]
|
||||
return tuple(map(int, v.split('.'))) # '2.0.1+cpu' -> (2, 0, 1)
|
||||
|
||||
|
||||
def is_ascii(s) -> bool:
|
||||
@ -121,24 +161,33 @@ def check_version(current: str = '0.0.0',
|
||||
# check if current version is between 20.04 (inclusive) and 22.04 (exclusive)
|
||||
check_version(current='21.10', required='>20.04,<22.04')
|
||||
"""
|
||||
current = pkg.parse_version(current)
|
||||
if not required:
|
||||
return True # in case required is '' or None
|
||||
|
||||
# import pkg_resources as pkg
|
||||
# current = pkg.parse_version(current)
|
||||
current = parse_version(current) # '1.2.3' -> (1, 2, 3)
|
||||
|
||||
constraints = re.findall(r'([<>!=]{1,2}\s*\d+\.\d+)', required) or [f'>={required}']
|
||||
|
||||
result = True
|
||||
for constraint in constraints:
|
||||
op, version = re.match(r'([<>!=]{1,2})\s*(\d+\.\d+)', constraint).groups()
|
||||
version = pkg.parse_version(version)
|
||||
if op == '==' and current != version:
|
||||
op, v = re.match(r'([<>!=]{1,2})\s*(\d+\.\d+)', constraint).groups()
|
||||
|
||||
# v = pkg.parse_version(v)
|
||||
v = parse_version(v) # '1.2.3' -> (1, 2, 3)
|
||||
|
||||
if op == '==' and current != v:
|
||||
result = False
|
||||
elif op == '!=' and current == version:
|
||||
elif op == '!=' and current == v:
|
||||
result = False
|
||||
elif op == '>=' and not (current >= version):
|
||||
elif op == '>=' and not (current >= v):
|
||||
result = False
|
||||
elif op == '<=' and not (current <= version):
|
||||
elif op == '<=' and not (current <= v):
|
||||
result = False
|
||||
elif op == '>' and not (current > version):
|
||||
elif op == '>' and not (current > v):
|
||||
result = False
|
||||
elif op == '<' and not (current < version):
|
||||
elif op == '<' and not (current < v):
|
||||
result = False
|
||||
if not result:
|
||||
warning_message = f'WARNING ⚠️ {name}{op}{required} is required, but {name}=={current} is currently installed'
|
||||
@ -177,7 +226,7 @@ def check_pip_update_available():
|
||||
with contextlib.suppress(Exception):
|
||||
from ultralytics import __version__
|
||||
latest = check_latest_pypi_version()
|
||||
if pkg.parse_version(__version__) < pkg.parse_version(latest): # update is available
|
||||
if check_version(__version__, f'<{latest}'): # check if current version is < latest version
|
||||
LOGGER.info(f'New https://pypi.org/project/ultralytics/{latest} available 😃 '
|
||||
f"Update with 'pip install -U ultralytics'")
|
||||
return True
|
||||
@ -253,29 +302,25 @@ def check_requirements(requirements=ROOT.parent / 'requirements.txt', exclude=()
|
||||
check_requirements(['numpy', 'ultralytics>=8.0.0'])
|
||||
```
|
||||
"""
|
||||
|
||||
prefix = colorstr('red', 'bold', 'requirements:')
|
||||
check_python() # check python version
|
||||
check_torchvision() # check torch-torchvision compatibility
|
||||
if isinstance(requirements, Path): # requirements.txt file
|
||||
file = requirements.resolve()
|
||||
assert file.exists(), f'{prefix} {file} not found, check failed.'
|
||||
with file.open() as f:
|
||||
requirements = [f'{x.name}{x.specifier}' for x in pkg.parse_requirements(f) if x.name not in exclude]
|
||||
requirements = [f'{x.name}{x.specifier}' for x in parse_requirements(file) if x.name not in exclude]
|
||||
elif isinstance(requirements, str):
|
||||
requirements = [requirements]
|
||||
|
||||
pkgs = []
|
||||
for r in requirements:
|
||||
r_stripped = r.split('/')[-1].replace('.git', '') # replace git+https://org/repo.git -> 'repo'
|
||||
match = re.match(r'([a-zA-Z0-9-_]+)([<>!=~]+.*)?', r_stripped)
|
||||
name, required = match[1], match[2].strip() if match[2] else ''
|
||||
try:
|
||||
pkg.require(r_stripped) # exception if requirements not met
|
||||
except pkg.DistributionNotFound:
|
||||
try: # attempt to import (slower but more accurate)
|
||||
import importlib
|
||||
importlib.import_module(next(pkg.parse_requirements(r_stripped)).name)
|
||||
except ImportError:
|
||||
pkgs.append(r)
|
||||
except pkg.VersionConflict:
|
||||
assert check_version(version(name), required) # exception if requirements not met
|
||||
except (AssertionError, PackageNotFoundError):
|
||||
pkgs.append(r)
|
||||
|
||||
s = ' '.join(f'"{x}"' for x in pkgs) # console string
|
||||
@ -430,6 +475,30 @@ def check_yolo(verbose=True, device=''):
|
||||
LOGGER.info(f'Setup complete ✅ {s}')
|
||||
|
||||
|
||||
def collect_system_info():
|
||||
"""Collect and print relevant system information including OS, Python, RAM, CPU, and CUDA."""
|
||||
|
||||
import psutil
|
||||
|
||||
from ultralytics.utils import ENVIRONMENT, is_git_dir
|
||||
from ultralytics.utils.torch_utils import get_cpu_info
|
||||
|
||||
ram_info = psutil.virtual_memory().total / (1024 ** 3) # Convert bytes to GB
|
||||
check_yolo()
|
||||
LOGGER.info(f"\n{'OS':<20}{platform.platform()}\n"
|
||||
f"{'Environment':<20}{ENVIRONMENT}\n"
|
||||
f"{'Python':<20}{sys.version.split()[0]}\n"
|
||||
f"{'Install':<20}{'git' if is_git_dir() else 'pip' if is_pip_package() else 'other'}\n"
|
||||
f"{'RAM':<20}{ram_info:.2f} GB\n"
|
||||
f"{'CPU':<20}{get_cpu_info()}\n"
|
||||
f"{'CUDA':<20}{torch.version.cuda if torch and torch.cuda.is_available() else None}\n")
|
||||
|
||||
for r in parse_requirements():
|
||||
current = version(r.name)
|
||||
is_met = '✅ ' if check_version(current, r.specifier) else '❌ '
|
||||
LOGGER.info(f'{r.name:<20}{is_met}{current}{r.specifier}')
|
||||
|
||||
|
||||
def check_amp(model):
|
||||
"""
|
||||
This function checks the PyTorch Automatic Mixed Precision (AMP) functionality of a YOLOv8 model.
|
||||
|
@ -76,11 +76,11 @@ def select_device(device='', batch=0, newline=False, verbose=True):
|
||||
verbose (bool, optional): If True, logs the device information. Defaults to True.
|
||||
|
||||
Returns:
|
||||
torch.device: Selected device.
|
||||
(torch.device): Selected device.
|
||||
|
||||
Raises:
|
||||
ValueError: If the specified device is not available or if the batch size is not a multiple of the number of
|
||||
devices when using multiple GPUs.
|
||||
devices when using multiple GPUs.
|
||||
|
||||
Examples:
|
||||
>>> select_device('cuda:0')
|
||||
|
Loading…
x
Reference in New Issue
Block a user