From e2b04dc85340a16b61ea13a3f1aea2af3d5a0329 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sun, 25 Aug 2024 05:05:30 +0800 Subject: [PATCH 1/2] TQDM, SimpleClass, IterableSimpleNamespace docstrings (#15795) Signed-off-by: UltralyticsAssistant Co-authored-by: UltralyticsAssistant --- .github/workflows/docs.yml | 4 +- ultralytics/utils/__init__.py | 126 +++++++++++++++++++++++++++++++--- 2 files changed, 120 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 29a95ccf4..596f3e5fc 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -44,11 +44,13 @@ jobs: cache: "pip" # caching pip dependencies - name: Install Dependencies run: pip install ruff black tqdm mkdocs-material "mkdocstrings[python]" mkdocs-jupyter mkdocs-redirects mkdocs-ultralytics-plugin mkdocs-macros-plugin + - name: Ruff fixes + continue-on-error: true + run: ruff check --fix --fix-unsafe --select D --ignore=D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 . - name: Update Docs Reference Section and Push Changes if: github.event_name == 'pull_request_target' run: | python docs/build_reference.py - ruff check --fix --fix-unsafe --select D --ignore=D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 . || true git pull origin ${{ github.head_ref || github.ref }} git add . git reset HEAD -- .github/workflows/ # workflow changes are not permitted with default token diff --git a/ultralytics/utils/__init__.py b/ultralytics/utils/__init__.py index 637e8a493..c195b862a 100644 --- a/ultralytics/utils/__init__.py +++ b/ultralytics/utils/__init__.py @@ -116,18 +116,46 @@ os.environ["KINETO_LOG_LEVEL"] = "5" # suppress verbose PyTorch profiler output class TQDM(tqdm_original): """ - Custom Ultralytics tqdm class with different default arguments. + A custom TQDM progress bar class that extends the original tqdm functionality. - Args: - *args (list): Positional arguments passed to original tqdm. - **kwargs (any): Keyword arguments, with custom defaults applied. + This class modifies the behavior of the original tqdm progress bar based on global settings and provides + additional customization options. + + Attributes: + disable (bool): Whether to disable the progress bar. Determined by the global VERBOSE setting and + any passed 'disable' argument. + bar_format (str): The format string for the progress bar. Uses the global TQDM_BAR_FORMAT if not + explicitly set. + + Methods: + __init__: Initializes the TQDM object with custom settings. + + Examples: + >>> from ultralytics.utils import TQDM + >>> for i in TQDM(range(100)): + ... # Your processing code here + ... pass """ def __init__(self, *args, **kwargs): """ - Initialize custom Ultralytics tqdm class with different default arguments. + Initializes a custom TQDM progress bar. - Note these can still be overridden when calling TQDM. + This class extends the original tqdm class to provide customized behavior for Ultralytics projects. + + Args: + *args (Any): Variable length argument list to be passed to the original tqdm constructor. + **kwargs (Any): Arbitrary keyword arguments to be passed to the original tqdm constructor. + + Notes: + - The progress bar is disabled if VERBOSE is False or if 'disable' is explicitly set to True in kwargs. + - The default bar format is set to TQDM_BAR_FORMAT unless overridden in kwargs. + + Examples: + >>> from ultralytics.utils import TQDM + >>> for i in TQDM(range(100)): + ... # Your code here + ... pass """ kwargs["disable"] = not VERBOSE or kwargs.get("disable", False) # logical 'and' with default value if passed kwargs.setdefault("bar_format", TQDM_BAR_FORMAT) # override default value if passed @@ -135,7 +163,34 @@ class TQDM(tqdm_original): class SimpleClass: - """A base class providing string representation and attribute access functionality for Ultralytics objects.""" + """ + A simple base class for creating objects with string representations of their attributes. + + This class provides a foundation for creating objects that can be easily printed or represented as strings, + showing all their non-callable attributes. It's useful for debugging and introspection of object states. + + Methods: + __str__: Returns a human-readable string representation of the object. + __repr__: Returns a machine-readable string representation of the object. + __getattr__: Provides a custom attribute access error message with helpful information. + + Examples: + >>> class MyClass(SimpleClass): + ... def __init__(self): + ... self.x = 10 + ... self.y = "hello" + >>> obj = MyClass() + >>> print(obj) + __main__.MyClass object with attributes: + + x: 10 + y: 'hello' + + Notes: + - This class is designed to be subclassed. It provides a convenient way to inspect object attributes. + - The string representation includes the module and class name of the object. + - Callable attributes and attributes starting with an underscore are excluded from the string representation. + """ def __str__(self): """Return a human-readable string representation of the object.""" @@ -162,7 +217,39 @@ class SimpleClass: class IterableSimpleNamespace(SimpleNamespace): - """Iterable SimpleNamespace subclass for key-value attribute iteration and custom error handling.""" + """ + An iterable SimpleNamespace class that provides enhanced functionality for attribute access and iteration. + + This class extends the SimpleNamespace class with additional methods for iteration, string representation, + and attribute access. It is designed to be used as a convenient container for storing and accessing + configuration parameters. + + Methods: + __iter__: Returns an iterator of key-value pairs from the namespace's attributes. + __str__: Returns a human-readable string representation of the object. + __getattr__: Provides a custom attribute access error message with helpful information. + get: Retrieves the value of a specified key, or a default value if the key doesn't exist. + + Examples: + >>> cfg = IterableSimpleNamespace(a=1, b=2, c=3) + >>> for k, v in cfg: + ... print(f"{k}: {v}") + a: 1 + b: 2 + c: 3 + >>> print(cfg) + a=1 + b=2 + c=3 + >>> cfg.get("b") + 2 + >>> cfg.get("d", "default") + 'default' + + Notes: + This class is particularly useful for storing configuration parameters in a more accessible + and iterable format compared to a standard dictionary. + """ def __iter__(self): """Return an iterator of key-value pairs from the namespace's attributes.""" @@ -235,7 +322,28 @@ def plt_settings(rcparams=None, backend="Agg"): def set_logging(name="LOGGING_NAME", verbose=True): - """Sets up logging with UTF-8 encoding and configurable verbosity for Ultralytics YOLO.""" + """ + Sets up logging with UTF-8 encoding and configurable verbosity. + + This function configures logging for the Ultralytics library, setting the appropriate logging level and + formatter based on the verbosity flag and the current process rank. It handles special cases for Windows + environments where UTF-8 encoding might not be the default. + + Args: + name (str): Name of the logger. Defaults to "LOGGING_NAME". + verbose (bool): Flag to set logging level to INFO if True, ERROR otherwise. Defaults to True. + + Examples: + >>> set_logging(name="ultralytics", verbose=True) + >>> logger = logging.getLogger("ultralytics") + >>> logger.info("This is an info message") + + Notes: + - On Windows, this function attempts to reconfigure stdout to use UTF-8 encoding if possible. + - If reconfiguration is not possible, it falls back to a custom formatter that handles non-UTF-8 environments. + - The function sets up a StreamHandler with the appropriate formatter and level. + - The logger's propagate flag is set to False to prevent duplicate logging in parent loggers. + """ level = logging.INFO if verbose and RANK in {-1, 0} else logging.ERROR # rank in world for Multi-GPU trainings # Configure the console (stdout) encoding to UTF-8, with checks for compatibility From dc15242cbdc56887a68e78c864119f6918bca0de Mon Sep 17 00:00:00 2001 From: memorylorry Date: Sun, 25 Aug 2024 07:05:52 +0800 Subject: [PATCH 2/2] Fix YOLOv8 C++ ONNXRuntime transpose op (#15779) Co-authored-by: Glenn Jocher --- examples/YOLOv8-ONNXRuntime-CPP/inference.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/YOLOv8-ONNXRuntime-CPP/inference.cpp b/examples/YOLOv8-ONNXRuntime-CPP/inference.cpp index 5154a8303..2ee993eed 100644 --- a/examples/YOLOv8-ONNXRuntime-CPP/inference.cpp +++ b/examples/YOLOv8-ONNXRuntime-CPP/inference.cpp @@ -221,8 +221,8 @@ char* YOLO_V8::TensorProcess(clock_t& starttime_1, cv::Mat& iImg, N& blob, std:: case YOLO_DETECT_V8: case YOLO_DETECT_V8_HALF: { - int strideNum = outputNodeDims[1];//8400 - int signalResultNum = outputNodeDims[2];//84 + int signalResultNum = outputNodeDims[1];//84 + int strideNum = outputNodeDims[2];//8400 std::vector class_ids; std::vector confidences; std::vector boxes; @@ -230,18 +230,18 @@ char* YOLO_V8::TensorProcess(clock_t& starttime_1, cv::Mat& iImg, N& blob, std:: if (modelType == YOLO_DETECT_V8) { // FP32 - rawData = cv::Mat(strideNum, signalResultNum, CV_32F, output); + rawData = cv::Mat(signalResultNum, strideNum, CV_32F, output); } else { // FP16 - rawData = cv::Mat(strideNum, signalResultNum, CV_16F, output); + rawData = cv::Mat(signalResultNum, strideNum, CV_16F, output); rawData.convertTo(rawData, CV_32F); } //Note: //ultralytics add transpose operator to the output of yolov8 model.which make yolov8/v5/v7 has same shape //https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8n.pt - //rowData = rowData.t(); + rawData = rawData.t(); float* data = (float*)rawData.data;