|
|
@ -8,10 +8,8 @@ from pathlib import Path
|
|
|
|
from types import SimpleNamespace
|
|
|
|
from types import SimpleNamespace
|
|
|
|
from typing import Dict, List, Union
|
|
|
|
from typing import Dict, List, Union
|
|
|
|
|
|
|
|
|
|
|
|
from ultralytics.yolo.utils import (DEFAULT_CFG, DEFAULT_CFG_DICT, DEFAULT_CFG_PATH, LOGGER, PREFIX, ROOT,
|
|
|
|
from ultralytics.yolo.utils import (DEFAULT_CFG, DEFAULT_CFG_DICT, DEFAULT_CFG_PATH, LOGGER, ROOT, USER_CONFIG_DIR,
|
|
|
|
USER_CONFIG_DIR, IterableSimpleNamespace, __version__, colorstr, emojis, yaml_load,
|
|
|
|
IterableSimpleNamespace, __version__, checks, colorstr, yaml_load, yaml_print)
|
|
|
|
yaml_print)
|
|
|
|
|
|
|
|
from ultralytics.yolo.utils.checks import check_yolo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CLI_HELP_MSG = \
|
|
|
|
CLI_HELP_MSG = \
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -83,7 +81,7 @@ def cfg2dict(cfg):
|
|
|
|
return cfg
|
|
|
|
return cfg
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG, overrides: Dict = None):
|
|
|
|
def get_cfg(cfg: Union[str, Path, Dict, SimpleNamespace] = DEFAULT_CFG_DICT, overrides: Dict = None):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Load and merge configuration data from a file or dictionary.
|
|
|
|
Load and merge configuration data from a file or dictionary.
|
|
|
|
|
|
|
|
|
|
|
@ -198,17 +196,23 @@ def entrypoint(debug=''):
|
|
|
|
LOGGER.info(CLI_HELP_MSG)
|
|
|
|
LOGGER.info(CLI_HELP_MSG)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# Add tasks, modes, special, and special with dash keys, i.e. -help, --help
|
|
|
|
# Define tasks and modes
|
|
|
|
tasks = 'detect', 'segment', 'classify'
|
|
|
|
tasks = 'detect', 'segment', 'classify'
|
|
|
|
modes = 'train', 'val', 'predict', 'export'
|
|
|
|
modes = 'train', 'val', 'predict', 'export'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Define special commands
|
|
|
|
special = {
|
|
|
|
special = {
|
|
|
|
'help': lambda: LOGGER.info(CLI_HELP_MSG),
|
|
|
|
'help': lambda: LOGGER.info(CLI_HELP_MSG),
|
|
|
|
'checks': check_yolo,
|
|
|
|
'checks': checks.check_yolo,
|
|
|
|
'version': lambda: LOGGER.info(__version__),
|
|
|
|
'version': lambda: LOGGER.info(__version__),
|
|
|
|
'settings': lambda: yaml_print(USER_CONFIG_DIR / 'settings.yaml'),
|
|
|
|
'settings': lambda: yaml_print(USER_CONFIG_DIR / 'settings.yaml'),
|
|
|
|
'cfg': lambda: yaml_print(DEFAULT_CFG_PATH),
|
|
|
|
'cfg': lambda: yaml_print(DEFAULT_CFG_PATH),
|
|
|
|
'copy-cfg': copy_default_cfg}
|
|
|
|
'copy-cfg': copy_default_cfg}
|
|
|
|
FULL_ARGS_DICT = {**DEFAULT_CFG_DICT, **{k: None for k in tasks}, **{k: None for k in modes}, **special}
|
|
|
|
full_args_dict = {**DEFAULT_CFG_DICT, **{k: None for k in tasks}, **{k: None for k in modes}, **special}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Define common mis-uses of special commands, i.e. -h, -help, --help
|
|
|
|
|
|
|
|
special.update({k[0]: v for k, v in special.items()}) # singular
|
|
|
|
|
|
|
|
special.update({k[:-1]: v for k, v in special.items() if len(k) > 1 and k.endswith('s')}) # singular
|
|
|
|
special = {**special, **{f'-{k}': v for k, v in special.items()}, **{f'--{k}': v for k, v in special.items()}}
|
|
|
|
special = {**special, **{f'-{k}': v for k, v in special.items()}, **{f'--{k}': v for k, v in special.items()}}
|
|
|
|
|
|
|
|
|
|
|
|
overrides = {} # basic overrides, i.e. imgsz=320
|
|
|
|
overrides = {} # basic overrides, i.e. imgsz=320
|
|
|
@ -219,7 +223,7 @@ def entrypoint(debug=''):
|
|
|
|
k, v = a.split('=', 1) # split on first '=' sign
|
|
|
|
k, v = a.split('=', 1) # split on first '=' sign
|
|
|
|
assert v, f"missing '{k}' value"
|
|
|
|
assert v, f"missing '{k}' value"
|
|
|
|
if k == 'cfg': # custom.yaml passed
|
|
|
|
if k == 'cfg': # custom.yaml passed
|
|
|
|
LOGGER.info(f"{PREFIX}Overriding {DEFAULT_CFG_PATH} with {v}")
|
|
|
|
LOGGER.info(f"Overriding {DEFAULT_CFG_PATH} with {v}")
|
|
|
|
overrides = {k: val for k, val in yaml_load(v).items() if k != 'cfg'}
|
|
|
|
overrides = {k: val for k, val in yaml_load(v).items() if k != 'cfg'}
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
if v.lower() == 'none':
|
|
|
|
if v.lower() == 'none':
|
|
|
@ -233,7 +237,7 @@ def entrypoint(debug=''):
|
|
|
|
v = eval(v)
|
|
|
|
v = eval(v)
|
|
|
|
overrides[k] = v
|
|
|
|
overrides[k] = v
|
|
|
|
except (NameError, SyntaxError, ValueError, AssertionError) as e:
|
|
|
|
except (NameError, SyntaxError, ValueError, AssertionError) as e:
|
|
|
|
check_cfg_mismatch(FULL_ARGS_DICT, {a: ""}, e)
|
|
|
|
check_cfg_mismatch(full_args_dict, {a: ""}, e)
|
|
|
|
|
|
|
|
|
|
|
|
elif a in tasks:
|
|
|
|
elif a in tasks:
|
|
|
|
overrides['task'] = a
|
|
|
|
overrides['task'] = a
|
|
|
@ -248,7 +252,7 @@ def entrypoint(debug=''):
|
|
|
|
raise SyntaxError(f"'{colorstr('red', 'bold', a)}' is a valid YOLO argument but is missing an '=' sign "
|
|
|
|
raise SyntaxError(f"'{colorstr('red', 'bold', a)}' is a valid YOLO argument but is missing an '=' sign "
|
|
|
|
f"to set its value, i.e. try '{a}={DEFAULT_CFG_DICT[a]}'\n{CLI_HELP_MSG}")
|
|
|
|
f"to set its value, i.e. try '{a}={DEFAULT_CFG_DICT[a]}'\n{CLI_HELP_MSG}")
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
check_cfg_mismatch(FULL_ARGS_DICT, {a: ""})
|
|
|
|
check_cfg_mismatch(full_args_dict, {a: ""})
|
|
|
|
|
|
|
|
|
|
|
|
# Defaults
|
|
|
|
# Defaults
|
|
|
|
task2model = dict(detect='yolov8n.pt', segment='yolov8n-seg.pt', classify='yolov8n-cls.pt')
|
|
|
|
task2model = dict(detect='yolov8n.pt', segment='yolov8n-seg.pt', classify='yolov8n-cls.pt')
|
|
|
@ -261,9 +265,9 @@ def entrypoint(debug=''):
|
|
|
|
LOGGER.warning(f"WARNING ⚠️ 'mode' is missing. Valid modes are {modes}. Using default 'mode={mode}'.")
|
|
|
|
LOGGER.warning(f"WARNING ⚠️ 'mode' is missing. Valid modes are {modes}. Using default 'mode={mode}'.")
|
|
|
|
elif mode not in modes:
|
|
|
|
elif mode not in modes:
|
|
|
|
if mode != 'checks':
|
|
|
|
if mode != 'checks':
|
|
|
|
raise ValueError(emojis(f"ERROR ❌ Invalid 'mode={mode}'. Valid modes are {modes}."))
|
|
|
|
raise ValueError(f"Invalid 'mode={mode}'. Valid modes are {modes}.")
|
|
|
|
LOGGER.warning("WARNING ⚠️ 'yolo mode=checks' is deprecated. Use 'yolo checks' instead.")
|
|
|
|
LOGGER.warning("WARNING ⚠️ 'yolo mode=checks' is deprecated. Use 'yolo checks' instead.")
|
|
|
|
check_yolo()
|
|
|
|
checks.check_yolo()
|
|
|
|
return
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# Model
|
|
|
|
# Model
|
|
|
@ -304,7 +308,7 @@ def entrypoint(debug=''):
|
|
|
|
def copy_default_cfg():
|
|
|
|
def copy_default_cfg():
|
|
|
|
new_file = Path.cwd() / DEFAULT_CFG_PATH.name.replace('.yaml', '_copy.yaml')
|
|
|
|
new_file = Path.cwd() / DEFAULT_CFG_PATH.name.replace('.yaml', '_copy.yaml')
|
|
|
|
shutil.copy2(DEFAULT_CFG_PATH, new_file)
|
|
|
|
shutil.copy2(DEFAULT_CFG_PATH, new_file)
|
|
|
|
LOGGER.info(f"{PREFIX}{DEFAULT_CFG_PATH} copied to {new_file}\n"
|
|
|
|
LOGGER.info(f"{DEFAULT_CFG_PATH} copied to {new_file}\n"
|
|
|
|
f"Example YOLO command with this new custom cfg:\n yolo cfg='{new_file}' imgsz=320 batch=8")
|
|
|
|
f"Example YOLO command with this new custom cfg:\n yolo cfg='{new_file}' imgsz=320 batch=8")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|