Files

1 line
24 KiB
JSON

{"repo": "brucemt/yolo8", "files": {"ultralytics/yolo/utils/__init__.py": {"f26c2f8e38712fc1088e511bf5befd430019c964": {"t": 1785595788.8061395, "n": 23698, "h": "b8ccdd09157c3275", "c": "# Ultralytics YOLO 🚀, GPL-3.0 license\n\nimport contextlib\nimport inspect\nimport logging.config\nimport os\nimport platform\nimport re\nimport subprocess\nimport sys\nimport tempfile\nimport threading\nimport uuid\nfrom pathlib import Path\nfrom types import SimpleNamespace\nfrom typing import Union\n\nimport cv2\nimport numpy as np\nimport torch\nimport yaml\n\nfrom ultralytics import __version__\n\n# PyTorch Multi-GPU DDP Constants\nRANK = int(os.getenv('RANK', -1))\nLOCAL_RANK = int(os.getenv('LOCAL_RANK', -1)) # https://pytorch.org/docs/stable/elastic/run.html\nWORLD_SIZE = int(os.getenv('WORLD_SIZE', 1))\n\n# Other Constants\nFILE = Path(__file__).resolve()\nROOT = FILE.parents[2] # YOLO\nDEFAULT_CFG_PATH = ROOT / 'yolo/cfg/default.yaml'\nNUM_THREADS = min(8, max(1, os.cpu_count() - 1)) # number of YOLOv5 multiprocessing threads\nAUTOINSTALL = str(os.getenv('YOLO_AUTOINSTALL', True)).lower() == 'true' # global auto-install mode\nVERBOSE = str(os.getenv('YOLO_VERBOSE', True)).lower() == 'true' # global verbose mode\nTQDM_BAR_FORMAT = '{l_bar}{bar:10}{r_bar}' # tqdm bar format\nLOGGING_NAME = 'ultralytics'\nMACOS, LINUX, WINDOWS = (platform.system() == x for x in ['Darwin', 'Linux', 'Windows']) # environment booleans\nHELP_MSG = \\\n \"\"\"\n Usage examples for running YOLOv8:\n\n 1. Install the ultralytics package:\n\n pip install ultralytics\n\n 2. Use the Python SDK:\n\n from ultralytics import YOLO\n\n # Load a model\n model = YOLO('yolov8n.yaml') # build a new model from scratch\n model = YOLO(\"yolov8n.pt\") # load a pretrained model (recommended for training)\n\n # Use the model\n results = model.train(data=\"coco128.yaml\", epochs=3) # train the model\n results = model.val() # evaluate model performance on the validation set\n results = model('https://ultralytics.com/images/bus.jpg') # predict on an image\n success = model.export(format='onnx') # export the model to ONNX format\n\n 3. Use the command line interface (CLI):\n\n YOLOv8 'yolo' CLI commands use the following syntax:\n\n yolo TASK MODE ARGS\n\n Where TASK (optional) is one of [detect, segment, classify]\n MODE (required) is one of [train, val, predict, export]\n ARGS (optional) are any number of custom 'arg=value' pairs like 'imgsz=320' that override defaults.\n See all ARGS at https://docs.ultralytics.com/usage/cfg or with 'yolo cfg'\n\n - Train a detection model for 10 epochs with an initial learning_rate of 0.01\n yolo detect train data=coco128.yaml model=yolov8n.pt epochs=10 lr0=0.01\n\n - Predict a YouTube video using a pretrained segmentation model at image size 320:\n yolo segment predict model=yolov8n-seg.pt source='https://youtu.be/Zgi9g1ksQHc' imgsz=320\n\n - Val a pretrained detection model at batch-size 1 and image size 640:\n yolo detect val model=yolov8n.pt data=coco128.yaml batch=1 imgsz=640\n\n - Export a YOLOv8n classification model to ONNX format at image size 224 by 128 (no TASK required)\n yolo export model=yolov8n-cls.pt format=onnx imgsz=224,128\n\n - Run special commands:\n yolo help\n yolo checks\n yolo version\n yolo settings\n yolo copy-cfg\n yolo cfg\n\n Docs: https://docs.ultralytics.com\n Community: https://community.ultralytics.com\n GitHub: https://github.com/ultralytics/ultralytics\n \"\"\"\n\n# Settings\ntorch.set_printoptions(linewidth=320, precision=4, profile='default')\nnp.set_printoptions(linewidth=320, formatter={'float_kind': '{:11.5g}'.format}) # format short g, %precision=5\ncv2.setNumThreads(0) # prevent OpenCV from multithreading (incompatible with PyTorch DataLoader)\nos.environ['NUMEXPR_MAX_THREADS'] = str(NUM_THREADS) # NumExpr max threads\nos.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8' # for deterministic training\n\n\nclass SimpleClass:\n \"\"\"\n Ultralytics SimpleClass is a base class providing helpful string representation, error reporting, and attribute\n access methods for easier debugging and usage.\n \"\"\"\n\n def __str__(self):\n \"\"\"Return a human-readable string representation of the object.\"\"\"\n attr = []\n for a in dir(self):\n v = getattr(self, a)\n if not callable(v) and not a.startswith('__'):\n if isinstance(v, SimpleClass):\n # Display only the module and class name for subclasses\n s = f'{a}: {v.__module__}.{v.__class__.__name__} object'\n else:\n s = f'{a}: {repr(v)}'\n attr.append(s)\n return f'{self.__module__}.{self.__class__.__name__} object with attributes:\\n\\n' + '\\n'.join(attr)\n\n def __repr__(self):\n \"\"\"Return a machine-readable string representation of the object.\"\"\"\n return self.__str__()\n\n def __getattr__(self, attr):\n \"\"\"Custom attribute access error message with helpful information.\"\"\"\n name = self.__class__.__name__\n raise AttributeError(f\"'{name}' object has no attribute '{attr}'. See valid attributes below.\\n{self.__doc__}\")\n\n\nclass IterableSimpleNamespace(SimpleNamespace):\n \"\"\"\n Ultralytics IterableSimpleNamespace is an extension class of SimpleNamespace that adds iterable functionality and\n enables usage with dict() and for loops.\n \"\"\"\n\n def __iter__(self):\n \"\"\"Return an iterator of key-value pairs from the namespace's attributes.\"\"\"\n return iter(vars(self).items())\n\n def __str__(self):\n \"\"\"Return a human-readable string representation of the object.\"\"\"\n return '\\n'.join(f'{k}={v}' for k, v in vars(self).items())\n\n def __getattr__(self, attr):\n \"\"\"Custom attribute access error message with helpful information.\"\"\"\n name = self.__class__.__name__\n raise AttributeError(f\"\"\"\n '{name}' object has no attribute '{attr}'. This may be caused by a modified or out of date ultralytics\n 'default.yaml' file.\\nPlease update your code with 'pip install -U ultralytics' and if necessary replace\n {DEFAULT_CFG_PATH} with the latest version from\n https://github.com/ultralytics/ultralytics/blob/main/ultralytics/yolo/cfg/default.yaml\n \"\"\")\n\n def get(self, key, default=None):\n \"\"\"Return the value of the specified key if it exists; otherwise, return the default value.\"\"\"\n return getattr(self, key, default)\n\n\ndef set_logging(name=LOGGING_NAME, verbose=True):\n # sets up logging for the given name\n rank = int(os.getenv('RANK', -1)) # rank in world for Multi-GPU trainings\n level = logging.INFO if verbose and rank in (-1, 0) else logging.ERROR\n logging.config.dictConfig({\n 'version': 1,\n 'disable_existing_loggers': False,\n 'formatters': {\n name: {\n 'format': '%(message)s'}},\n 'handlers': {\n name: {\n 'class': 'logging.StreamHandler',\n 'formatter': name,\n 'level': level}},\n 'loggers': {\n name: {\n 'level': level,\n 'handlers': [name],\n 'propagate': False}}})\n\n\n# Set logger\nset_logging(LOGGING_NAME, verbose=VERBOSE) # run before defining LOGGER\nLOGGER = logging.getLogger(LOGGING_NAME) # define globally (used in train.py, val.py, detect.py, etc.)\nif WINDOWS: # emoji-safe logging\n info_fn, warning_fn = LOGGER.info, LOGGER.warning\n setattr(LOGGER, info_fn.__name__, lambda x: info_fn(emojis(x)))\n setattr(LOGGER, warning_fn.__name__, lambda x: warning_fn(emojis(x)))\n\n\ndef yaml_save(file='data.yaml', data=None):\n \"\"\"\n Save YAML data to a file.\n\n Args:\n file (str, optional): File name. Default is 'data.yaml'.\n data (dict, optional): Data to save in YAML format. Default is None.\n\n Returns:\n None: Data is saved to the specified file.\n \"\"\"\n file = Path(file)\n if not file.parent.exists():\n # Create parent directories if they don't exist\n file.parent.mkdir(parents=True, exist_ok=True)\n\n with open(file, 'w') as f:\n # Dump data to file in YAML format, converting Path objects to strings\n yaml.safe_dump({k: str(v) if isinstance(v, Path) else v\n for k, v in data.items()},\n f,\n sort_keys=False,\n allow_unicode=True)\n\n\ndef yaml_load(file='data.yaml', append_filename=False):\n \"\"\"\n Load YAML data from a file.\n\n Args:\n file (str, optional): File name. Default is 'data.yaml'.\n append_filename (bool): Add the YAML filename to the YAML dictionary. Default is False.\n\n Returns:\n dict: YAML data and file name.\n \"\"\"\n with open(file, errors='ignore', encoding='utf-8') as f:\n s = f.read() # string\n\n # Remove special characters\n if not s.isprintable():\n s = re.sub(r'[^\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\U00010000-\\U0010ffff]+', '', s)\n\n # Add YAML filename to dict and return\n return {**yaml.safe_load(s), 'yaml_file': str(file)} if append_filename else yaml.safe_load(s)\n\n\ndef yaml_print(yaml_file: Union[str, Path, dict]) -> None:\n \"\"\"\n Pretty prints a yaml file or a yaml-formatted dictionary.\n\n Args:\n yaml_file: The file path of the yaml file or a yaml-formatted dictionary.\n\n Returns:\n None\n \"\"\"\n yaml_dict = yaml_load(yaml_file) if isinstance(yaml_file, (str, Path)) else yaml_file\n dump = yaml.dump(yaml_dict, sort_keys=False, allow_unicode=True)\n LOGGER.info(f\"Printing '{colorstr('bold', 'black', yaml_file)}'\\n\\n{dump}\")\n\n\n# Default configuration\nDEFAULT_CFG_DICT = yaml_load(DEFAULT_CFG_PATH)\nfor k, v in DEFAULT_CFG_DICT.items():\n if isinstance(v, str) and v.lower() == 'none':\n DEFAULT_CFG_DICT[k] = None\nDEFAULT_CFG_KEYS = DEFAULT_CFG_DICT.keys()\nDEFAULT_CFG = IterableSimpleNamespace(**DEFAULT_CFG_DICT)\n\n\ndef is_colab():\n \"\"\"\n Check if the current script is running inside a Google Colab notebook.\n\n Returns:\n bool: True if running inside a Colab notebook, False otherwise.\n \"\"\"\n return 'COLAB_RELEASE_TAG' in os.environ or 'COLAB_BACKEND_VERSION' in os.environ\n\n\ndef is_kaggle():\n \"\"\"\n Check if the current script is running inside a Kaggle kernel.\n\n Returns:\n bool: True if running inside a Kaggle kernel, False otherwise.\n \"\"\"\n return os.environ.get('PWD') == '/kaggle/working' and os.environ.get('KAGGLE_URL_BASE') == 'https://www.kaggle.com'\n\n\ndef is_jupyter():\n \"\"\"\n Check if the current script is running inside a Jupyter Notebook.\n Verified on Colab, Jupyterlab, Kaggle, Paperspace.\n\n Returns:\n bool: True if running inside a Jupyter Notebook, False otherwise.\n \"\"\"\n with contextlib.suppress(Exception):\n from IPython import get_ipython\n return get_ipython() is not None\n return False\n\n\ndef is_docker() -> bool:\n \"\"\"\n Determine if the script is running inside a Docker container.\n\n Returns:\n bool: True if the script is running inside a Docker container, False otherwise.\n \"\"\"\n file = Path('/proc/self/cgroup')\n if file.exists():\n with open(file) as f:\n return 'docker' in f.read()\n else:\n return False\n\n\ndef is_online() -> bool:\n \"\"\"\n Check internet connectivity by attempting to connect to a known online host.\n\n Returns:\n bool: True if connection is successful, False otherwise.\n \"\"\"\n import socket\n\n for server in '1.1.1.1', '8.8.8.8', '223.5.5.5': # Cloudflare, Google, AliDNS:\n try:\n socket.create_connection((server, 53), timeout=2) # connect to (server, port=53)\n return True\n except (socket.timeout, socket.gaierror, OSError):\n continue\n return False\n\n\nONLINE = is_online()\n\n\ndef is_pip_package(filepath: str = __name__) -> bool:\n \"\"\"\n Determines if the file at the given filepath is part of a pip package.\n\n Args:\n filepath (str): The filepath to check.\n\n Returns:\n bool: True if the file is part of a pip package, False otherwise.\n \"\"\"\n import importlib.util\n\n # Get the spec for the module\n spec = importlib.util.find_spec(filepath)\n\n # Return whether the spec is not None and the origin is not None (indicating it is a package)\n return spec is not None and spec.origin is not None\n\n\ndef is_dir_writeable(dir_path: Union[str, Path]) -> bool:\n \"\"\"\n Check if a directory is writeable.\n\n Args:\n dir_path (str) or (Path): The path to the directory.\n\n Returns:\n bool: True if the directory is writeable, False otherwise.\n \"\"\"\n try:\n with tempfile.TemporaryFile(dir=dir_path):\n pass\n return True\n except OSError:\n return False\n\n\ndef is_pytest_running():\n \"\"\"\n Determines whether pytest is currently running or not.\n\n Returns:\n (bool): True if pytest is running, False otherwise.\n \"\"\"\n return ('PYTEST_CURRENT_TEST' in os.environ) or ('pytest' in sys.modules) or ('pytest' in Path(sys.argv[0]).stem)\n\n\ndef is_github_actions_ci() -> bool:\n \"\"\"\n Determine if the current environment is a GitHub Actions CI Python runner.\n\n Returns:\n (bool): True if the current environment is a GitHub Actions CI Python runner, False otherwise.\n \"\"\"\n return 'GITHUB_ACTIONS' in os.environ and 'RUNNER_OS' in os.environ and 'RUNNER_TOOL_CACHE' in os.environ\n\n\ndef is_git_dir():\n \"\"\"\n Determines whether the current file is part of a git repository.\n If the current file is not part of a git repository, returns None.\n\n Returns:\n (bool): True if current file is part of a git repository.\n \"\"\"\n return get_git_dir() is not None\n\n\ndef get_git_dir():\n \"\"\"\n Determines whether the current file is part of a git repository and if so, returns the repository root directory.\n If the current file is not part of a git repository, returns None.\n\n Returns:\n (Path) or (None): Git root directory if found or None if not found.\n \"\"\"\n for d in Path(__file__).parents:\n if (d / '.git').is_dir():\n return d\n return None # no .git dir found\n\n\ndef get_git_origin_url():\n \"\"\"\n Retrieves the origin URL of a git repository.\n\n Returns:\n (str) or (None): The origin URL of the git repository.\n \"\"\"\n if is_git_dir():\n with contextlib.suppress(subprocess.CalledProcessError):\n origin = subprocess.check_output(['git', 'config', '--get', 'remote.origin.url'])\n return origin.decode().strip()\n return None # if not git dir or on error\n\n\ndef get_git_branch():\n \"\"\"\n Returns the current git branch name. If not in a git repository, returns None.\n\n Returns:\n (str) or (None): The current git branch name.\n \"\"\"\n if is_git_dir():\n with contextlib.suppress(subprocess.CalledProcessError):\n origin = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])\n return origin.decode().strip()\n return None # if not git dir or on error\n\n\ndef get_default_args(func):\n \"\"\"Returns a dictionary of default arguments for a function.\n\n Args:\n func (callable): The function to inspect.\n\n Returns:\n dict: A dictionary where each key is a parameter name, and each value is the default value of that parameter.\n \"\"\"\n signature = inspect.signature(func)\n return {k: v.default for k, v in signature.parameters.items() if v.default is not inspect.Parameter.empty}\n\n\ndef get_user_config_dir(sub_dir='Ultralytics'):\n \"\"\"\n Get the user config directory.\n\n Args:\n sub_dir (str): The name of the subdirectory to create.\n\n Returns:\n Path: The path to the user config directory.\n \"\"\"\n # Return the appropriate config directory for each operating system\n if WINDOWS:\n path = Path.home() / 'AppData' / 'Roaming' / sub_dir\n elif MACOS: # macOS\n path = Path.home() / 'Library' / 'Application Support' / sub_dir\n elif LINUX:\n path = Path.home() / '.config' / sub_dir\n else:\n raise ValueError(f'Unsupported operating system: {platform.system()}')\n\n # GCP and AWS lambda fix, only /tmp is writeable\n if not is_dir_writeable(str(path.parent)):\n path = Path('/tmp') / sub_dir\n\n # Create the subdirectory if it does not exist\n path.mkdir(parents=True, exist_ok=True)\n\n return path\n\n\nUSER_CONFIG_DIR = Path(os.getenv('YOLO_CONFIG_DIR', get_user_config_dir())) # Ultralytics settings dir\n\n\ndef emojis(string=''):\n # Return platform-dependent emoji-safe version of string\n return string.encode().decode('ascii', 'ignore') if WINDOWS else string\n\n\ndef colorstr(*input):\n # Colors a string https://en.wikipedia.org/wiki/ANSI_escape_code, i.e. colorstr('blue', 'hello world')\n *args, string = input if len(input) > 1 else ('blue', 'bold', input[0]) # color arguments, string\n colors = {\n 'black': '\\033[30m', # basic colors\n 'red': '\\033[31m',\n 'green': '\\033[32m',\n 'yellow': '\\033[33m',\n 'blue': '\\033[34m',\n 'magenta': '\\033[35m',\n 'cyan': '\\033[36m',\n 'white': '\\033[37m',\n 'bright_black': '\\033[90m', # bright colors\n 'bright_red': '\\033[91m',\n 'bright_green': '\\033[92m',\n 'bright_yellow': '\\033[93m',\n 'bright_blue': '\\033[94m',\n 'bright_magenta': '\\033[95m',\n 'bright_cyan': '\\033[96m',\n 'bright_white': '\\033[97m',\n 'end': '\\033[0m', # misc\n 'bold': '\\033[1m',\n 'underline': '\\033[4m'}\n return ''.join(colors[x] for x in args) + f'{string}' + colors['end']\n\n\nclass TryExcept(contextlib.ContextDecorator):\n # YOLOv8 TryExcept class. Usage: @TryExcept() decorator or 'with TryExcept():' context manager\n def __init__(self, msg='', verbose=True):\n self.msg = msg\n self.verbose = verbose\n\n def __enter__(self):\n pass\n\n def __exit__(self, exc_type, value, traceback):\n if self.verbose and value:\n print(emojis(f\"{self.msg}{': ' if self.msg else ''}{value}\"))\n return True\n\n\ndef threaded(func):\n # Multi-threads a target function and returns thread. Usage: @threaded decorator\n def wrapper(*args, **kwargs):\n thread = threading.Thread(target=func, args=args, kwargs=kwargs, daemon=True)\n thread.start()\n return thread\n\n return wrapper\n\n\ndef set_sentry():\n \"\"\"\n Initialize the Sentry SDK for error tracking and reporting if pytest is not currently running.\n \"\"\"\n\n def before_send(event, hint):\n if 'exc_info' in hint:\n exc_type, exc_value, tb = hint['exc_info']\n if exc_type in (KeyboardInterrupt, FileNotFoundError) \\\n or 'out of memory' in str(exc_value):\n return None # do not send event\n\n event['tags'] = {\n 'sys_argv': sys.argv[0],\n 'sys_argv_name': Path(sys.argv[0]).name,\n 'install': 'git' if is_git_dir() else 'pip' if is_pip_package() else 'other',\n 'os': ENVIRONMENT}\n return event\n\n if SETTINGS['sync'] and \\\n RANK in (-1, 0) and \\\n Path(sys.argv[0]).name == 'yolo' and \\\n not TESTS_RUNNING and \\\n ONLINE and \\\n ((is_pip_package() and not is_git_dir()) or\n (get_git_origin_url() == 'https://github.com/ultralytics/ultralytics.git' and get_git_branch() == 'main')):\n\n import sentry_sdk # noqa\n sentry_sdk.init(\n dsn='https://f805855f03bb4363bc1e16cb7d87b654@o4504521589325824.ingest.sentry.io/4504521592406016',\n debug=False,\n traces_sample_rate=1.0,\n release=__version__,\n environment='production', # 'dev' or 'production'\n before_send=before_send,\n ignore_errors=[KeyboardInterrupt, FileNotFoundError])\n sentry_sdk.set_user({'id': SETTINGS['uuid']})\n\n # Disable all sentry logging\n for logger in 'sentry_sdk', 'sentry_sdk.errors':\n logging.getLogger(logger).setLevel(logging.CRITICAL)\n\n\ndef get_settings(file=USER_CONFIG_DIR / 'settings.yaml', version='0.0.3'):\n \"\"\"\n Loads a global Ultralytics settings YAML file or creates one with default values if it does not exist.\n\n Args:\n file (Path): Path to the Ultralytics settings YAML file. Defaults to 'settings.yaml' in the USER_CONFIG_DIR.\n version (str): Settings version. If min settings version not met, new default settings will be saved.\n\n Returns:\n dict: Dictionary of settings key-value pairs.\n \"\"\"\n import hashlib\n\n from ultralytics.yolo.utils.checks import check_version\n from ultralytics.yolo.utils.torch_utils import torch_distributed_zero_first\n\n git_dir = get_git_dir()\n root = git_dir or Path()\n datasets_root = (root.parent if git_dir and is_dir_writeable(root.parent) else root).resolve()\n defaults = {\n 'datasets_dir': str(datasets_root / 'datasets'), # default datasets directory.\n 'weights_dir': str(root / 'weights'), # default weights directory.\n 'runs_dir': str(root / 'runs'), # default runs directory.\n 'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(), # anonymized uuid hash\n 'sync': True, # sync analytics to help with YOLO development\n 'api_key': '', # Ultralytics HUB API key (https://hub.ultralytics.com/)\n 'settings_version': version} # Ultralytics settings version\n\n with torch_distributed_zero_first(RANK):\n if not file.exists():\n yaml_save(file, defaults)\n settings = yaml_load(file)\n\n # Check that settings keys and types match defaults\n correct = \\\n settings \\\n and settings.keys() == defaults.keys() \\\n and all(type(a) == type(b) for a, b in zip(settings.values(), defaults.values())) \\\n and check_version(settings['settings_version'], version)\n if not correct:\n LOGGER.warning('WARNING ⚠️ Ultralytics settings reset to defaults. This is normal and may be due to a '\n 'recent ultralytics package update, but may have overwritten previous settings. '\n f\"\\nView and update settings with 'yolo settings' or at '{file}'\")\n settings = defaults # merge **defaults with **settings (prefer **settings)\n yaml_save(file, settings) # save updated defaults\n\n return settings\n\n\ndef set_settings(kwargs, file=USER_CONFIG_DIR / 'settings.yaml'):\n \"\"\"\n Function that runs on a first-time ultralytics package installation to set up global settings and create necessary\n directories.\n \"\"\"\n SETTINGS.update(kwargs)\n yaml_save(file, SETTINGS)\n\n\ndef deprecation_warn(arg, new_arg, version=None):\n if not version:\n version = float(__version__[0:3]) + 0.2 # deprecate after 2nd major release\n LOGGER.warning(\n f'WARNING: `{arg}` is deprecated and will be removed in upcoming major release {version}. Use `{new_arg}` instead'\n )\n\n\n# Run below code on yolo/utils init ------------------------------------------------------------------------------------\n\n# Check first-install steps\nPREFIX = colorstr('Ultralytics: ')\nSETTINGS = get_settings()\nDATASETS_DIR = Path(SETTINGS['datasets_dir']) # global datasets directory\nENVIRONMENT = 'Colab' if is_colab() else 'Kaggle' if is_kaggle() else 'Jupyter' if is_jupyter() else \\\n 'Docker' if is_docker() else platform.system()\nTESTS_RUNNING = is_pytest_running() or is_github_actions_ci()\nset_sentry()\n"}}}}