From 1e70710f3eb3779bcbaa38fb428b1be53fc913eb Mon Sep 17 00:00:00 2001 From: Muhammad Rizwan Munawar Date: Thu, 31 Oct 2024 22:18:28 +0500 Subject: [PATCH 01/18] Add model comparison graphs in `benchmark.md` (#17212) Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher --- docs/en/modes/benchmark.md | 20 +++++++ docs/overrides/javascript/extra.js | 88 ++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/docs/en/modes/benchmark.md b/docs/en/modes/benchmark.md index 3086e98ec..00d851bea 100644 --- a/docs/en/modes/benchmark.md +++ b/docs/en/modes/benchmark.md @@ -8,6 +8,26 @@ keywords: model benchmarking, YOLO11, Ultralytics, performance evaluation, expor Ultralytics YOLO ecosystem and integrations +## Benchmark Visualization + + + +!!! tip "Refresh Browser" + + You may need to refresh the page to view the graphs correctly due to potential cookie issues. + +
+ + + + + + + + +
+ + ## Introduction Once your model is trained and validated, the next logical step is to evaluate its performance in various real-world scenarios. Benchmark mode in Ultralytics YOLO11 serves this purpose by providing a robust framework for assessing the speed and [accuracy](https://www.ultralytics.com/glossary/accuracy) of your model across a range of export formats. diff --git a/docs/overrides/javascript/extra.js b/docs/overrides/javascript/extra.js index 5029ff489..13f07397e 100644 --- a/docs/overrides/javascript/extra.js +++ b/docs/overrides/javascript/extra.js @@ -147,3 +147,91 @@ document.addEventListener("DOMContentLoaded", () => { addInkeepWidget(); // initialize the widget }); }); + +// This object contains the benchmark data for various object detection models. +const data = { + 'YOLOv5': {s: {speed: 1.92, mAP: 37.4}, m: {speed: 4.03, mAP: 45.4}, l: {speed: 6.61, mAP: 49.0}, x: {speed: 11.89, mAP: 50.7}}, + 'YOLOv6': {n: {speed: 1.17, mAP: 37.5}, s: {speed: 2.66, mAP: 45.0}, m: {speed: 5.28, mAP: 50.0}, l: {speed: 8.95, mAP: 52.8}}, + 'YOLOv7': {l: {speed: 6.84, mAP: 51.4}, x: {speed: 11.57, mAP: 53.1}}, + 'YOLOv8': {n: {speed: 1.47, mAP: 37.3}, s: {speed: 2.66, mAP: 44.9}, m: {speed: 5.86, mAP: 50.2}, l: {speed: 9.06, mAP: 52.9}, x: {speed: 14.37, mAP: 53.9}}, + 'YOLOv9': {t: {speed: 2.30, mAP: 37.8}, s: {speed: 3.54, mAP: 46.5}, m: {speed: 6.43, mAP: 51.5}, c: {speed: 7.16, mAP: 52.8}, e: {speed: 16.77, mAP: 55.1}}, + 'YOLOv10': {n: {speed: 1.56, mAP: 39.5}, s: {speed: 2.66, mAP: 46.7}, m: {speed: 5.48, mAP: 51.3}, b: {speed: 6.54, mAP: 52.7}, l: {speed: 8.33, mAP: 53.3}, x: {speed: 12.2, mAP: 54.4}}, + 'PPYOLOE': {t: {speed: 2.84, mAP: 39.9}, s: {speed: 2.62, mAP: 43.7}, m: {speed: 5.56, mAP: 49.8}, l: {speed: 8.36, mAP: 52.9}, x: {speed: 14.3, mAP: 54.7}}, + 'YOLO11': {n: {speed: 1.55, mAP: 39.5}, s: {speed: 2.63, mAP: 47.0}, m: {speed: 5.27, mAP: 51.4}, l: {speed: 6.84, mAP: 53.2}, x: {speed: 12.49, mAP: 54.7}} +}; + +let chart = null; // chart variable will hold the reference to the current chart instance. + +// This function is responsible for updating the benchmarks chart. +function updateChart() { + // If a chart instance already exists, destroy it. + if (chart) { chart.destroy(); } + + // Get the selected algorithms from the checkboxes. + const selectedAlgorithms = [...document.querySelectorAll('input[name="algorithm"]:checked')].map(e => e.value); + + // Create the datasets for the selected algorithms. + const datasets = selectedAlgorithms.map((algorithm, index) => ({ + label: algorithm, // Label for the data points in the legend. + data: Object.entries(data[algorithm]).map(([version, point]) => ({ + x: point.speed, // Speed data points on the x-axis. + y: point.mAP, // mAP data points on the y-axis. + version: version.toUpperCase() // Store the version as additional data. + })), + fill: false, // Don't fill the chart. + borderColor: `hsl(${index * 90}, 70%, 50%)`, // Assign a unique color to each dataset. + tension: 0.3, // Smooth the line. + pointRadius: 5, // Increase the dot size. + pointHoverRadius: 10, // Increase the dot size on hover. + borderWidth: 2 // Set the line thickness. + })); + + // If there are no selected algorithms, return without creating a new chart. + if (datasets.length === 0) return; + + // Create a new chart instance. + chart = new Chart(document.getElementById('chart').getContext('2d'), { + type: 'line', // Set the chart type to line. + data: { datasets }, + options: { + plugins: { + legend: { display: true, position: 'top', labels: { color: '#111e68' } }, // Configure the legend. + tooltip: { + callbacks: { + label: (tooltipItem) => { + const { dataset, dataIndex } = tooltipItem; + const point = dataset.data[dataIndex]; + return `${dataset.label}${point.version.toLowerCase()}: Speed = ${point.x}, mAP = ${point.y}`; // Custom tooltip label. + } + }, + mode: 'nearest', + intersect: false + } // Configure the tooltip. + }, + interaction: { mode: 'nearest', axis: 'x', intersect: false }, // Configure the interaction mode. + scales: { + x: { + type: 'linear', position: 'bottom', + title: { display: true, text: 'Latency T4 TensorRT10 FP16 (ms/img)', color: '#111e68' }, // X-axis title. + grid: { color: '#e0e0e0' }, // Grid line color. + ticks: { color: '#111e68' } // Tick label color. + }, + y: { + title: { display: true, text: 'mAP', color: '#111e68' }, // Y-axis title. + grid: { color: '#e0e0e0' }, // Grid line color. + ticks: { color: '#111e68' } // Tick label color. + } + } + } + }); +} + +// Add event listeners to the checkboxes to trigger the chart update. +document.addEventListener("DOMContentLoaded", () => { + document.querySelectorAll('input[name="algorithm"]').forEach(checkbox => + checkbox.addEventListener('change', updateChart) + ); + // Call updateChart on initial load + updateChart(); + console.log("DOM loaded, initial chart render attempted"); +}); From daaac35fffe0889ce3e6371fff0253434b5f0c9b Mon Sep 17 00:00:00 2001 From: Lakshantha Dissanayake Date: Thu, 31 Oct 2024 17:12:29 -0700 Subject: [PATCH 02/18] Skip MNN export for Raspberry Pi and NVIDIA Jetson (#17292) Co-authored-by: Glenn Jocher Co-authored-by: UltralyticsAssistant --- tests/test_exports.py | 1 + ultralytics/engine/exporter.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/tests/test_exports.py b/tests/test_exports.py index a05f0e059..5a54b1afa 100644 --- a/tests/test_exports.py +++ b/tests/test_exports.py @@ -193,6 +193,7 @@ def test_export_paddle(): @pytest.mark.slow +@pytest.mark.skipif(IS_RASPBERRYPI, reason="MNN not supported on Raspberry Pi") def test_export_mnn(): """Test YOLO exports to MNN format (WARNING: MNN test must precede NCNN test or CI error on Windows).""" file = YOLO(MODEL).export(format="mnn", imgsz=32) diff --git a/ultralytics/engine/exporter.py b/ultralytics/engine/exporter.py index ea8d03b46..223454f60 100644 --- a/ultralytics/engine/exporter.py +++ b/ultralytics/engine/exporter.py @@ -77,6 +77,7 @@ from ultralytics.utils import ( ARM64, DEFAULT_CFG, IS_JETSON, + IS_RASPBERRYPI, LINUX, LOGGER, MACOS, @@ -244,6 +245,8 @@ class Exporter: "WARNING ⚠️ INT8 export requires a missing 'data' arg for calibration. " f"Using default 'data={self.args.data}'." ) + if mnn and (IS_RASPBERRYPI or IS_JETSON): + raise SystemError("MNN export not supported on Raspberry Pi and NVIDIA Jetson") # Input im = torch.zeros(self.args.batch, 3, *self.imgsz).to(self.device) file = Path( From 7cb36d64b23e311eadd9a75f402d599598396893 Mon Sep 17 00:00:00 2001 From: Muhammad Rizwan Munawar Date: Fri, 1 Nov 2024 05:34:03 +0500 Subject: [PATCH 03/18] Benchmark graph fix (#17296) Co-authored-by: Glenn Jocher --- docs/en/modes/benchmark.md | 22 +++++++++++--------- docs/overrides/javascript/extra.js | 33 ++++++++++++++++-------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/docs/en/modes/benchmark.md b/docs/en/modes/benchmark.md index 00d851bea..b562a979e 100644 --- a/docs/en/modes/benchmark.md +++ b/docs/en/modes/benchmark.md @@ -16,17 +16,19 @@ keywords: model benchmarking, YOLO11, Ultralytics, performance evaluation, expor You may need to refresh the page to view the graphs correctly due to potential cookie issues. -
- - - - - - - - +
+
+
+
+
+
+
+
+
+ +
+
- ## Introduction diff --git a/docs/overrides/javascript/extra.js b/docs/overrides/javascript/extra.js index 13f07397e..e2faf7986 100644 --- a/docs/overrides/javascript/extra.js +++ b/docs/overrides/javascript/extra.js @@ -165,7 +165,7 @@ let chart = null; // chart variable will hold the reference to the current char // This function is responsible for updating the benchmarks chart. function updateChart() { // If a chart instance already exists, destroy it. - if (chart) { chart.destroy(); } + if (chart) chart.destroy(); // Get the selected algorithms from the checkboxes. const selectedAlgorithms = [...document.querySelectorAll('input[name="algorithm"]:checked')].map(e => e.value); @@ -195,7 +195,7 @@ function updateChart() { data: { datasets }, options: { plugins: { - legend: { display: true, position: 'top', labels: { color: '#111e68' } }, // Configure the legend. + legend: { display: true, position: 'top', labels: {color: '#808080'} }, // Configure the legend. tooltip: { callbacks: { label: (tooltipItem) => { @@ -212,26 +212,29 @@ function updateChart() { scales: { x: { type: 'linear', position: 'bottom', - title: { display: true, text: 'Latency T4 TensorRT10 FP16 (ms/img)', color: '#111e68' }, // X-axis title. + title: { display: true, text: 'Latency T4 TensorRT10 FP16 (ms/img)', color: '#808080'}, // X-axis title. grid: { color: '#e0e0e0' }, // Grid line color. - ticks: { color: '#111e68' } // Tick label color. + ticks: { color: '#808080' } // Tick label color. }, y: { - title: { display: true, text: 'mAP', color: '#111e68' }, // Y-axis title. + title: { display: true, text: 'mAP', color: '#808080'}, // Y-axis title. grid: { color: '#e0e0e0' }, // Grid line color. - ticks: { color: '#111e68' } // Tick label color. + ticks: { color: '#808080' } // Tick label color. } } } }); } -// Add event listeners to the checkboxes to trigger the chart update. -document.addEventListener("DOMContentLoaded", () => { - document.querySelectorAll('input[name="algorithm"]').forEach(checkbox => - checkbox.addEventListener('change', updateChart) - ); - // Call updateChart on initial load - updateChart(); - console.log("DOM loaded, initial chart render attempted"); -}); +// Poll for Chart.js to load, then initialize checkboxes and chart +function initializeApp() { + if (typeof Chart !== 'undefined') { + document.querySelectorAll('input[name="algorithm"]').forEach(checkbox => + checkbox.addEventListener('change', updateChart) + ); + updateChart(); + } else { + setTimeout(initializeApp, 100); // Retry every 100ms + } +} +document.addEventListener("DOMContentLoaded", initializeApp); // Initial chart rendering on page load From 3a4b65c347863e0bb1f1eb6b797a9bc59936bf3b Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Fri, 1 Nov 2024 01:42:51 +0100 Subject: [PATCH 04/18] `ultralytics 8.3.27` HUB timed training fix (#17298) Signed-off-by: UltralyticsAssistant Co-authored-by: UltralyticsAssistant --- docs/mkdocs_github_authors.yaml | 11 +++++++---- ultralytics/__init__.py | 2 +- ultralytics/engine/trainer.py | 2 +- ultralytics/utils/checks.py | 8 ++------ 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/mkdocs_github_authors.yaml b/docs/mkdocs_github_authors.yaml index 55ac6ec95..3e6919e7f 100644 --- a/docs/mkdocs_github_authors.yaml +++ b/docs/mkdocs_github_authors.yaml @@ -5,8 +5,8 @@ avatar: https://avatars.githubusercontent.com/u/116908874?v=4 username: jk4e 1185102784@qq.com: - avatar: null - username: null + avatar: https://avatars.githubusercontent.com/u/61612323?v=4 + username: Laughing-q 130829914+IvorZhu331@users.noreply.github.com: avatar: https://avatars.githubusercontent.com/u/130829914?v=4 username: IvorZhu331 @@ -137,8 +137,8 @@ rulosanti@gmail.com: avatar: null username: null shuizhuyuanluo@126.com: - avatar: null - username: null + avatar: https://avatars.githubusercontent.com/u/171016?v=4 + username: https://github.com/nihui sometimesocrazy@gmail.com: avatar: null username: null @@ -157,3 +157,6 @@ xinwang614@gmail.com: zhaode.wzd@alibaba-inc.com: avatar: https://avatars.githubusercontent.com/u/8401806?v=4 username: ZhaodeWang +davis.justin@mssm.org: + avatar: https://avatars.githubusercontent.com/u/23462437?v=4 + username: justincdavis diff --git a/ultralytics/__init__.py b/ultralytics/__init__.py index fedf8629a..e24b210ed 100644 --- a/ultralytics/__init__.py +++ b/ultralytics/__init__.py @@ -1,6 +1,6 @@ # Ultralytics YOLO 🚀, AGPL-3.0 license -__version__ = "8.3.26" +__version__ = "8.3.27" import os diff --git a/ultralytics/engine/trainer.py b/ultralytics/engine/trainer.py index e82aed9e0..068274a42 100644 --- a/ultralytics/engine/trainer.py +++ b/ultralytics/engine/trainer.py @@ -118,7 +118,7 @@ class BaseTrainer: self.save_period = self.args.save_period self.batch_size = self.args.batch - self.epochs = self.args.epochs + self.epochs = self.args.epochs or 100 # in case users accidentally pass epochs=None with timed training self.start_epoch = 0 if RANK == -1: print_args(vars(self.args)) diff --git a/ultralytics/utils/checks.py b/ultralytics/utils/checks.py index 9591d3dea..3a8201a54 100644 --- a/ultralytics/utils/checks.py +++ b/ultralytics/utils/checks.py @@ -23,7 +23,6 @@ from ultralytics.utils import ( AUTOINSTALL, IS_COLAB, IS_GIT_DIR, - IS_JUPYTER, IS_KAGGLE, IS_PIP_PACKAGE, LINUX, @@ -569,11 +568,8 @@ def check_yolo(verbose=True, device=""): from ultralytics.utils.torch_utils import select_device - if IS_JUPYTER: - if check_requirements("wandb", install=False): - os.system("pip uninstall -y wandb") # uninstall wandb: unwanted account creation prompt with infinite hang - if IS_COLAB: - shutil.rmtree("sample_data", ignore_errors=True) # remove colab /sample_data directory + if IS_COLAB: + shutil.rmtree("sample_data", ignore_errors=True) # remove colab /sample_data directory if verbose: # System info From 591fdbd8b1a48eb820bd6dffe3d128db809f323d Mon Sep 17 00:00:00 2001 From: Laughing <61612323+Laughing-q@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:08:30 +0800 Subject: [PATCH 05/18] Fix `Bboxes` numpy.reshape (#17301) --- ultralytics/utils/instance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ultralytics/utils/instance.py b/ultralytics/utils/instance.py index f88389571..d18bdb612 100644 --- a/ultralytics/utils/instance.py +++ b/ultralytics/utils/instance.py @@ -176,7 +176,7 @@ class Bboxes: length as the number of bounding boxes. """ if isinstance(index, int): - return Bboxes(self.bboxes[index].view(1, -1)) + return Bboxes(self.bboxes[index].reshape(1, -1)) b = self.bboxes[index] assert b.ndim == 2, f"Indexing on Bboxes with {index} failed to return a matrix!" return Bboxes(b) From 4ca50c8c377c5b7a63723777b6f91ccd0a836dc8 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Fri, 1 Nov 2024 16:11:48 +0100 Subject: [PATCH 06/18] Fix MNN Raspberry Pi benchmark attempt (#17308) --- ultralytics/utils/benchmarks.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ultralytics/utils/benchmarks.py b/ultralytics/utils/benchmarks.py index 3ddd934db..13d940780 100644 --- a/ultralytics/utils/benchmarks.py +++ b/ultralytics/utils/benchmarks.py @@ -108,12 +108,16 @@ def benchmark( assert not isinstance(model, YOLOWorld), "YOLOWorldv2 TensorFlow exports not supported by onnx2tf yet" if i in {9, 10}: # TF EdgeTPU and TF.js assert not isinstance(model, YOLOWorld), "YOLOWorldv2 TensorFlow exports not supported by onnx2tf yet" - if i in {11}: # Paddle + if i == 11: # Paddle assert not isinstance(model, YOLOWorld), "YOLOWorldv2 Paddle exports not supported yet" assert not is_end2end, "End-to-end models not supported by PaddlePaddle yet" assert LINUX or MACOS, "Windows Paddle exports not supported yet" - if i in {12, 13}: # MNN, NCNN - assert not isinstance(model, YOLOWorld), "YOLOWorldv2 MNN, NCNN exports not supported yet" + if i == 12: # MNN + assert not isinstance(model, YOLOWorld), "YOLOWorldv2 MNN exports not supported yet" + assert not IS_RASPBERRYPI, "MNN export not supported on Raspberry Pi" + assert not IS_JETSON, "MNN export not supported on NVIDIA Jetson" + if i == 13: # NCNN + assert not isinstance(model, YOLOWorld), "YOLOWorldv2 NCNN exports not supported yet" if "cpu" in device.type: assert cpu, "inference not supported on CPU" if "cuda" in device.type: From 19d9f77cc291f5fb5e11b3229eb3db8f4fbb794b Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sat, 2 Nov 2024 12:07:41 +0100 Subject: [PATCH 07/18] Fix mkdocs_github_authors.yaml (#17314) --- docs/mkdocs_github_authors.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mkdocs_github_authors.yaml b/docs/mkdocs_github_authors.yaml index 3e6919e7f..5240ff8e5 100644 --- a/docs/mkdocs_github_authors.yaml +++ b/docs/mkdocs_github_authors.yaml @@ -138,7 +138,7 @@ rulosanti@gmail.com: username: null shuizhuyuanluo@126.com: avatar: https://avatars.githubusercontent.com/u/171016?v=4 - username: https://github.com/nihui + username: nihui sometimesocrazy@gmail.com: avatar: null username: null @@ -156,7 +156,7 @@ xinwang614@gmail.com: username: GreatV zhaode.wzd@alibaba-inc.com: avatar: https://avatars.githubusercontent.com/u/8401806?v=4 - username: ZhaodeWang + username: wangzhaode davis.justin@mssm.org: avatar: https://avatars.githubusercontent.com/u/23462437?v=4 username: justincdavis From 788387831aa37e29c3fdf5dd62d47624b5db6dc6 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sat, 2 Nov 2024 12:59:48 +0100 Subject: [PATCH 08/18] Update mkdocs_github_authors.yaml (#17320) --- docs/mkdocs_github_authors.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/mkdocs_github_authors.yaml b/docs/mkdocs_github_authors.yaml index 5240ff8e5..f91a730b8 100644 --- a/docs/mkdocs_github_authors.yaml +++ b/docs/mkdocs_github_authors.yaml @@ -157,6 +157,9 @@ xinwang614@gmail.com: zhaode.wzd@alibaba-inc.com: avatar: https://avatars.githubusercontent.com/u/8401806?v=4 username: wangzhaode +8401806+wangzhaode@users.noreply.github.com: + avatar: https://avatars.githubusercontent.com/u/8401806?v=4 + username: wangzhaode davis.justin@mssm.org: avatar: https://avatars.githubusercontent.com/u/23462437?v=4 username: justincdavis From d28caa9a58dc720a71d4916d7a9c69a376ed7a6c Mon Sep 17 00:00:00 2001 From: Mohammed Yasin <32206511+Y-T-G@users.noreply.github.com> Date: Sat, 2 Nov 2024 20:00:05 +0800 Subject: [PATCH 09/18] Refactor TFLite example. Support FP32, Fp16, INT8 models (#17317) Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher --- examples/README.md | 2 +- .../README.md | 65 ---- .../YOLOv8-OpenCV-int8-tflite-Python/main.py | 308 ------------------ examples/YOLOv8-TFLite-Python/README.md | 55 ++++ examples/YOLOv8-TFLite-Python/main.py | 221 +++++++++++++ 5 files changed, 277 insertions(+), 374 deletions(-) delete mode 100644 examples/YOLOv8-OpenCV-int8-tflite-Python/README.md delete mode 100644 examples/YOLOv8-OpenCV-int8-tflite-Python/main.py create mode 100644 examples/YOLOv8-TFLite-Python/README.md create mode 100644 examples/YOLOv8-TFLite-Python/main.py diff --git a/examples/README.md b/examples/README.md index ab875b3ba..260ec2f51 100644 --- a/examples/README.md +++ b/examples/README.md @@ -18,7 +18,7 @@ This directory features a collection of real-world applications and walkthroughs | [YOLOv8 Region Counter](https://github.com/RizwanMunawar/ultralytics/blob/main/examples/YOLOv8-Region-Counter/yolov8_region_counter.py) | Python | [Muhammad Rizwan Munawar](https://github.com/RizwanMunawar) | | [YOLOv8 Segmentation ONNXRuntime Python](./YOLOv8-Segmentation-ONNXRuntime-Python) | Python/ONNXRuntime | [jamjamjon](https://github.com/jamjamjon) | | [YOLOv8 LibTorch CPP](./YOLOv8-LibTorch-CPP-Inference) | C++/LibTorch | [Myyura](https://github.com/Myyura) | -| [YOLOv8 OpenCV INT8 TFLite Python](./YOLOv8-OpenCV-int8-tflite-Python) | Python | [Wamiq Raza](https://github.com/wamiqraza) | +| [YOLOv8 OpenCV INT8 TFLite Python](./YOLOv8-TFLite-Python) | Python | [Wamiq Raza](https://github.com/wamiqraza) | | [YOLOv8 All Tasks ONNXRuntime Rust](./YOLOv8-ONNXRuntime-Rust) | Rust/ONNXRuntime | [jamjamjon](https://github.com/jamjamjon) | | [YOLOv8 OpenVINO CPP](./YOLOv8-OpenVINO-CPP-Inference) | C++/OpenVINO | [Erlangga Yudi Pradana](https://github.com/rlggyp) | diff --git a/examples/YOLOv8-OpenCV-int8-tflite-Python/README.md b/examples/YOLOv8-OpenCV-int8-tflite-Python/README.md deleted file mode 100644 index ea14e4440..000000000 --- a/examples/YOLOv8-OpenCV-int8-tflite-Python/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# YOLOv8 - Int8-TFLite Runtime - -Welcome to the YOLOv8 Int8 TFLite Runtime for efficient and optimized object detection project. This README provides comprehensive instructions for installing and using our YOLOv8 implementation. - -## Installation - -Ensure a smooth setup by following these steps to install necessary dependencies. - -### Installing Required Dependencies - -Install all required dependencies with this simple command: - -```bash -pip install -r requirements.txt -``` - -### Installing `tflite-runtime` - -To load TFLite models, install the `tflite-runtime` package using: - -```bash -pip install tflite-runtime -``` - -### Installing `tensorflow-gpu` (For NVIDIA GPU Users) - -Leverage GPU acceleration with NVIDIA GPUs by installing `tensorflow-gpu`: - -```bash -pip install tensorflow-gpu -``` - -**Note:** Ensure you have compatible GPU drivers installed on your system. - -### Installing `tensorflow` (CPU Version) - -For CPU usage or non-NVIDIA GPUs, install TensorFlow with: - -```bash -pip install tensorflow -``` - -## Usage - -Follow these instructions to run YOLOv8 after successful installation. - -Convert the YOLOv8 model to Int8 TFLite format: - -```bash -yolo export model=yolov8n.pt imgsz=640 format=tflite int8 -``` - -Locate the Int8 TFLite model in `yolov8n_saved_model`. Choose `best_full_integer_quant` or verify quantization at [Netron](https://netron.app/). Then, execute the following in your terminal: - -```bash -python main.py --model yolov8n_full_integer_quant.tflite --img image.jpg --conf-thres 0.5 --iou-thres 0.5 -``` - -Replace `best_full_integer_quant.tflite` with your model file's path, `image.jpg` with your input image, and adjust the confidence (conf-thres) and IoU thresholds (iou-thres) as necessary. - -### Output - -The output is displayed as annotated images, showcasing the model's detection capabilities: - -![image](https://github.com/wamiqraza/Attribute-recognition-and-reidentification-Market1501-dataset/blob/main/img/bus.jpg) diff --git a/examples/YOLOv8-OpenCV-int8-tflite-Python/main.py b/examples/YOLOv8-OpenCV-int8-tflite-Python/main.py deleted file mode 100644 index 46d7fb427..000000000 --- a/examples/YOLOv8-OpenCV-int8-tflite-Python/main.py +++ /dev/null @@ -1,308 +0,0 @@ -# Ultralytics YOLO 🚀, AGPL-3.0 license - -import argparse - -import cv2 -import numpy as np -from tflite_runtime import interpreter as tflite - -from ultralytics.utils import ASSETS, yaml_load -from ultralytics.utils.checks import check_yaml - -# Declare as global variables, can be updated based trained model image size -img_width = 640 -img_height = 640 - - -class LetterBox: - """Resizes and reshapes images while maintaining aspect ratio by adding padding, suitable for YOLO models.""" - - def __init__( - self, new_shape=(img_width, img_height), auto=False, scaleFill=False, scaleup=True, center=True, stride=32 - ): - """Initializes LetterBox with parameters for reshaping and transforming image while maintaining aspect ratio.""" - self.new_shape = new_shape - self.auto = auto - self.scaleFill = scaleFill - self.scaleup = scaleup - self.stride = stride - self.center = center # Put the image in the middle or top-left - - def __call__(self, labels=None, image=None): - """Return updated labels and image with added border.""" - if labels is None: - labels = {} - img = labels.get("img") if image is None else image - shape = img.shape[:2] # current shape [height, width] - new_shape = labels.pop("rect_shape", self.new_shape) - if isinstance(new_shape, int): - new_shape = (new_shape, new_shape) - - # Scale ratio (new / old) - r = min(new_shape[0] / shape[0], new_shape[1] / shape[1]) - if not self.scaleup: # only scale down, do not scale up (for better val mAP) - r = min(r, 1.0) - - # Compute padding - ratio = r, r # width, height ratios - new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) - dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding - if self.auto: # minimum rectangle - dw, dh = np.mod(dw, self.stride), np.mod(dh, self.stride) # wh padding - elif self.scaleFill: # stretch - dw, dh = 0.0, 0.0 - new_unpad = (new_shape[1], new_shape[0]) - ratio = new_shape[1] / shape[1], new_shape[0] / shape[0] # width, height ratios - - if self.center: - dw /= 2 # divide padding into 2 sides - dh /= 2 - - if shape[::-1] != new_unpad: # resize - img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR) - top, bottom = int(round(dh - 0.1)) if self.center else 0, int(round(dh + 0.1)) - left, right = int(round(dw - 0.1)) if self.center else 0, int(round(dw + 0.1)) - img = cv2.copyMakeBorder( - img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114) - ) # add border - if labels.get("ratio_pad"): - labels["ratio_pad"] = (labels["ratio_pad"], (left, top)) # for evaluation - - if len(labels): - labels = self._update_labels(labels, ratio, dw, dh) - labels["img"] = img - labels["resized_shape"] = new_shape - return labels - else: - return img - - def _update_labels(self, labels, ratio, padw, padh): - """Update labels.""" - labels["instances"].convert_bbox(format="xyxy") - labels["instances"].denormalize(*labels["img"].shape[:2][::-1]) - labels["instances"].scale(*ratio) - labels["instances"].add_padding(padw, padh) - return labels - - -class Yolov8TFLite: - """Class for performing object detection using YOLOv8 model converted to TensorFlow Lite format.""" - - def __init__(self, tflite_model, input_image, confidence_thres, iou_thres): - """ - Initializes an instance of the Yolov8TFLite class. - - Args: - tflite_model: Path to the TFLite model. - input_image: Path to the input image. - confidence_thres: Confidence threshold for filtering detections. - iou_thres: IoU (Intersection over Union) threshold for non-maximum suppression. - """ - self.tflite_model = tflite_model - self.input_image = input_image - self.confidence_thres = confidence_thres - self.iou_thres = iou_thres - - # Load the class names from the COCO dataset - self.classes = yaml_load(check_yaml("coco8.yaml"))["names"] - - # Generate a color palette for the classes - self.color_palette = np.random.uniform(0, 255, size=(len(self.classes), 3)) - - def draw_detections(self, img, box, score, class_id): - """ - Draws bounding boxes and labels on the input image based on the detected objects. - - Args: - img: The input image to draw detections on. - box: Detected bounding box. - score: Corresponding detection score. - class_id: Class ID for the detected object. - - Returns: - None - """ - # Extract the coordinates of the bounding box - x1, y1, w, h = box - - # Retrieve the color for the class ID - color = self.color_palette[class_id] - - # Draw the bounding box on the image - cv2.rectangle(img, (int(x1), int(y1)), (int(x1 + w), int(y1 + h)), color, 2) - - # Create the label text with class name and score - label = f"{self.classes[class_id]}: {score:.2f}" - - # Calculate the dimensions of the label text - (label_width, label_height), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1) - - # Calculate the position of the label text - label_x = x1 - label_y = y1 - 10 if y1 - 10 > label_height else y1 + 10 - - # Draw a filled rectangle as the background for the label text - cv2.rectangle( - img, - (int(label_x), int(label_y - label_height)), - (int(label_x + label_width), int(label_y + label_height)), - color, - cv2.FILLED, - ) - - # Draw the label text on the image - cv2.putText(img, label, (int(label_x), int(label_y)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA) - - def preprocess(self): - """ - Preprocesses the input image before performing inference. - - Returns: - image_data: Preprocessed image data ready for inference. - """ - # Read the input image using OpenCV - self.img = cv2.imread(self.input_image) - - print("image before", self.img) - # Get the height and width of the input image - self.img_height, self.img_width = self.img.shape[:2] - - letterbox = LetterBox(new_shape=[img_width, img_height], auto=False, stride=32) - image = letterbox(image=self.img) - image = [image] - image = np.stack(image) - image = image[..., ::-1].transpose((0, 3, 1, 2)) - img = np.ascontiguousarray(image) - # n, h, w, c - image = img.astype(np.float32) - return image / 255 - - def postprocess(self, input_image, output): - """ - Performs post-processing on the model's output to extract bounding boxes, scores, and class IDs. - - Args: - input_image (numpy.ndarray): The input image. - output (numpy.ndarray): The output of the model. - - Returns: - numpy.ndarray: The input image with detections drawn on it. - """ - # Transpose predictions outside the loop - output = [np.transpose(pred) for pred in output] - - boxes = [] - scores = [] - class_ids = [] - - # Vectorize extraction of bounding boxes, scores, and class IDs - for pred in output: - x, y, w, h = pred[:, 0], pred[:, 1], pred[:, 2], pred[:, 3] - x1 = x - w / 2 - y1 = y - h / 2 - boxes.extend(np.column_stack([x1, y1, w, h])) - - # Argmax and score extraction for all predictions at once - idx = np.argmax(pred[:, 4:], axis=1) - scores.extend(pred[np.arange(pred.shape[0]), idx + 4]) - class_ids.extend(idx) - - # Precompute gain and pad once - img_height, img_width = input_image.shape[:2] - gain = min(img_width / self.img_width, img_height / self.img_height) - pad = ( - round((img_width - self.img_width * gain) / 2 - 0.1), - round((img_height - self.img_height * gain) / 2 - 0.1), - ) - - # Non-Maximum Suppression (NMS) in one go - indices = cv2.dnn.NMSBoxes(boxes, scores, self.confidence_thres, self.iou_thres) - - # Process selected indices - for i in indices.flatten(): - box = boxes[i] - box[0] = (box[0] - pad[0]) / gain - box[1] = (box[1] - pad[1]) / gain - box[2] = box[2] / gain - box[3] = box[3] / gain - - score = scores[i] - class_id = class_ids[i] - - if score > 0.25: - # Draw the detection on the input image - self.draw_detections(input_image, box, score, class_id) - - return input_image - - def main(self): - """ - Performs inference using a TFLite model and returns the output image with drawn detections. - - Returns: - output_img: The output image with drawn detections. - """ - # Create an interpreter for the TFLite model - interpreter = tflite.Interpreter(model_path=self.tflite_model) - self.model = interpreter - interpreter.allocate_tensors() - - # Get the model inputs - input_details = interpreter.get_input_details() - output_details = interpreter.get_output_details() - - # Store the shape of the input for later use - input_shape = input_details[0]["shape"] - self.input_width = input_shape[1] - self.input_height = input_shape[2] - - # Preprocess the image data - img_data = self.preprocess() - img_data = img_data - # img_data = img_data.cpu().numpy() - # Set the input tensor to the interpreter - print(input_details[0]["index"]) - print(img_data.shape) - img_data = img_data.transpose((0, 2, 3, 1)) - - scale, zero_point = input_details[0]["quantization"] - img_data_int8 = (img_data / scale + zero_point).astype(np.int8) - interpreter.set_tensor(input_details[0]["index"], img_data_int8) - - # Run inference - interpreter.invoke() - - # Get the output tensor from the interpreter - output = interpreter.get_tensor(output_details[0]["index"]) - scale, zero_point = output_details[0]["quantization"] - output = (output.astype(np.float32) - zero_point) * scale - - output[:, [0, 2]] *= img_width - output[:, [1, 3]] *= img_height - print(output) - # Perform post-processing on the outputs to obtain output image. - return self.postprocess(self.img, output) - - -if __name__ == "__main__": - # Create an argument parser to handle command-line arguments - parser = argparse.ArgumentParser() - parser.add_argument( - "--model", type=str, default="yolov8n_full_integer_quant.tflite", help="Input your TFLite model." - ) - parser.add_argument("--img", type=str, default=str(ASSETS / "bus.jpg"), help="Path to input image.") - parser.add_argument("--conf-thres", type=float, default=0.5, help="Confidence threshold") - parser.add_argument("--iou-thres", type=float, default=0.5, help="NMS IoU threshold") - args = parser.parse_args() - - # Create an instance of the Yolov8TFLite class with the specified arguments - detection = Yolov8TFLite(args.model, args.img, args.conf_thres, args.iou_thres) - - # Perform object detection and obtain the output image - output_image = detection.main() - - # Display the output image in a window - cv2.imshow("Output", output_image) - - # Wait for a key press to exit - cv2.waitKey(0) diff --git a/examples/YOLOv8-TFLite-Python/README.md b/examples/YOLOv8-TFLite-Python/README.md new file mode 100644 index 000000000..0156759fd --- /dev/null +++ b/examples/YOLOv8-TFLite-Python/README.md @@ -0,0 +1,55 @@ +# YOLOv8 - TFLite Runtime + +This example shows how to run inference with YOLOv8 TFLite model. It supports FP32, FP16 and INT8 models. + +## Installation + +### Installing `tflite-runtime` + +To load TFLite models, install the `tflite-runtime` package using: + +```bash +pip install tflite-runtime +``` + +### Installing `tensorflow-gpu` (For NVIDIA GPU Users) + +Leverage GPU acceleration with NVIDIA GPUs by installing `tensorflow-gpu`: + +```bash +pip install tensorflow-gpu +``` + +**Note:** Ensure you have compatible GPU drivers installed on your system. + +### Installing `tensorflow` (CPU Version) + +For CPU usage or non-NVIDIA GPUs, install TensorFlow with: + +```bash +pip install tensorflow +``` + +## Usage + +Follow these instructions to run YOLOv8 after successful installation. + +Convert the YOLOv8 model to TFLite format: + +```bash +yolo export model=yolov8n.pt imgsz=640 format=tflite int8 +``` + +Locate the TFLite model in `yolov8n_saved_model`. Then, execute the following in your terminal: + +```bash +python main.py --model yolov8n_full_integer_quant.tflite --img image.jpg --conf 0.25 --iou 0.45 --metadata "metadata.yaml" +``` + +Replace `best_full_integer_quant.tflite` with the TFLite model path, `image.jpg` with the input image path, `metadata.yaml` with the one generated by `ultralytics` during export, and adjust the confidence (conf) and IoU thresholds (iou) as necessary. + +### Output + +The output would show the detections along with the class labels and confidences of each detected object. + +![image](https://github.com/wamiqraza/Attribute-recognition-and-reidentification-Market1501-dataset/blob/main/img/bus.jpg) diff --git a/examples/YOLOv8-TFLite-Python/main.py b/examples/YOLOv8-TFLite-Python/main.py new file mode 100644 index 000000000..1fadd86b2 --- /dev/null +++ b/examples/YOLOv8-TFLite-Python/main.py @@ -0,0 +1,221 @@ +# Ultralytics YOLO 🚀, AGPL-3.0 license + +import argparse +from typing import Tuple, Union + +import cv2 +import numpy as np +import tensorflow as tf +import yaml + +from ultralytics.utils import ASSETS + +try: + from tflite_runtime.interpreter import Interpreter +except ImportError: + import tensorflow as tf + + Interpreter = tf.lite.Interpreter + + +class YOLOv8TFLite: + """ + YOLOv8TFLite. + + A class for performing object detection using the YOLOv8 model with TensorFlow Lite. + + Attributes: + model (str): Path to the TensorFlow Lite model file. + conf (float): Confidence threshold for filtering detections. + iou (float): Intersection over Union threshold for non-maximum suppression. + metadata (Optional[str]): Path to the metadata file, if any. + + Methods: + detect(img_path: str) -> np.ndarray: + Performs inference and returns the output image with drawn detections. + """ + + def __init__(self, model: str, conf: float = 0.25, iou: float = 0.45, metadata: Union[str, None] = None): + """ + Initializes an instance of the YOLOv8TFLite class. + + Args: + model (str): Path to the TFLite model. + conf (float, optional): Confidence threshold for filtering detections. Defaults to 0.25. + iou (float, optional): IoU (Intersection over Union) threshold for non-maximum suppression. Defaults to 0.45. + metadata (Union[str, None], optional): Path to the metadata file or None if not used. Defaults to None. + """ + self.conf = conf + self.iou = iou + if metadata is None: + self.classes = {i: i for i in range(1000)} + else: + with open(metadata) as f: + self.classes = yaml.safe_load(f)["names"] + np.random.seed(42) + self.color_palette = np.random.uniform(128, 255, size=(len(self.classes), 3)) + + self.model = Interpreter(model_path=model) + self.model.allocate_tensors() + + input_details = self.model.get_input_details()[0] + + self.in_width, self.in_height = input_details["shape"][1:3] + self.in_index = input_details["index"] + self.in_scale, self.in_zero_point = input_details["quantization"] + self.int8 = input_details["dtype"] == np.int8 + + output_details = self.model.get_output_details()[0] + self.out_index = output_details["index"] + self.out_scale, self.out_zero_point = output_details["quantization"] + + def letterbox(self, img: np.ndarray, new_shape: Tuple = (640, 640)) -> Tuple[np.ndarray, Tuple[float, float]]: + """Resizes and reshapes images while maintaining aspect ratio by adding padding, suitable for YOLO models.""" + shape = img.shape[:2] # current shape [height, width] + + # Scale ratio (new / old) + r = min(new_shape[0] / shape[0], new_shape[1] / shape[1]) + + # Compute padding + new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) + dw, dh = (new_shape[1] - new_unpad[0]) / 2, (new_shape[0] - new_unpad[1]) / 2 # wh padding + + if shape[::-1] != new_unpad: # resize + img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR) + top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1)) + left, right = int(round(dw - 0.1)), int(round(dw + 0.1)) + img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114)) + + return img, (top / img.shape[0], left / img.shape[1]) + + def draw_detections(self, img: np.ndarray, box: np.ndarray, score: np.float32, class_id: int) -> None: + """ + Draws bounding boxes and labels on the input image based on the detected objects. + + Args: + img (np.ndarray): The input image to draw detections on. + box (np.ndarray): Detected bounding box in the format [x1, y1, width, height]. + score (np.float32): Corresponding detection score. + class_id (int): Class ID for the detected object. + + Returns: + None + """ + x1, y1, w, h = box + color = self.color_palette[class_id] + + cv2.rectangle(img, (int(x1), int(y1)), (int(x1 + w), int(y1 + h)), color, 2) + + label = f"{self.classes[class_id]}: {score:.2f}" + + (label_width, label_height), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1) + + label_x = x1 + label_y = y1 - 10 if y1 - 10 > label_height else y1 + 10 + + cv2.rectangle( + img, + (int(label_x), int(label_y - label_height)), + (int(label_x + label_width), int(label_y + label_height)), + color, + cv2.FILLED, + ) + + cv2.putText(img, label, (int(label_x), int(label_y)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA) + + def preprocess(self, img: np.ndarray) -> Tuple[np.ndarray, Tuple[float, float]]: + """ + Preprocesses the input image before performing inference. + + Args: + img (np.ndarray): The input image to be preprocessed. + + Returns: + Tuple[np.ndarray, Tuple[float, float]]: A tuple containing: + - The preprocessed image (np.ndarray). + - A tuple of two float values representing the padding applied (top/bottom, left/right). + """ + img, pad = self.letterbox(img, (self.in_width, self.in_height)) + img = img[..., ::-1][None] # N,H,W,C for TFLite + img = np.ascontiguousarray(img) + img = img.astype(np.float32) + return img / 255, pad + + def postprocess(self, img: np.ndarray, outputs: np.ndarray, pad: Tuple[float, float]) -> np.ndarray: + """ + Performs post-processing on the model's output to extract bounding boxes, scores, and class IDs. + + Args: + img (numpy.ndarray): The input image. + outputs (numpy.ndarray): The output of the model. + pad (Tuple[float, float]): Padding used by letterbox. + + Returns: + numpy.ndarray: The input image with detections drawn on it. + """ + outputs[:, 0] -= pad[1] + outputs[:, 1] -= pad[0] + outputs[:, :4] *= max(img.shape) + + outputs = outputs.transpose(0, 2, 1) + outputs[..., 0] -= outputs[..., 2] / 2 + outputs[..., 1] -= outputs[..., 3] / 2 + + for out in outputs: + scores = out[:, 4:].max(-1) + keep = scores > self.conf + boxes = out[keep, :4] + scores = scores[keep] + class_ids = out[keep, 4:].argmax(-1) + + indices = cv2.dnn.NMSBoxes(boxes, scores, self.conf, self.iou).flatten() + + [self.draw_detections(img, boxes[i], scores[i], class_ids[i]) for i in indices] + + return img + + def detect(self, img_path: str) -> np.ndarray: + """ + Performs inference using a TFLite model and returns the output image with drawn detections. + + Args: + img_path (str): The path to the input image file. + + Returns: + np.ndarray: The output image with drawn detections. + """ + img = cv2.imread(img_path) + x, pad = self.preprocess(img) + if self.int8: + x = (x / self.in_scale + self.in_zero_point).astype(np.int8) + self.model.set_tensor(self.in_index, x) + + self.model.invoke() + + y = self.model.get_tensor(self.out_index) + + if self.int8: + y = (y.astype(np.float32) - self.out_zero_point) * self.out_scale + + return self.postprocess(img, y, pad) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--model", + type=str, + default="yolov8n_saved_model/yolov8n_full_integer_quant.tflite", + help="Path to TFLite model.", + ) + parser.add_argument("--img", type=str, default=str(ASSETS / "bus.jpg"), help="Path to input image") + parser.add_argument("--conf", type=float, default=0.25, help="Confidence threshold") + parser.add_argument("--iou", type=float, default=0.45, help="NMS IoU threshold") + parser.add_argument("--metadata", type=str, default="yolov8n_saved_model/metadata.yaml", help="Metadata yaml") + args = parser.parse_args() + + detector = YOLOv8TFLite(args.model, args.conf, args.iou, args.metadata) + result = detector.detect(str(ASSETS / "bus.jpg"))[..., ::-1] + + cv2.imshow("Output", result) + cv2.waitKey(0) From f95dc37311fc9eaf78e26cec69305e711247244c Mon Sep 17 00:00:00 2001 From: Jamjamjon <51357717+jamjamjon@users.noreply.github.com> Date: Sat, 2 Nov 2024 20:06:07 +0800 Subject: [PATCH 10/18] [Example] YOLO-Series(v5-11) ONNXRuntime Rust (#17311) Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher --- examples/README.md | 1 + .../YOLO-Series-ONNXRuntime-Rust/Cargo.toml | 12 + .../YOLO-Series-ONNXRuntime-Rust/README.md | 94 +++++++ .../YOLO-Series-ONNXRuntime-Rust/src/main.rs | 236 ++++++++++++++++++ examples/YOLOv8-ONNXRuntime-Rust/Cargo.toml | 2 +- examples/YOLOv8-ONNXRuntime-Rust/README.md | 27 +- examples/YOLOv8-ONNXRuntime-Rust/src/lib.rs | 13 +- examples/YOLOv8-ONNXRuntime-Rust/src/model.rs | 6 +- 8 files changed, 362 insertions(+), 29 deletions(-) create mode 100644 examples/YOLO-Series-ONNXRuntime-Rust/Cargo.toml create mode 100644 examples/YOLO-Series-ONNXRuntime-Rust/README.md create mode 100644 examples/YOLO-Series-ONNXRuntime-Rust/src/main.rs diff --git a/examples/README.md b/examples/README.md index 260ec2f51..76f078bde 100644 --- a/examples/README.md +++ b/examples/README.md @@ -21,6 +21,7 @@ This directory features a collection of real-world applications and walkthroughs | [YOLOv8 OpenCV INT8 TFLite Python](./YOLOv8-TFLite-Python) | Python | [Wamiq Raza](https://github.com/wamiqraza) | | [YOLOv8 All Tasks ONNXRuntime Rust](./YOLOv8-ONNXRuntime-Rust) | Rust/ONNXRuntime | [jamjamjon](https://github.com/jamjamjon) | | [YOLOv8 OpenVINO CPP](./YOLOv8-OpenVINO-CPP-Inference) | C++/OpenVINO | [Erlangga Yudi Pradana](https://github.com/rlggyp) | +| [YOLOv5-YOLO11 ONNXRuntime Rust](./YOLO-Series-ONNXRuntime-Rust) | Rust/ONNXRuntime | [jamjamjon](https://github.com/jamjamjon) | ### How to Contribute diff --git a/examples/YOLO-Series-ONNXRuntime-Rust/Cargo.toml b/examples/YOLO-Series-ONNXRuntime-Rust/Cargo.toml new file mode 100644 index 000000000..a795eea29 --- /dev/null +++ b/examples/YOLO-Series-ONNXRuntime-Rust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "YOLO-ONNXRuntime-Rust" +version = "0.1.0" +edition = "2021" +authors = ["Jamjamjon "] + +[dependencies] +anyhow = "1.0.92" +clap = "4.5.20" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" +usls = { version = "0.0.19", features = ["auto"] } diff --git a/examples/YOLO-Series-ONNXRuntime-Rust/README.md b/examples/YOLO-Series-ONNXRuntime-Rust/README.md new file mode 100644 index 000000000..ca05fbb18 --- /dev/null +++ b/examples/YOLO-Series-ONNXRuntime-Rust/README.md @@ -0,0 +1,94 @@ +# YOLO-Series ONNXRuntime Rust Demo for Core YOLO Tasks + +This repository provides a Rust demo for key YOLO-Series tasks such as `Classification`, `Segmentation`, `Detection`, `Pose Detection`, and `OBB` using ONNXRuntime. It supports various YOLO models (v5 - 11) across multiple vision tasks. + +## Introduction + +- This example leverages the latest versions of both ONNXRuntime and YOLO models. +- We utilize the [usls](https://github.com/jamjamjon/usls/tree/main) crate to streamline YOLO model inference, providing efficient data loading, visualization, and optimized inference performance. + +## Features + +- **Extensive Model Compatibility**: Supports `YOLOv5`, `YOLOv6`, `YOLOv7`, `YOLOv8`, `YOLOv9`, `YOLOv10`, `YOLO11`, `YOLO-world`, `RTDETR`, and others, covering a wide range of YOLO versions. +- **Versatile Task Coverage**: Includes `Classification`, `Segmentation`, `Detection`, `Pose`, and `OBB`. +- **Precision Flexibility**: Works with `FP16` and `FP32` ONNX models. +- **Execution Providers**: Accelerated support for `CPU`, `CUDA`, `CoreML`, and `TensorRT`. +- **Dynamic Input Shapes**: Dynamically adjusts to variable `batch`, `width`, and `height` dimensions for flexible model input. +- **Flexible Data Loading**: The `DataLoader` handles images, folders, videos, and video streams. +- **Real-Time Display and Video Export**: `Viewer` provides real-time frame visualization and video export functions, similar to OpenCV’s `imshow()` and `imwrite()`. +- **Enhanced Annotation and Visualization**: The `Annotator` facilitates comprehensive result rendering, with support for bounding boxes (HBB), oriented bounding boxes (OBB), polygons, masks, keypoints, and text labels. + +## Setup Instructions + +### 1. ONNXRuntime Linking + +
+You have two options to link the ONNXRuntime library: + +- **Option 1: Manual Linking** + + - For detailed setup, consult the [ONNX Runtime linking documentation](https://ort.pyke.io/setup/linking). + - **Linux or macOS**: + 1. Download the ONNX Runtime package from the [Releases page](https://github.com/microsoft/onnxruntime/releases). + 2. Set up the library path by exporting the `ORT_DYLIB_PATH` environment variable: + ```shell + export ORT_DYLIB_PATH=/path/to/onnxruntime/lib/libonnxruntime.so.1.19.0 + ``` + +- **Option 2: Automatic Download** + - Use the `--features auto` flag to handle downloading automatically: + ```shell + cargo run -r --example yolo --features auto + ``` + +
+ +### 2. \[Optional\] Install CUDA, CuDNN, and TensorRT + +- The CUDA execution provider requires CUDA version `12.x`. +- The TensorRT execution provider requires both CUDA `12.x` and TensorRT `10.x`. + +### 3. \[Optional\] Install ffmpeg + +To view video frames and save video inferences, install `rust-ffmpeg`. For instructions, see: +[https://github.com/zmwangx/rust-ffmpeg/wiki/Notes-on-building#dependencies](https://github.com/zmwangx/rust-ffmpeg/wiki/Notes-on-building#dependencies) + +## Get Started + +```Shell +# customized +cargo run -r -- --task detect --ver v8 --nc 6 --model xxx.onnx # YOLOv8 + +# Classify +cargo run -r -- --task classify --ver v5 --scale s --width 224 --height 224 --nc 1000 # YOLOv5 +cargo run -r -- --task classify --ver v8 --scale n --width 224 --height 224 --nc 1000 # YOLOv8 +cargo run -r -- --task classify --ver v11 --scale n --width 224 --height 224 --nc 1000 # YOLOv11 + +# Detect +cargo run -r -- --task detect --ver v5 --scale n # YOLOv5 +cargo run -r -- --task detect --ver v6 --scale n # YOLOv6 +cargo run -r -- --task detect --ver v7 --scale t # YOLOv7 +cargo run -r -- --task detect --ver v8 --scale n # YOLOv8 +cargo run -r -- --task detect --ver v9 --scale t # YOLOv9 +cargo run -r -- --task detect --ver v10 --scale n # YOLOv10 +cargo run -r -- --task detect --ver v11 --scale n # YOLOv11 +cargo run -r -- --task detect --ver rtdetr --scale l # RTDETR + +# Pose +cargo run -r -- --task pose --ver v8 --scale n # YOLOv8-Pose +cargo run -r -- --task pose --ver v11 --scale n # YOLOv11-Pose + +# Segment +cargo run -r -- --task segment --ver v5 --scale n # YOLOv5-Segment +cargo run -r -- --task segment --ver v8 --scale n # YOLOv8-Segment +cargo run -r -- --task segment --ver v11 --scale n # YOLOv8-Segment +cargo run -r -- --task segment --ver v8 --model yolo/FastSAM-s-dyn-f16.onnx # FastSAM + +# OBB +cargo run -r -- --ver v8 --task obb --scale n --width 1024 --height 1024 --source images/dota.png # YOLOv8-Obb +cargo run -r -- --ver v11 --task obb --scale n --width 1024 --height 1024 --source images/dota.png # YOLOv11-Obb +``` + +**`cargo run -- --help` for more options** + +For more details, please refer to [usls-yolo](https://github.com/jamjamjon/usls/tree/main/examples/yolo). diff --git a/examples/YOLO-Series-ONNXRuntime-Rust/src/main.rs b/examples/YOLO-Series-ONNXRuntime-Rust/src/main.rs new file mode 100644 index 000000000..3c71a2531 --- /dev/null +++ b/examples/YOLO-Series-ONNXRuntime-Rust/src/main.rs @@ -0,0 +1,236 @@ +use anyhow::Result; +use clap::Parser; + +use usls::{ + models::YOLO, Annotator, DataLoader, Device, Options, Viewer, Vision, YOLOScale, YOLOTask, + YOLOVersion, COCO_SKELETONS_16, +}; + +#[derive(Parser, Clone)] +#[command(author, version, about, long_about = None)] +pub struct Args { + /// Path to the ONNX model + #[arg(long)] + pub model: Option, + + /// Input source path + #[arg(long, default_value_t = String::from("../../ultralytics/assets/bus.jpg"))] + pub source: String, + + /// YOLO Task + #[arg(long, value_enum, default_value_t = YOLOTask::Detect)] + pub task: YOLOTask, + + /// YOLO Version + #[arg(long, value_enum, default_value_t = YOLOVersion::V8)] + pub ver: YOLOVersion, + + /// YOLO Scale + #[arg(long, value_enum, default_value_t = YOLOScale::N)] + pub scale: YOLOScale, + + /// Batch size + #[arg(long, default_value_t = 1)] + pub batch_size: usize, + + /// Minimum input width + #[arg(long, default_value_t = 224)] + pub width_min: isize, + + /// Input width + #[arg(long, default_value_t = 640)] + pub width: isize, + + /// Maximum input width + #[arg(long, default_value_t = 1024)] + pub width_max: isize, + + /// Minimum input height + #[arg(long, default_value_t = 224)] + pub height_min: isize, + + /// Input height + #[arg(long, default_value_t = 640)] + pub height: isize, + + /// Maximum input height + #[arg(long, default_value_t = 1024)] + pub height_max: isize, + + /// Number of classes + #[arg(long, default_value_t = 80)] + pub nc: usize, + + /// Class confidence + #[arg(long)] + pub confs: Vec, + + /// Enable TensorRT support + #[arg(long)] + pub trt: bool, + + /// Enable CUDA support + #[arg(long)] + pub cuda: bool, + + /// Enable CoreML support + #[arg(long)] + pub coreml: bool, + + /// Use TensorRT half precision + #[arg(long)] + pub half: bool, + + /// Device ID to use + #[arg(long, default_value_t = 0)] + pub device_id: usize, + + /// Enable performance profiling + #[arg(long)] + pub profile: bool, + + /// Disable contour drawing, for saving time + #[arg(long)] + pub no_contours: bool, + + /// Show result + #[arg(long)] + pub view: bool, + + /// Do not save output + #[arg(long)] + pub nosave: bool, +} + +fn main() -> Result<()> { + let args = Args::parse(); + + // logger + if args.profile { + tracing_subscriber::fmt() + .with_max_level(tracing::Level::INFO) + .init(); + } + + // model path + let path = match &args.model { + None => format!( + "yolo/{}-{}-{}.onnx", + args.ver.name(), + args.scale.name(), + args.task.name() + ), + Some(x) => x.to_string(), + }; + + // saveout + let saveout = match &args.model { + None => format!( + "{}-{}-{}", + args.ver.name(), + args.scale.name(), + args.task.name() + ), + Some(x) => { + let p = std::path::PathBuf::from(&x); + p.file_stem().unwrap().to_str().unwrap().to_string() + } + }; + + // device + let device = if args.cuda { + Device::Cuda(args.device_id) + } else if args.trt { + Device::Trt(args.device_id) + } else if args.coreml { + Device::CoreML(args.device_id) + } else { + Device::Cpu(args.device_id) + }; + + // build options + let options = Options::new() + .with_model(&path)? + .with_yolo_version(args.ver) + .with_yolo_task(args.task) + .with_device(device) + .with_trt_fp16(args.half) + .with_ixx(0, 0, (1, args.batch_size as _, 4).into()) + .with_ixx(0, 2, (args.height_min, args.height, args.height_max).into()) + .with_ixx(0, 3, (args.width_min, args.width, args.width_max).into()) + .with_confs(if args.confs.is_empty() { + &[0.2, 0.15] + } else { + &args.confs + }) + .with_nc(args.nc) + .with_find_contours(!args.no_contours) // find contours or not + // .with_names(&COCO_CLASS_NAMES_80) // detection class names + // .with_names2(&COCO_KEYPOINTS_17) // keypoints class names + // .exclude_classes(&[0]) + // .retain_classes(&[0, 5]) + .with_profile(args.profile); + + // build model + let mut model = YOLO::new(options)?; + + // build dataloader + let dl = DataLoader::new(&args.source)? + .with_batch(model.batch() as _) + .build()?; + + // build annotator + let annotator = Annotator::default() + .with_skeletons(&COCO_SKELETONS_16) + .without_masks(true) // no masks plotting when doing segment task + .with_bboxes_thickness(3) + .with_keypoints_name(false) // enable keypoints names + .with_saveout_subs(&["YOLO"]) + .with_saveout(&saveout); + + // build viewer + let mut viewer = if args.view { + Some(Viewer::new().with_delay(5).with_scale(1.).resizable(true)) + } else { + None + }; + + // run & annotate + for (xs, _paths) in dl { + let ys = model.forward(&xs, args.profile)?; + let images_plotted = annotator.plot(&xs, &ys, !args.nosave)?; + + // show image + match &mut viewer { + Some(viewer) => viewer.imshow(&images_plotted)?, + None => continue, + } + + // check out window and key event + match &mut viewer { + Some(viewer) => { + if !viewer.is_open() || viewer.is_key_pressed(usls::Key::Escape) { + break; + } + } + None => continue, + } + + // write video + if !args.nosave { + match &mut viewer { + Some(viewer) => viewer.write_batch(&images_plotted)?, + None => continue, + } + } + } + + // finish video write + if !args.nosave { + if let Some(viewer) = &mut viewer { + viewer.finish_write()?; + } + } + + Ok(()) +} diff --git a/examples/YOLOv8-ONNXRuntime-Rust/Cargo.toml b/examples/YOLOv8-ONNXRuntime-Rust/Cargo.toml index fcf1fb797..39dff0313 100644 --- a/examples/YOLOv8-ONNXRuntime-Rust/Cargo.toml +++ b/examples/YOLOv8-ONNXRuntime-Rust/Cargo.toml @@ -12,7 +12,7 @@ clap = { version = "4.2.4", features = ["derive"] } image = { version = "0.25.2"} imageproc = { version = "0.25.0"} ndarray = { version = "0.16" } -ort = { version = "2.0.0-rc.5", features = ["cuda", "tensorrt"]} +ort = { version = "2.0.0-rc.5", features = ["cuda", "tensorrt", "load-dynamic", "copy-dylibs", "half"]} rusttype = { version = "0.9.3" } anyhow = { version = "1.0.75" } regex = { version = "1.5.4" } diff --git a/examples/YOLOv8-ONNXRuntime-Rust/README.md b/examples/YOLOv8-ONNXRuntime-Rust/README.md index 9121c7dac..53a7da883 100644 --- a/examples/YOLOv8-ONNXRuntime-Rust/README.md +++ b/examples/YOLOv8-ONNXRuntime-Rust/README.md @@ -7,7 +7,7 @@ This repository provides a Rust demo for performing YOLOv8 tasks like `Classific - Add YOLOv8-OBB demo - Update ONNXRuntime to 1.19.x -Newly updated YOLOv8 example code is located in this repository (https://github.com/jamjamjon/usls/tree/main/examples/yolo) +Newly updated YOLOv8 example code is located in [this repository](https://github.com/jamjamjon/usls/tree/main/examples/yolo) ## Features @@ -22,25 +22,16 @@ Newly updated YOLOv8 example code is located in this repository (https://github. Please follow the Rust official installation. (https://www.rust-lang.org/tools/install) -### 2. Install ONNXRuntime +### 2. ONNXRuntime Linking -This repository use `ort` crate, which is ONNXRuntime wrapper for Rust. (https://docs.rs/ort/latest/ort/) +- #### For detailed setup instructions, refer to the [ORT documentation](https://ort.pyke.io/setup/linking). -You can follow the instruction with `ort` doc or simply do this: - -- step1: Download ONNXRuntime(https://github.com/microsoft/onnxruntime/releases) -- setp2: Set environment variable `PATH` for linking. - -On ubuntu, You can do like this: - -```bash -vim ~/.bashrc - -# Add the path of ONNXRUntime lib -export LD_LIBRARY_PATH=/home/qweasd/Documents/onnxruntime-linux-x64-gpu-1.16.3/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} - -source ~/.bashrc -``` +- #### For Linux or macOS Users: + - Download the ONNX Runtime package from the [Releases page](https://github.com/microsoft/onnxruntime/releases). + - Set up the library path by exporting the `ORT_DYLIB_PATH` environment variable: + ```shell + export ORT_DYLIB_PATH=/path/to/onnxruntime/lib/libonnxruntime.so.1.19.0 + ``` ### 3. \[Optional\] Install CUDA & CuDNN & TensorRT diff --git a/examples/YOLOv8-ONNXRuntime-Rust/src/lib.rs b/examples/YOLOv8-ONNXRuntime-Rust/src/lib.rs index 849801ee4..0084535ee 100644 --- a/examples/YOLOv8-ONNXRuntime-Rust/src/lib.rs +++ b/examples/YOLOv8-ONNXRuntime-Rust/src/lib.rs @@ -118,16 +118,15 @@ pub fn check_font(font: &str) -> rusttype::Font<'static> { rusttype::Font::try_from_vec(buffer).unwrap() } - use ab_glyph::FontArc; -pub fn load_font() -> FontArc{ +pub fn load_font() -> FontArc { use std::path::Path; let font_path = Path::new("./font/Arial.ttf"); match font_path.try_exists() { Ok(true) => { let buffer = std::fs::read(font_path).unwrap(); FontArc::try_from_vec(buffer).unwrap() - }, + } Ok(false) => { std::fs::create_dir_all("./font").unwrap(); println!("Downloading font..."); @@ -136,7 +135,7 @@ pub fn load_font() -> FontArc{ .timeout(std::time::Duration::from_secs(500)) .call() .unwrap_or_else(|err| panic!("> Failed to download font: {source_url}: {err:?}")); - + // read to buffer let mut buffer = vec![]; let total_size = resp @@ -153,9 +152,9 @@ pub fn load_font() -> FontArc{ fd.write_all(&buffer).unwrap(); println!("Font saved at: {:?}", font_path.display()); FontArc::try_from_vec(buffer).unwrap() - }, + } Err(e) => { panic!("Failed to load font {}", e); - }, + } } -} \ No newline at end of file +} diff --git a/examples/YOLOv8-ONNXRuntime-Rust/src/model.rs b/examples/YOLOv8-ONNXRuntime-Rust/src/model.rs index e0c35f6c2..95b2bdfff 100644 --- a/examples/YOLOv8-ONNXRuntime-Rust/src/model.rs +++ b/examples/YOLOv8-ONNXRuntime-Rust/src/model.rs @@ -8,7 +8,7 @@ use rand::{thread_rng, Rng}; use std::path::PathBuf; use crate::{ - load_font, gen_time_string, non_max_suppression, Args, Batch, Bbox, Embedding, OrtBackend, + gen_time_string, load_font, non_max_suppression, Args, Batch, Bbox, Embedding, OrtBackend, OrtConfig, OrtEP, Point2, YOLOResult, YOLOTask, SKELETON, }; @@ -40,7 +40,7 @@ impl YOLOv8 { OrtEP::CUDA(config.device_id) } else { OrtEP::CPU - }; + }; // batch let batch = Batch { @@ -463,7 +463,7 @@ impl YOLOv8 { image::Rgb(self.color_palette[bbox.id()].into()), bbox.xmin() as i32, (bbox.ymin() - legend_size as f32) as i32, - legend_size as f32, + legend_size as f32, &font, &legend, ); From 7453a1c3fc5d469a55a2e0fd8c8e42d2195a46d2 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Sat, 2 Nov 2024 14:41:23 +0100 Subject: [PATCH 11/18] Fix Docker badges (#17321) Signed-off-by: UltralyticsAssistant Co-authored-by: UltralyticsAssistant --- README.md | 6 +++--- README.zh-CN.md | 6 +++--- docs/en/index.md | 21 +++++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 51f13230e..01277aff5 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@
Ultralytics CI + Ultralytics Downloads Ultralytics YOLO Citation - Ultralytics Docker Pulls Ultralytics Discord Ultralytics Forums Ultralytics Reddit @@ -55,7 +55,7 @@ See below for a quickstart install and usage examples, and see our [Docs](https: Pip install the ultralytics package including all [requirements](https://github.com/ultralytics/ultralytics/blob/main/pyproject.toml) in a [**Python>=3.8**](https://www.python.org/) environment with [**PyTorch>=1.8**](https://pytorch.org/get-started/locally/). -[![PyPI - Version](https://img.shields.io/pypi/v/ultralytics?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics/) [![Downloads](https://static.pepy.tech/badge/ultralytics)](https://pepy.tech/project/ultralytics) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics/) +[![PyPI - Version](https://img.shields.io/pypi/v/ultralytics?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics/) [![Ultralytics Downloads](https://static.pepy.tech/badge/ultralytics)](https://pepy.tech/project/ultralytics) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics/) ```bash pip install ultralytics @@ -63,7 +63,7 @@ pip install ultralytics For alternative installation methods including [Conda](https://anaconda.org/conda-forge/ultralytics), [Docker](https://hub.docker.com/r/ultralytics/ultralytics), and Git, please refer to the [Quickstart Guide](https://docs.ultralytics.com/quickstart/). -[![Conda Version](https://img.shields.io/conda/vn/conda-forge/ultralytics?logo=condaforge)](https://anaconda.org/conda-forge/ultralytics) [![Docker Image Version](https://img.shields.io/docker/v/ultralytics/ultralytics?sort=semver&logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) +[![Conda Version](https://img.shields.io/conda/vn/conda-forge/ultralytics?logo=condaforge)](https://anaconda.org/conda-forge/ultralytics) [![Docker Image Version](https://img.shields.io/docker/v/ultralytics/ultralytics?sort=semver&logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) [![Ultralytics Docker Pulls](https://img.shields.io/docker/pulls/ultralytics/ultralytics?logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) diff --git a/README.zh-CN.md b/README.zh-CN.md index d7665f166..caf5e6b47 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -8,8 +8,8 @@
Ultralytics CI + Ultralytics Downloads Ultralytics YOLO Citation - Ultralytics Docker Pulls Ultralytics Discord Ultralytics Forums Ultralytics Reddit @@ -55,7 +55,7 @@ 在 [**Python>=3.8**](https://www.python.org/) 环境中使用 [**PyTorch>=1.8**](https://pytorch.org/get-started/locally/) 通过 pip 安装包含所有[依赖项](https://github.com/ultralytics/ultralytics/blob/main/pyproject.toml) 的 ultralytics 包。 -[![PyPI - Version](https://img.shields.io/pypi/v/ultralytics?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics/) [![Downloads](https://static.pepy.tech/badge/ultralytics)](https://pepy.tech/project/ultralytics) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics/) +[![PyPI - Version](https://img.shields.io/pypi/v/ultralytics?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics/) [![Ultralytics Downloads](https://static.pepy.tech/badge/ultralytics)](https://pepy.tech/project/ultralytics) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics/) ```bash pip install ultralytics @@ -63,7 +63,7 @@ pip install ultralytics 有关其他安装方法,包括 [Conda](https://anaconda.org/conda-forge/ultralytics)、[Docker](https://hub.docker.com/r/ultralytics/ultralytics) 和 Git,请参阅 [快速开始指南](https://docs.ultralytics.com/quickstart/)。 -[![Conda Version](https://img.shields.io/conda/vn/conda-forge/ultralytics?logo=condaforge)](https://anaconda.org/conda-forge/ultralytics) [![Docker Image Version](https://img.shields.io/docker/v/ultralytics/ultralytics?sort=semver&logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) +[![Conda Version](https://img.shields.io/conda/vn/conda-forge/ultralytics?logo=condaforge)](https://anaconda.org/conda-forge/ultralytics) [![Docker Image Version](https://img.shields.io/docker/v/ultralytics/ultralytics?sort=semver&logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) [![Ultralytics Docker Pulls](https://img.shields.io/docker/pulls/ultralytics/ultralytics?logo=docker)](https://hub.docker.com/r/ultralytics/ultralytics) diff --git a/docs/en/index.md b/docs/en/index.md index f796e4b48..ef1245f89 100644 --- a/docs/en/index.md +++ b/docs/en/index.md @@ -19,16 +19,17 @@ keywords: Ultralytics, YOLO, YOLO11, object detection, image segmentation, deep العربية

-Ultralytics CI -YOLO Citation -Docker Pulls -Discord -Ultralytics Forums -Ultralytics Reddit -
-Run on Gradient -Open In Colab -Open In Kaggle + Ultralytics CI + Ultralytics Downloads + Ultralytics YOLO Citation + Ultralytics Discord + Ultralytics Forums + Ultralytics Reddit +
+ Run Ultralytics on Gradient + Open Ultralytics In Colab + Open Ultralytics In Kaggle + Open Ultralytics In Binder
Introducing [Ultralytics](https://www.ultralytics.com/) [YOLO11](https://github.com/ultralytics/ultralytics), the latest version of the acclaimed real-time object detection and image segmentation model. YOLO11 is built on cutting-edge advancements in [deep learning](https://www.ultralytics.com/glossary/deep-learning-dl) and [computer vision](https://www.ultralytics.com/glossary/computer-vision-cv), offering unparalleled performance in terms of speed and [accuracy](https://www.ultralytics.com/glossary/accuracy). Its streamlined design makes it suitable for various applications and easily adaptable to different hardware platforms, from edge devices to cloud APIs. From 2a1fabcf83df6e44f451065ab46b5b0e6fd3b601 Mon Sep 17 00:00:00 2001 From: Muhammad Rizwan Munawar Date: Sun, 3 Nov 2024 04:54:06 +0500 Subject: [PATCH 12/18] Add ultralytics models publication notice in citations section (#17318) Co-authored-by: Glenn Jocher --- docs/en/models/yolo11.md | 8 ++++---- docs/en/models/yolov5.md | 8 ++++---- docs/en/models/yolov8.md | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/en/models/yolo11.md b/docs/en/models/yolo11.md index fe9115f2e..dee9344b4 100644 --- a/docs/en/models/yolo11.md +++ b/docs/en/models/yolo11.md @@ -8,10 +8,6 @@ keywords: YOLO11, state-of-the-art object detection, YOLO series, Ultralytics, c ## Overview -!!! tip "Ultralytics YOLO11 Publication" - - Ultralytics has not published a formal research paper for YOLO11 due to the rapidly evolving nature of the models. We focus on advancing the technology and making it easier to use, rather than producing static documentation. For the most up-to-date information on YOLO architecture, features, and usage, please refer to our [GitHub repository](https://github.com/ultralytics/ultralytics) and [documentation](https://docs.ultralytics.com). - YOLO11 is the latest iteration in the [Ultralytics](https://www.ultralytics.com/) YOLO series of real-time object detectors, redefining what's possible with cutting-edge [accuracy](https://www.ultralytics.com/glossary/accuracy), speed, and efficiency. Building upon the impressive advancements of previous YOLO versions, YOLO11 introduces significant improvements in architecture and training methods, making it a versatile choice for a wide range of [computer vision](https://www.ultralytics.com/glossary/computer-vision-cv) tasks. ![Ultralytics YOLO11 Comparison Plots](https://raw.githubusercontent.com/ultralytics/assets/refs/heads/main/yolo/performance-comparison.png) @@ -132,6 +128,10 @@ Note that the example below is for YOLO11 [Detect](../tasks/detect.md) models fo ## Citations and Acknowledgements +!!! tip "Ultralytics YOLO11 Publication" + + Ultralytics has not published a formal research paper for YOLO11 due to the rapidly evolving nature of the models. We focus on advancing the technology and making it easier to use, rather than producing static documentation. For the most up-to-date information on YOLO architecture, features, and usage, please refer to our [GitHub repository](https://github.com/ultralytics/ultralytics) and [documentation](https://docs.ultralytics.com). + If you use YOLO11 or any other software from this repository in your work, please cite it using the following format: !!! quote "" diff --git a/docs/en/models/yolov5.md b/docs/en/models/yolov5.md index 91c562a44..4d261df5c 100644 --- a/docs/en/models/yolov5.md +++ b/docs/en/models/yolov5.md @@ -6,10 +6,6 @@ keywords: YOLOv5, YOLOv5u, object detection, Ultralytics, anchor-free, pre-train # Ultralytics YOLOv5 -!!! tip "Ultralytics YOLOv5 Publication" - - Ultralytics has not published a formal research paper for YOLOv5 due to the rapidly evolving nature of the models. We focus on advancing the technology and making it easier to use, rather than producing static documentation. For the most up-to-date information on YOLO architecture, features, and usage, please refer to our [GitHub repository](https://github.com/ultralytics/ultralytics) and [documentation](https://docs.ultralytics.com). - ## Overview YOLOv5u represents an advancement in [object detection](https://www.ultralytics.com/glossary/object-detection) methodologies. Originating from the foundational architecture of the [YOLOv5](https://github.com/ultralytics/yolov5) model developed by Ultralytics, YOLOv5u integrates the anchor-free, objectness-free split head, a feature previously introduced in the [YOLOv8](yolov8.md) models. This adaptation refines the model's architecture, leading to an improved accuracy-speed tradeoff in object detection tasks. Given the empirical results and its derived features, YOLOv5u provides an efficient alternative for those seeking robust solutions in both research and practical applications. @@ -96,6 +92,10 @@ This example provides simple YOLOv5 training and inference examples. For full do ## Citations and Acknowledgements +!!! tip "Ultralytics YOLOv5 Publication" + + Ultralytics has not published a formal research paper for YOLOv5 due to the rapidly evolving nature of the models. We focus on advancing the technology and making it easier to use, rather than producing static documentation. For the most up-to-date information on YOLO architecture, features, and usage, please refer to our [GitHub repository](https://github.com/ultralytics/ultralytics) and [documentation](https://docs.ultralytics.com). + If you use YOLOv5 or YOLOv5u in your research, please cite the Ultralytics YOLOv5 repository as follows: !!! quote "" diff --git a/docs/en/models/yolov8.md b/docs/en/models/yolov8.md index c8e4397d1..bb4f287a9 100644 --- a/docs/en/models/yolov8.md +++ b/docs/en/models/yolov8.md @@ -6,10 +6,6 @@ keywords: YOLOv8, real-time object detection, YOLO series, Ultralytics, computer # Ultralytics YOLOv8 -!!! tip "Ultralytics YOLOv8 Publication" - - Ultralytics has not published a formal research paper for YOLOv8 due to the rapidly evolving nature of the models. We focus on advancing the technology and making it easier to use, rather than producing static documentation. For the most up-to-date information on YOLO architecture, features, and usage, please refer to our [GitHub repository](https://github.com/ultralytics/ultralytics) and [documentation](https://docs.ultralytics.com). - ## Overview YOLOv8 is the latest iteration in the YOLO series of real-time object detectors, offering cutting-edge performance in terms of accuracy and speed. Building upon the advancements of previous YOLO versions, YOLOv8 introduces new features and optimizations that make it an ideal choice for various [object detection](https://www.ultralytics.com/glossary/object-detection) tasks in a wide range of applications. @@ -169,6 +165,10 @@ Note the below example is for YOLOv8 [Detect](../tasks/detect.md) models for obj ## Citations and Acknowledgements +!!! tip "Ultralytics YOLOv8 Publication" + + Ultralytics has not published a formal research paper for YOLOv8 due to the rapidly evolving nature of the models. We focus on advancing the technology and making it easier to use, rather than producing static documentation. For the most up-to-date information on YOLO architecture, features, and usage, please refer to our [GitHub repository](https://github.com/ultralytics/ultralytics) and [documentation](https://docs.ultralytics.com). + If you use the YOLOv8 model or any other software from this repository in your work, please cite it using the following format: !!! quote "" From bf1d076e20f3e169ff25f60fb10c6e05f82db353 Mon Sep 17 00:00:00 2001 From: Muhammad Rizwan Munawar Date: Sun, 3 Nov 2024 04:55:55 +0500 Subject: [PATCH 13/18] Optimize Auto-Annotation with all args (#17315) Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher --- docs/en/models/sam-2.md | 2 ++ docs/en/models/sam.md | 2 ++ ultralytics/data/annotator.py | 17 +++++++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/en/models/sam-2.md b/docs/en/models/sam-2.md index de5881c42..86059422d 100644 --- a/docs/en/models/sam-2.md +++ b/docs/en/models/sam-2.md @@ -262,6 +262,8 @@ To auto-annotate your dataset using SAM 2, follow this example: | `conf` | `float`, optional | Confidence threshold for detection model; default is 0.25. | `0.25` | | `iou` | `float`, optional | IoU threshold for filtering overlapping boxes in detection results; default is 0.45. | `0.45` | | `imgsz` | `int`, optional | Input image resize dimension; default is 640. | `640` | +| `max_det` | `int`, optional | Limits detections per image to control outputs in dense scenes. | `300` | +| `classes` | `list`, optional | Filters predictions to specified class IDs, returning only relevant detections. | `None` | | `output_dir` | `str`, `None`, optional | Directory to save the annotated results. Defaults to a 'labels' folder in the same directory as 'data'. | `None` | This function facilitates the rapid creation of high-quality segmentation datasets, ideal for researchers and developers aiming to accelerate their projects. diff --git a/docs/en/models/sam.md b/docs/en/models/sam.md index fe4c01bd8..d6f49792e 100644 --- a/docs/en/models/sam.md +++ b/docs/en/models/sam.md @@ -217,6 +217,8 @@ To auto-annotate your dataset with the Ultralytics framework, use the `auto_anno | `conf` | `float`, optional | Confidence threshold for detection model; default is 0.25. | `0.25` | | `iou` | `float`, optional | IoU threshold for filtering overlapping boxes in detection results; default is 0.45. | `0.45` | | `imgsz` | `int`, optional | Input image resize dimension; default is 640. | `640` | +| `max_det` | `int`, optional | Limits detections per image to control outputs in dense scenes. | `300` | +| `classes` | `list`, optional | Filters predictions to specified class IDs, returning only relevant detections. | `None` | | `output_dir` | `str`, None, optional | Directory to save the annotated results. Defaults to a 'labels' folder in the same directory as 'data'. | `None` | The `auto_annotate` function takes the path to your images, with optional arguments for specifying the pre-trained detection and SAM segmentation models, the device to run the models on, and the output directory for saving the annotated results. diff --git a/ultralytics/data/annotator.py b/ultralytics/data/annotator.py index 64ee9af6c..fc3b8d076 100644 --- a/ultralytics/data/annotator.py +++ b/ultralytics/data/annotator.py @@ -6,7 +6,16 @@ from ultralytics import SAM, YOLO def auto_annotate( - data, det_model="yolo11x.pt", sam_model="sam_b.pt", device="", conf=0.25, iou=0.45, imgsz=640, output_dir=None + data, + det_model="yolo11x.pt", + sam_model="sam_b.pt", + device="", + conf=0.25, + iou=0.45, + imgsz=640, + max_det=300, + classes=None, + output_dir=None, ): """ Automatically annotates images using a YOLO object detection model and a SAM segmentation model. @@ -22,6 +31,8 @@ def auto_annotate( conf (float): Confidence threshold for detection model; default is 0.25. iou (float): IoU threshold for filtering overlapping boxes in detection results; default is 0.45. imgsz (int): Input image resize dimension; default is 640. + max_det (int): Limits detections per image to control outputs in dense scenes. + classes (list): Filters predictions to specified class IDs, returning only relevant detections. output_dir (str | None): Directory to save the annotated results. If None, a default directory is created. Examples: @@ -41,7 +52,9 @@ def auto_annotate( output_dir = data.parent / f"{data.stem}_auto_annotate_labels" Path(output_dir).mkdir(exist_ok=True, parents=True) - det_results = det_model(data, stream=True, device=device, conf=conf, iou=iou, imgsz=imgsz) + det_results = det_model( + data, stream=True, device=device, conf=conf, iou=iou, imgsz=imgsz, max_det=max_det, classes=classes + ) for result in det_results: class_ids = result.boxes.cls.int().tolist() # noqa From 2875c30072e840a3573504fd32ce8d3a9bb7698d Mon Sep 17 00:00:00 2001 From: Francesco Mattioli Date: Sun, 3 Nov 2024 01:38:00 +0100 Subject: [PATCH 14/18] New JupyterLab Dockerfile (#17071) Co-authored-by: Ultralytics Assistant <135830346+UltralyticsAssistant@users.noreply.github.com> Co-authored-by: Glenn Jocher --- .github/workflows/docker.yaml | 9 +++++++++ docker/Dockerfile-jupyter | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 docker/Dockerfile-jupyter diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index ef7dd86e9..38f30bb1b 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -170,6 +170,15 @@ jobs: docker build -f docker/Dockerfile-runner -t $t . docker push $t fi + if [[ "${{ matrix.tags }}" == "latest-python" ]]; then + t=ultralytics/ultralytics:latest-jupyter + v=ultralytics/ultralytics:${{ steps.get_version.outputs.version_tag }}-jupyter + docker build -f docker/Dockerfile-jupyter -t $t -t $v . + docker push $t + if [[ "${{ steps.check_tag.outputs.new_release }}" == "true" ]]; then + docker push $v + fi + fi trigger-actions: runs-on: ubuntu-latest diff --git a/docker/Dockerfile-jupyter b/docker/Dockerfile-jupyter new file mode 100644 index 000000000..e42639b9b --- /dev/null +++ b/docker/Dockerfile-jupyter @@ -0,0 +1,34 @@ +# Ultralytics YOLO 🚀, AGPL-3.0 license +# Builds ultralytics/ultralytics:latest-jupyter image on DockerHub https://hub.docker.com/r/ultralytics/ultralytics +# Image provides JupyterLab interface for interactive YOLO development and includes tutorial notebooks + +# Start from Python-based Ultralytics image for full Python environment +FROM ultralytics/ultralytics:latest-python + +# Install JupyterLab for interactive development +RUN /usr/local/bin/pip install jupyterlab + +# Create persistent data directory structure +RUN mkdir /data + +# Configure YOLO directory paths +RUN mkdir /data/datasets && /usr/local/bin/yolo settings datasets_dir="/data/datasets" +RUN mkdir /data/weights && /usr/local/bin/yolo settings weights_dir="/data/weights" +RUN mkdir /data/runs && /usr/local/bin/yolo settings runs_dir="/data/runs" + +# Start JupyterLab with tutorial notebook +ENTRYPOINT ["/usr/local/bin/jupyter", "lab", "--allow-root", "/ultralytics/examples/tutorial.ipynb"] + +# Usage Examples ------------------------------------------------------------------------------------------------------- + +# Build and Push +# t=ultralytics/ultralytics:latest-jupyter && sudo docker build -f docker/Dockerfile-jupyter -t $t . && sudo docker push $t + +# Run +# t=ultralytics/ultralytics:latest-jupyter && sudo docker run -it --ipc=host -p 8888:8888 $t + +# Pull and Run +# t=ultralytics/ultralytics:latest-jupyter && sudo docker pull $t && sudo docker run -it --ipc=host -p 8888:8888 $t + +# Pull and Run with local volume mounted +# t=ultralytics/ultralytics:latest-jupyter && sudo docker pull $t && sudo docker run -it --ipc=host -p 8888:8888 -v "$(pwd)"/datasets:/data/datasets $t From 5f9911a44a086d99785a4d6a9e566b5a6a6e2f52 Mon Sep 17 00:00:00 2001 From: Mohammed Yasin <32206511+Y-T-G@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:20:48 +0800 Subject: [PATCH 15/18] Update `overlap_mask` description. (#17324) Co-authored-by: UltralyticsAssistant --- docs/en/macros/train-args.md | 2 +- ultralytics/cfg/default.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/macros/train-args.md b/docs/en/macros/train-args.md index cb72bdece..ede32f910 100644 --- a/docs/en/macros/train-args.md +++ b/docs/en/macros/train-args.md @@ -43,7 +43,7 @@ | `kobj` | `2.0` | Weight of the keypoint objectness loss in pose estimation models, balancing detection confidence with pose accuracy. | | `label_smoothing` | `0.0` | Applies label smoothing, softening hard labels to a mix of the target label and a uniform distribution over labels, can improve generalization. | | `nbs` | `64` | Nominal batch size for normalization of loss. | -| `overlap_mask` | `True` | Determines whether segmentation masks should overlap during training, applicable in [instance segmentation](https://www.ultralytics.com/glossary/instance-segmentation) tasks. | +| `overlap_mask` | `True` | Determines whether object masks should be merged into a single mask for training, or kept separate for each object. In case of overlap, the smaller mask is overlayed on top of the larger mask during merge. | | `mask_ratio` | `4` | Downsample ratio for segmentation masks, affecting the resolution of masks used during training. | | `dropout` | `0.0` | Dropout rate for regularization in classification tasks, preventing overfitting by randomly omitting units during training. | | `val` | `True` | Enables validation during training, allowing for periodic evaluation of model performance on a separate dataset. | diff --git a/ultralytics/cfg/default.yaml b/ultralytics/cfg/default.yaml index 7922f6359..2ef1f4284 100644 --- a/ultralytics/cfg/default.yaml +++ b/ultralytics/cfg/default.yaml @@ -36,7 +36,7 @@ profile: False # (bool) profile ONNX and TensorRT speeds during training for log freeze: None # (int | list, optional) freeze first n layers, or freeze list of layer indices during training multi_scale: False # (bool) Whether to use multiscale during training # Segmentation -overlap_mask: True # (bool) masks should overlap during training (segment train only) +overlap_mask: True # (bool) merge object masks into a single image mask during training (segment train only) mask_ratio: 4 # (int) mask downsample ratio (segment train only) # Classification dropout: 0.0 # (float) use dropout regularization (classify train only) From f5ce64c12887cc752bd8ef5bd3271b07ecb22c27 Mon Sep 17 00:00:00 2001 From: Jairaj Jangle <25704330+JairajJangle@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:52:21 +0530 Subject: [PATCH 16/18] Generalized M1/M2 references to "Apple silicon" in train.md for broader inclusion (#17330) Co-authored-by: Glenn Jocher --- docs/en/modes/train.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/en/modes/train.md b/docs/en/modes/train.md index 9cbe79199..276bd4f69 100644 --- a/docs/en/modes/train.md +++ b/docs/en/modes/train.md @@ -1,7 +1,7 @@ --- comments: true description: Learn how to efficiently train object detection models using YOLO11 with comprehensive instructions on settings, augmentation, and hardware utilization. -keywords: Ultralytics, YOLO11, model training, deep learning, object detection, GPU training, dataset augmentation, hyperparameter tuning, model performance, M1 M2 training +keywords: Ultralytics, YOLO11, model training, deep learning, object detection, GPU training, dataset augmentation, hyperparameter tuning, model performance, apple silicon training --- # Model Training with Ultralytics YOLO @@ -107,11 +107,11 @@ Multi-GPU training allows for more efficient utilization of available hardware r yolo detect train data=coco8.yaml model=yolo11n.pt epochs=100 imgsz=640 device=0,1 ``` -### Apple M1 and M2 MPS Training +### Apple Silicon MPS Training -With the support for Apple M1 and M2 chips integrated in the Ultralytics YOLO models, it's now possible to train your models on devices utilizing the powerful Metal Performance Shaders (MPS) framework. The MPS offers a high-performance way of executing computation and image processing tasks on Apple's custom silicon. +With the support for Apple silicon chips integrated in the Ultralytics YOLO models, it's now possible to train your models on devices utilizing the powerful Metal Performance Shaders (MPS) framework. The MPS offers a high-performance way of executing computation and image processing tasks on Apple's custom silicon. -To enable training on Apple M1 and M2 chips, you should specify 'mps' as your device when initiating the training process. Below is an example of how you could do this in Python and via the command line: +To enable training on Apple silicon chips, you should specify 'mps' as your device when initiating the training process. Below is an example of how you could do this in Python and via the command line: !!! example "MPS Training Example" @@ -134,7 +134,7 @@ To enable training on Apple M1 and M2 chips, you should specify 'mps' as your de yolo detect train data=coco8.yaml model=yolo11n.pt epochs=100 imgsz=640 device=mps ``` -While leveraging the computational power of the M1/M2 chips, this enables more efficient processing of the training tasks. For more detailed guidance and advanced configuration options, please refer to the [PyTorch MPS documentation](https://pytorch.org/docs/stable/notes/mps.html). +While leveraging the computational power of the Apple silicon chips, this enables more efficient processing of the training tasks. For more detailed guidance and advanced configuration options, please refer to the [PyTorch MPS documentation](https://pytorch.org/docs/stable/notes/mps.html). ### Resuming Interrupted Trainings @@ -335,9 +335,9 @@ To resume training from an interrupted session, set the `resume` argument to `Tr Check the section on [Resuming Interrupted Trainings](#resuming-interrupted-trainings) for more information. -### Can I train YOLO11 models on Apple M1 and M2 chips? +### Can I train YOLO11 models on Apple silicon chips? -Yes, Ultralytics YOLO11 supports training on Apple M1 and M2 chips utilizing the Metal Performance Shaders (MPS) framework. Specify 'mps' as your training device. +Yes, Ultralytics YOLO11 supports training on Apple silicon chips utilizing the Metal Performance Shaders (MPS) framework. Specify 'mps' as your training device. !!! example "MPS Training Example" @@ -349,7 +349,7 @@ Yes, Ultralytics YOLO11 supports training on Apple M1 and M2 chips utilizing the # Load a pretrained model model = YOLO("yolo11n.pt") - # Train the model on M1/M2 chip + # Train the model on Apple silicon chip (M1/M2/M3/M4) results = model.train(data="coco8.yaml", epochs=100, imgsz=640, device="mps") ``` @@ -359,7 +359,7 @@ Yes, Ultralytics YOLO11 supports training on Apple M1 and M2 chips utilizing the yolo detect train data=coco8.yaml model=yolo11n.pt epochs=100 imgsz=640 device=mps ``` -For more details, refer to the [Apple M1 and M2 MPS Training](#apple-m1-and-m2-mps-training) section. +For more details, refer to the [Apple Silicon MPS Training](#apple-silicon-mps-training) section. ### What are the common training settings, and how do I configure them? From 603fa84774376b10d8783ffa9017f6b9b9b84861 Mon Sep 17 00:00:00 2001 From: Abirami Vina Date: Tue, 5 Nov 2024 05:52:46 +0530 Subject: [PATCH 17/18] Add Albumentations Integrations Docs Page (#17297) Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher Co-authored-by: Francesco Mattioli --- docs/en/integrations/albumentations.md | 160 +++++++++++++++++++++++++ docs/en/integrations/index.md | 2 + mkdocs.yml | 1 + 3 files changed, 163 insertions(+) create mode 100644 docs/en/integrations/albumentations.md diff --git a/docs/en/integrations/albumentations.md b/docs/en/integrations/albumentations.md new file mode 100644 index 000000000..3c407093e --- /dev/null +++ b/docs/en/integrations/albumentations.md @@ -0,0 +1,160 @@ +--- +comments: true +description: Learn how to use Albumentations with YOLO11 to enhance data augmentation, improve model performance, and streamline your computer vision projects. +keywords: Albumentations, YOLO11, data augmentation, Ultralytics, computer vision, object detection, model training, image transformations, machine learning +--- + +# Enhance Your Dataset to Train YOLO11 Using Albumentations + +When you are building [computer vision models](../models/index.md), the quality and variety of your [training data](../datasets/index.md) can play a big role in how well your model performs. Albumentations offers a fast, flexible, and efficient way to apply a wide range of image transformations that can improve your model's ability to adapt to real-world scenarios. It easily integrates with [Ultralytics YOLO11](https://github.com/ultralytics/ultralytics) and can help you create robust datasets for [object detection](../tasks/detect.md), [segmentation](../tasks/segment.md), and [classification](../tasks/classify.md) tasks. + +By using Albumentations, you can boost your YOLO11 training data with techniques like geometric transformations and color adjustments. In this article, we’ll see how Albumentations can improve your [data augmentation](../guides/preprocessing_annotated_data.md) process and make your [YOLO11 projects](../solutions/index.md) even more impactful. Let’s get started! + +## Albumentations for Image Augmentation + +[Albumentations](https://albumentations.ai/) is an open-source image augmentation library created in [June 2018](https://arxiv.org/pdf/1809.06839). It is designed to simplify and accelerate the image augmentation process in [computer vision](https://www.ultralytics.com/blog/exploring-image-processing-computer-vision-and-machine-vision). Created with [performance](https://www.ultralytics.com/blog/measuring-ai-performance-to-weigh-the-impact-of-your-innovations) and flexibility in mind, it supports many diverse augmentation techniques, ranging from simple transformations like rotations and flips to more complex adjustments like brightness and contrast changes. Albumentations helps developers generate rich, varied datasets for tasks like [image classification](https://www.youtube.com/watch?v=5BO0Il_YYAg), [object detection](https://www.youtube.com/watch?v=5ku7npMrW40&t=1s), and [segmentation](https://www.youtube.com/watch?v=o4Zd-IeMlSY). + +You can use Albumentations to easily apply augmentations to images, [segmentation masks](https://www.ultralytics.com/glossary/image-segmentation), [bounding boxes](https://www.ultralytics.com/glossary/bounding-box), and [key points](../datasets/pose/index.md), and make sure that all elements of your dataset are transformed together. It works seamlessly with popular deep learning frameworks like [PyTorch](../integrations/torchscript.md) and [TensorFlow](../integrations/tensorboard.md), making it accessible for a wide range of projects. + +Also, Albumentations is a great option for augmentation whether you're handling small datasets or large-scale [computer vision tasks](../tasks/index.md). It ensures fast and efficient processing, cutting down the time spent on data preparation. At the same time, it helps improve [model performance](../guides/yolo-performance-metrics.md), making your models more effective in real-world applications. + +## Key Features of Albumentations + +Albumentations offers many useful features that simplify complex image augmentations for a wide range of [computer vision applications](https://www.ultralytics.com/blog/exploring-how-the-applications-of-computer-vision-work). Here are some of the key features: + +- **Wide Range of Transformations**: Albumentations offers over [70 different transformations](https://github.com/albumentations-team/albumentations?tab=readme-ov-file#list-of-augmentations), including geometric changes (e.g., rotation, flipping), color adjustments (e.g., brightness, contrast), and noise addition (e.g., Gaussian noise). Having multiple options enables the creation of highly diverse and robust training datasets. + +

+ Example of Image Augmentations +

+ +- **High Performance Optimization**: Built on OpenCV and NumPy, Albumentations uses advanced optimization techniques like SIMD (Single Instruction, Multiple Data), which processes multiple data points simultaneously to speed up processing. It handles large datasets quickly, making it one of the fastest options available for image augmentation. + +- **Three Levels of Augmentation**: Albumentations supports three levels of augmentation: pixel-level transformations, spatial-level transformations, and mixing-level transformation. Pixel-level transformations only affect the input images without altering masks, bounding boxes, or key points. Meanwhile, both the image and its elements, like masks and bounding boxes, are transformed using spatial-level transformations. Furthermore, mixing-level transformations are a unique way to augment data as it combines multiple images into one. + +![Overview of the Different Levels of Augmentations](https://github.com/ultralytics/docs/releases/download/0/levels-of-augmentation.avif) + +- **[Benchmarking Results](https://albumentations.ai/docs/benchmarking_results/)**: When it comes to benchmarking, Albumentations consistently outperforms other libraries, especially with large datasets. + +## Why Should You Use Albumentations for Your Vision AI Projects? + +With respect to image augmentation, Albumentations stands out as a reliable tool for computer vision tasks. Here are a few key reasons why you should consider using it for your Vision AI projects: + +- **Easy-to-Use API**: Albumentations provides a single, straightforward API for applying a wide range of augmentations to images, masks, bounding boxes, and keypoints. It’s designed to adapt easily to different datasets, making [data preparation](../guides/data-collection-and-annotation.md) simpler and more efficient. + +- **Rigorous Bug Testing**: Bugs in the augmentation pipeline can silently corrupt input data, often going unnoticed but ultimately degrading model performance. Albumentations addresses this with a thorough test suite that helps catch bugs early in development. + +- **Extensibility**: Albumentations can be used to easily add new augmentations and use them in computer vision pipelines through a single interface along with built-in transformations. + +## How to Use Albumentations to Augment Data for YOLO11 Training + +Now that we’ve covered what Albumentations is and what it can do, let’s look at how to use it to augment your data for YOLO11 model training. It’s easy to set up because it integrates directly into [Ultralytics’ training mode](../modes/train.md) and applies automatically if you have the Albumentations package installed. + +### Installation + +To use Albumentations with YOLOv11, start by making sure you have the necessary packages installed. If Albumentations isn’t installed, the augmentations won’t be applied during training. Once set up, you’ll be ready to create an augmented dataset for training, with Albumentations integrated to enhance your model automatically. + +!!! tip "Installation" + + === "CLI" + + ```bash + # Install the required packages + pip install albumentations ultralytics + ``` + +For detailed instructions and best practices related to the installation process, check our [Ultralytics Installation guide](../quickstart.md). While installing the required packages for YOLO11, if you encounter any difficulties, consult our [Common Issues guide](../guides/yolo-common-issues.md) for solutions and tips. + +### Usage + +After installing the necessary packages, you’re ready to start using Albumentations with YOLO11. When you train YOLOv11, a set of augmentations is automatically applied through its integration with Albumentations, making it easy to enhance your model’s performance. + +!!! example "Usage" + + === "Python" + + ```python + from ultralytics import YOLO + + # Load a pre-trained model + model = YOLO("yolo11n.pt") + + # Train the model + results = model.train(data="coco8.yaml", epochs=100, imgsz=640) + ``` + +Next, let’s take look a closer look at the specific augmentations that are applied during training. + +### Blur + +The Blur transformation in Albumentations applies a simple blur effect to the image by averaging pixel values within a small square area, or kernel. This is done using OpenCV’s `cv2.blur` function, which helps reduce noise in the image, though it also slightly reduces image details. + +Here are the parameters and values used in this integration: + +- **blur_limit**: This controls the size range of the blur effect. The default range is (3, 7), meaning the kernel size for the blur can vary between 3 and 7 pixels, with only odd numbers allowed to keep the blur centered. + +- **p**: The probability of applying the blur. In the integration, p=0.01, so there’s a 1% chance that this blur will be applied to each image. The low probability allows for occasional blur effects, introducing a bit of variation to help the model generalize without over-blurring the images. + +An Example of the Blur Augmentation + +### Median Blur + +The MedianBlur transformation in Albumentations applies a median blur effect to the image, which is particularly useful for reducing noise while preserving edges. Unlike typical blurring methods, MedianBlur uses a median filter, which is especially effective at removing salt-and-pepper noise while maintaining sharpness around the edges. + +Here are the parameters and values used in this integration: + +- **blur_limit**: This parameter controls the maximum size of the blurring kernel. In this integration, it defaults to a range of (3, 7), meaning the kernel size for the blur is randomly chosen between 3 and 7 pixels, with only odd values allowed to ensure proper alignment. + +- **p**: Sets the probability of applying the median blur. Here, p=0.01, so the transformation has a 1% chance of being applied to each image. This low probability ensures that the median blur is used sparingly, helping the model generalize by occasionally seeing images with reduced noise and preserved edges. + +The image below shows an example of this augmentation applied to an image. + +An Example of the MedianBlur Augmentation + +### Grayscale + +The ToGray transformation in Albumentations converts an image to grayscale, reducing it to a single-channel format and optionally replicating this channel to match a specified number of output channels. Different methods can be used to adjust how grayscale brightness is calculated, ranging from simple averaging to more advanced techniques for realistic perception of contrast and brightness. + +Here are the parameters and values used in this integration: + +- **num_output_channels**: Sets the number of channels in the output image. If this value is more than 1, the single grayscale channel will be replicated to create a multi-channel grayscale image. By default, it’s set to 3, giving a grayscale image with three identical channels. + +- **method**: Defines the grayscale conversion method. The default method, "weighted_average", applies a formula (0.299R + 0.587G + 0.114B) that closely aligns with human perception, providing a natural-looking grayscale effect. Other options, like "from_lab", "desaturation", "average", "max", and "pca", offer alternative ways to create grayscale images based on various needs for speed, brightness emphasis, or detail preservation. + +- **p**: Controls how often the grayscale transformation is applied. With p=0.01, there is a 1% chance of converting each image to grayscale, making it possible for a mix of color and grayscale images to help the model generalize better. + +The image below shows an example of this grayscale transformation applied. + +An Example of the ToGray Augmentation + +### Contrast Limited Adaptive Histogram Equalization (CLAHE) + +The CLAHE transformation in Albumentations applies Contrast Limited Adaptive Histogram Equalization (CLAHE), a technique that enhances image contrast by equalizing the histogram in localized regions (tiles) instead of across the whole image. CLAHE produces a balanced enhancement effect, avoiding the overly amplified contrast that can result from standard histogram equalization, especially in areas with initially low contrast. + +Here are the parameters and values used in this integration: + +- **clip_limit**: Controls the contrast enhancement range. Set to a default range of (1, 4), it determines the maximum contrast allowed in each tile. Higher values are used for more contrast but may also introduce noise. + +- **tile_grid_size**: Defines the size of the grid of tiles, typically as (rows, columns). The default value is (8, 8), meaning the image is divided into an 8x8 grid. Smaller tile sizes provide more localized adjustments, while larger ones create effects closer to global equalization. + +- **p**: The probability of applying CLAHE. Here, p=0.01 introduces the enhancement effect only 1% of the time, ensuring that contrast adjustments are applied sparingly for occasional variation in training images. + +The image below shows an example of the CLAHE transformation applied. + +An Example of the CLAHE Augmentation + +## Keep Learning about Albumentations + +If you are interested in learning more about Albumentations, check out the following resources for more in-depth instructions and examples: + +- **[Albumentations Documentation](https://albumentations.ai/docs/)**: The official documentation provides a full range of supported transformations and advanced usage techniques. + +- **[Ultralytics Albumentations Guide](https://docs.ultralytics.com/reference/data/augment/?h=albumentation#ultralytics.data.augment.Albumentations)**: Get a closer look at the details of the function that facilitate this integration. + +- **[Albumentations GitHub Repository](https://github.com/albumentations-team/albumentations/)**: The repository includes examples, benchmarks, and discussions to help you get started with customizing augmentations. + +## Key Takeaways + +In this guide, we explored the key aspects of Albumentations, a great Python library for image augmentation. We discussed its wide range of transformations, optimized performance, and how you can use it in your next YOLO11 project. + +Also, if you'd like to know more about other Ultralytics YOLO11 integrations, visit our [integration guide page](../integrations/index.md). You'll find valuable resources and insights there. diff --git a/docs/en/integrations/index.md b/docs/en/integrations/index.md index f2859e838..05af43993 100644 --- a/docs/en/integrations/index.md +++ b/docs/en/integrations/index.md @@ -59,6 +59,8 @@ Welcome to the Ultralytics Integrations page! This page provides an overview of - [VS Code](vscode.md): An extension for VS Code that provides code snippets for accelerating development workflows with Ultralytics and also for anyone looking for examples to help learn or get started with Ultralytics. +- [Albumentations](albumentations.md): Enhance your Ultralytics models with powerful image augmentations to improve model robustness and generalization. + ## Deployment Integrations - [CoreML](coreml.md): CoreML, developed by [Apple](https://www.apple.com/), is a framework designed for efficiently integrating machine learning models into applications across iOS, macOS, watchOS, and tvOS, using Apple's hardware for effective and secure [model deployment](https://www.ultralytics.com/glossary/model-deployment). diff --git a/mkdocs.yml b/mkdocs.yml index 3ee15f83b..20d8ec3bf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -417,6 +417,7 @@ nav: - TorchScript: integrations/torchscript.md - VS Code: integrations/vscode.md - Weights & Biases: integrations/weights-biases.md + - Albumentations: integrations/albumentations.md - HUB: - hub/index.md - Web: From d0abd95f95211851cb37004510f03191ac8d12be Mon Sep 17 00:00:00 2001 From: Mohammed Yasin <32206511+Y-T-G@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:48:33 +0800 Subject: [PATCH 18/18] Fix error on TensorRT export with float `workspace` value (#17352) --- ultralytics/engine/exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ultralytics/engine/exporter.py b/ultralytics/engine/exporter.py index 223454f60..e764dd4dc 100644 --- a/ultralytics/engine/exporter.py +++ b/ultralytics/engine/exporter.py @@ -791,7 +791,7 @@ class Exporter: LOGGER.warning(f"{prefix} WARNING ⚠️ 'dynamic=True' model requires max batch size, i.e. 'batch=16'") profile = builder.create_optimization_profile() min_shape = (1, shape[1], 32, 32) # minimum input shape - max_shape = (*shape[:2], *(max(1, self.args.workspace) * d for d in shape[2:])) # max input shape + max_shape = (*shape[:2], *(int(max(1, self.args.workspace) * d) for d in shape[2:])) # max input shape for inp in inputs: profile.set_shape(inp.name, min=min_shape, opt=shape, max=max_shape) config.add_optimization_profile(profile)