Merge branch 'main' into afpn

afpn
Glenn Jocher 1 year ago committed by GitHub
commit e985fa2018
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .pre-commit-config.yaml
  2. 2
      README.md
  3. 2
      README.zh-CN.md
  4. 1
      docker/Dockerfile
  5. 1
      docker/Dockerfile-arm64
  6. 1
      docker/Dockerfile-cpu
  7. 1
      docker/Dockerfile-jetson
  8. 1
      docker/Dockerfile-python
  9. 6
      docs/guides/kfold-cross-validation.md
  10. 2
      docs/integrations/openvino.md
  11. 69
      docs/integrations/ray-tune.md
  12. 2
      docs/modes/predict.md
  13. 71
      docs/modes/track.md
  14. 2
      setup.py
  15. 2
      ultralytics/__init__.py
  16. 4
      ultralytics/data/annotator.py
  17. 3
      ultralytics/engine/exporter.py
  18. 5
      ultralytics/utils/__init__.py
  19. 53
      ultralytics/utils/checks.py

@ -60,7 +60,7 @@ repos:
hooks:
- id: codespell
args:
- --ignore-words-list=crate,nd,strack,dota,ane
- --ignore-words-list=crate,nd,strack,dota,ane,segway,fo
# - repo: https://github.com/asottile/yesqa
# rev: v1.4.0

@ -65,7 +65,7 @@ Pip install the ultralytics package including all [requirements](https://github.
pip install ultralytics
```
For alternative installation methods including Conda, Docker, and Git, please refer to the [Quickstart Guide](https://docs.ultralytics.com/quickstart).
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).
</details>

@ -65,7 +65,7 @@
pip install ultralytics
```
如需使用包括Conda、Docker和Git在内的其他安装方法,请参考[快速入门指南](https://docs.ultralytics.com/quickstart)。
如需使用包括[Conda](https://anaconda.org/conda-forge/ultralytics)[Docker](https://hub.docker.com/r/ultralytics/ultralytics)和Git在内的其他安装方法,请参考[快速入门指南](https://docs.ultralytics.com/quickstart)。
</details>

@ -20,7 +20,6 @@ RUN apt update \
RUN apt upgrade --no-install-recommends -y openssl tar
# Create working directory
RUN mkdir -p /usr/src/ultralytics
WORKDIR /usr/src/ultralytics
# Copy contents

@ -15,7 +15,6 @@ RUN apt update \
# RUN alias python=python3
# Create working directory
RUN mkdir -p /usr/src/ultralytics
WORKDIR /usr/src/ultralytics
# Copy contents

@ -15,7 +15,6 @@ RUN apt update \
# RUN alias python=python3
# Create working directory
RUN mkdir -p /usr/src/ultralytics
WORKDIR /usr/src/ultralytics
# Copy contents

@ -15,7 +15,6 @@ RUN apt update \
# RUN alias python=python3
# Create working directory
RUN mkdir -p /usr/src/ultralytics
WORKDIR /usr/src/ultralytics
# Copy contents

@ -15,7 +15,6 @@ RUN apt update \
# RUN alias python=python3
# Create working directory
RUN mkdir -p /usr/src/ultralytics
WORKDIR /usr/src/ultralytics
# Copy contents

@ -4,12 +4,16 @@ description: An in-depth guide demonstrating the implementation of K-Fold Cross
keywords: K-Fold cross validation, Ultralytics, YOLO detection format, Python, sklearn, object detection
---
# K-Fold Cross Validation in the Ultralytics Ecosystem
# K-Fold Cross Validation with Ultralytics
## Introduction
This comprehensive guide illustrates the implementation of K-Fold Cross Validation for object detection datasets within the Ultralytics ecosystem. We'll leverage the YOLO detection format and key Python libraries such as sklearn, pandas, and PyYaml to guide you through the necessary setup, the process of generating feature vectors, and the execution of a K-Fold dataset split.
<p align="center">
<img width="800" src="https://user-images.githubusercontent.com/26833433/258589390-8d815058-ece8-48b9-a94e-0e1ab53ea0f6.png" alt="K-Fold Cross Validation Overview">
</p>
Whether your project involves the Fruit Detection dataset or a custom data source, this tutorial aims to help you comprehend and apply K-Fold Cross Validation to bolster the reliability and robustness of your machine learning models. While we're applying `k=5` folds for this tutorial, keep in mind that the optimal number of folds can vary depending on your dataset and the specifics of your project.
Without further ado, let's dive in!

@ -4,7 +4,7 @@ description: Discover the power of deploying your Ultralytics YOLOv8 model using
keywords: ultralytics docs, YOLOv8, export YOLOv8, YOLOv8 model deployment, exporting YOLOv8, OpenVINO, OpenVINO format
---
<img width="1024" src="https://user-images.githubusercontent.com/26833433/252345644-0cf84257-4b34-404c-b7ce-eb73dfbcaff1.png">
<img width="1024" src="https://user-images.githubusercontent.com/26833433/252345644-0cf84257-4b34-404c-b7ce-eb73dfbcaff1.png" alt="OpenVINO Ecosystem">
**Export mode** is used for exporting a YOLOv8 model to a format that can be used for deployment. In this guide, we specifically cover exporting to OpenVINO, which can provide up to 3x [CPU](https://docs.openvino.ai/2023.0/openvino_docs_OV_UG_supported_plugins_CPU.html) speedup as well as accelerating on other Intel hardware ([iGPU](https://docs.openvino.ai/2023.0/openvino_docs_OV_UG_supported_plugins_GPU.html), [dGPU](https://docs.openvino.ai/2023.0/openvino_docs_OV_UG_supported_plugins_GPU.html), [VPU](https://docs.openvino.ai/2022.3/openvino_docs_OV_UG_supported_plugins_VPU.html), etc.).

@ -14,7 +14,9 @@ Hyperparameter tuning is vital in achieving peak model performance by discoverin
### Ray Tune
![Ray Tune Overview](https://docs.ray.io/en/latest/_images/tune_overview.png)
<p align="center">
<img width="640" src="https://docs.ray.io/en/latest/_images/tune_overview.png" alt="Ray Tune Overview">
</p>
[Ray Tune](https://docs.ray.io/en/latest/tune/index.html) is a hyperparameter tuning library designed for efficiency and flexibility. It supports various search strategies, parallelism, and early stopping strategies, and seamlessly integrates with popular machine learning frameworks, including Ultralytics YOLOv8.
@ -43,7 +45,10 @@ To install the required packages, run:
```python
from ultralytics import YOLO
# Load a YOLOv8n model
model = YOLO("yolov8n.pt")
# Start tuning hyperparameters for YOLOv8n training on the COCO128 dataset
result_grid = model.tune(data="coco128.yaml")
```
@ -51,14 +56,14 @@ To install the required packages, run:
The `tune()` method in YOLOv8 provides an easy-to-use interface for hyperparameter tuning with Ray Tune. It accepts several arguments that allow you to customize the tuning process. Below is a detailed explanation of each parameter:
| Parameter | Type | Description | Default Value |
|-----------------|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| `data` | str | The dataset configuration file (in YAML format) to run the tuner on. This file should specify the training and validation data paths, as well as other dataset-specific settings. | |
| `space` | dict, optional | A dictionary defining the hyperparameter search space for Ray Tune. Each key corresponds to a hyperparameter name, and the value specifies the range of values to explore during tuning. If not provided, YOLOv8 uses a default search space with various hyperparameters. | |
| `grace_period` | int, optional | The grace period in epochs for the [ASHA scheduler](https://docs.ray.io/en/latest/tune/api/schedulers.html) in Ray Tune. The scheduler will not terminate any trial before this number of epochs, allowing the model to have some minimum training before making a decision on early stopping. | 10 |
| `gpu_per_trial` | int, optional | The number of GPUs to allocate per trial during tuning. This helps manage GPU usage, particularly in multi-GPU environments. If not provided, the tuner will use all available GPUs. | None |
| `max_samples` | int, optional | The maximum number of trials to run during tuning. This parameter helps control the total number of hyperparameter combinations tested, ensuring the tuning process does not run indefinitely. | 10 |
| `**train_args` | dict, optional | Additional arguments to pass to the `train()` method during tuning. These arguments can include settings like the number of training epochs, batch size, and other training-specific configurations. | {} |
| Parameter | Type | Description | Default Value |
|-----------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| `data` | `str` | The dataset configuration file (in YAML format) to run the tuner on. This file should specify the training and validation data paths, as well as other dataset-specific settings. | |
| `space` | `dict, optional` | A dictionary defining the hyperparameter search space for Ray Tune. Each key corresponds to a hyperparameter name, and the value specifies the range of values to explore during tuning. If not provided, YOLOv8 uses a default search space with various hyperparameters. | |
| `grace_period` | `int, optional` | The grace period in epochs for the [ASHA scheduler](https://docs.ray.io/en/latest/tune/api/schedulers.html) in Ray Tune. The scheduler will not terminate any trial before this number of epochs, allowing the model to have some minimum training before making a decision on early stopping. | 10 |
| `gpu_per_trial` | `int, optional` | The number of GPUs to allocate per trial during tuning. This helps manage GPU usage, particularly in multi-GPU environments. If not provided, the tuner will use all available GPUs. | None |
| `max_samples` | `int, optional` | The maximum number of trials to run during tuning. This parameter helps control the total number of hyperparameter combinations tested, ensuring the tuning process does not run indefinitely. | 10 |
| `**train_args` | `dict, optional` | Additional arguments to pass to the `train()` method during tuning. These arguments can include settings like the number of training epochs, batch size, and other training-specific configurations. | {} |
By customizing these parameters, you can fine-tune the hyperparameter optimization process to suit your specific needs and available computational resources.
@ -66,29 +71,29 @@ By customizing these parameters, you can fine-tune the hyperparameter optimizati
The following table lists the default search space parameters for hyperparameter tuning in YOLOv8 with Ray Tune. Each parameter has a specific value range defined by `tune.uniform()`.
| Parameter | Value Range | Description |
|-----------------|----------------------------|------------------------------------------|
| lr0 | `tune.uniform(1e-5, 1e-1)` | Initial learning rate |
| lrf | `tune.uniform(0.01, 1.0)` | Final learning rate factor |
| momentum | `tune.uniform(0.6, 0.98)` | Momentum |
| weight_decay | `tune.uniform(0.0, 0.001)` | Weight decay |
| warmup_epochs | `tune.uniform(0.0, 5.0)` | Warmup epochs |
| warmup_momentum | `tune.uniform(0.0, 0.95)` | Warmup momentum |
| box | `tune.uniform(0.02, 0.2)` | Box loss weight |
| cls | `tune.uniform(0.2, 4.0)` | Class loss weight |
| hsv_h | `tune.uniform(0.0, 0.1)` | Hue augmentation range |
| hsv_s | `tune.uniform(0.0, 0.9)` | Saturation augmentation range |
| hsv_v | `tune.uniform(0.0, 0.9)` | Value (brightness) augmentation range |
| degrees | `tune.uniform(0.0, 45.0)` | Rotation augmentation range (degrees) |
| translate | `tune.uniform(0.0, 0.9)` | Translation augmentation range |
| scale | `tune.uniform(0.0, 0.9)` | Scaling augmentation range |
| shear | `tune.uniform(0.0, 10.0)` | Shear augmentation range (degrees) |
| perspective | `tune.uniform(0.0, 0.001)` | Perspective augmentation range |
| flipud | `tune.uniform(0.0, 1.0)` | Vertical flip augmentation probability |
| fliplr | `tune.uniform(0.0, 1.0)` | Horizontal flip augmentation probability |
| mosaic | `tune.uniform(0.0, 1.0)` | Mosaic augmentation probability |
| mixup | `tune.uniform(0.0, 1.0)` | Mixup augmentation probability |
| copy_paste | `tune.uniform(0.0, 1.0)` | Copy-paste augmentation probability |
| Parameter | Value Range | Description |
|-------------------|----------------------------|------------------------------------------|
| `lr0` | `tune.uniform(1e-5, 1e-1)` | Initial learning rate |
| `lrf` | `tune.uniform(0.01, 1.0)` | Final learning rate factor |
| `momentum` | `tune.uniform(0.6, 0.98)` | Momentum |
| `weight_decay` | `tune.uniform(0.0, 0.001)` | Weight decay |
| `warmup_epochs` | `tune.uniform(0.0, 5.0)` | Warmup epochs |
| `warmup_momentum` | `tune.uniform(0.0, 0.95)` | Warmup momentum |
| `box` | `tune.uniform(0.02, 0.2)` | Box loss weight |
| `cls` | `tune.uniform(0.2, 4.0)` | Class loss weight |
| `hsv_h` | `tune.uniform(0.0, 0.1)` | Hue augmentation range |
| `hsv_s` | `tune.uniform(0.0, 0.9)` | Saturation augmentation range |
| `hsv_v` | `tune.uniform(0.0, 0.9)` | Value (brightness) augmentation range |
| `degrees` | `tune.uniform(0.0, 45.0)` | Rotation augmentation range (degrees) |
| `translate` | `tune.uniform(0.0, 0.9)` | Translation augmentation range |
| `scale` | `tune.uniform(0.0, 0.9)` | Scaling augmentation range |
| `shear` | `tune.uniform(0.0, 10.0)` | Shear augmentation range (degrees) |
| `perspective` | `tune.uniform(0.0, 0.001)` | Perspective augmentation range |
| `flipud` | `tune.uniform(0.0, 1.0)` | Vertical flip augmentation probability |
| `fliplr` | `tune.uniform(0.0, 1.0)` | Horizontal flip augmentation probability |
| `mosaic` | `tune.uniform(0.0, 1.0)` | Mosaic augmentation probability |
| `mixup` | `tune.uniform(0.0, 1.0)` | Mixup augmentation probability |
| `copy_paste` | `tune.uniform(0.0, 1.0)` | Copy-paste augmentation probability |
## Custom Search Space Example

@ -571,7 +571,7 @@ You can use the `plot()` method of a `Result` objects to visualize predictions.
# Show the results
for r in results:
im_array = r.plot() # plot a BGR numpy array of predictions
im = Image.fromarray(im[..., ::-1]) # RGB PIL image
im = Image.fromarray(im_array[..., ::-1]) # RGB PIL image
im.show() # show image
im.save('results.jpg') # save image
```

@ -122,7 +122,7 @@ Here is a Python script using OpenCV (`cv2`) and YOLOv8 to run object tracking o
model = YOLO('yolov8n.pt')
# Open the video file
video_path = "path/to/your/video/file.mp4"
video_path = "path/to/video.mp4"
cap = cv2.VideoCapture(video_path)
# Loop through the video frames
@ -154,6 +154,75 @@ Here is a Python script using OpenCV (`cv2`) and YOLOv8 to run object tracking o
Please note the change from `model(frame)` to `model.track(frame)`, which enables object tracking instead of simple detection. This modified script will run the tracker on each frame of the video, visualize the results, and display them in a window. The loop can be exited by pressing 'q'.
### Plotting Tracks Over Time
Visualizing object tracks over consecutive frames can provide valuable insights into the movement patterns and behavior of detected objects within a video. With Ultralytics YOLOv8, plotting these tracks is a seamless and efficient process.
In the following example, we demonstrate how to utilize YOLOv8's tracking capabilities to plot the movement of detected objects across multiple video frames. This script involves opening a video file, reading it frame by frame, and utilizing the YOLO model to identify and track various objects. By retaining the center points of the detected bounding boxes and connecting them, we can draw lines that represent the paths followed by the tracked objects.
!!! example "Plotting tracks over multiple video frames"
```python
from collections import defaultdict
import cv2
import numpy as np
from ultralytics import YOLO
# Load the YOLOv8 model
model = YOLO('yolov8n.pt')
# Open the video file
video_path = "path/to/video.mp4"
cap = cv2.VideoCapture(video_path)
# Store the track history
track_history = defaultdict(lambda: [])
# Loop through the video frames
while cap.isOpened():
# Read a frame from the video
success, frame = cap.read()
if success:
# Run YOLOv8 tracking on the frame, persisting tracks between frames
results = model.track(frame, persist=True)
# Get the boxes and track IDs
boxes = results[0].boxes.xywh.cpu()
track_ids = results[0].boxes.id.int().cpu().tolist()
# Visualize the results on the frame
annotated_frame = results[0].plot()
# Plot the tracks
for box, track_id in zip(boxes, track_ids):
x, y, w, h = box
track = track_history[track_id]
track.append((float(x), float(y))) # x, y center point
if len(track) > 30: # retain 90 tracks for 90 frames
track.pop(0)
# Draw the tracking lines
points = np.hstack(track).astype(np.int32).reshape((-1, 1, 2))
cv2.polylines(annotated_frame, [points], isClosed=False, color=(230, 230, 230), thickness=10)
# Display the annotated frame
cv2.imshow("YOLOv8 Tracking", annotated_frame)
# Break the loop if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# Break the loop if the end of the video is reached
break
# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()
```
### Multithreaded Tracking
Multithreaded tracking provides the capability to run object tracking on multiple video streams simultaneously. This is particularly useful when handling multiple video inputs, such as from multiple surveillance cameras, where concurrent processing can greatly enhance efficiency and performance.

@ -46,7 +46,7 @@ setup(
'mkdocs-material',
'mkdocstrings[python]',
'mkdocs-redirects', # for 301 redirects
'mkdocs-ultralytics-plugin>=0.0.24', # for meta descriptions and images, dates and authors
'mkdocs-ultralytics-plugin>=0.0.25', # for meta descriptions and images, dates and authors
],
'export': [
'coremltools>=6.0,<=6.2',

@ -1,6 +1,6 @@
# Ultralytics YOLO 🚀, AGPL-3.0 license
__version__ = '8.0.147'
__version__ = '8.0.148'
from ultralytics.hub import start
from ultralytics.models import RTDETR, SAM, YOLO

@ -24,13 +24,13 @@ def auto_annotate(data, det_model='yolov8x.pt', sam_model='sam_b.pt', device='',
det_results = det_model(data, stream=True, device=device)
for result in det_results:
boxes = result.boxes.xyxy # Boxes object for bbox outputs
class_ids = result.boxes.cls.int().tolist() # noqa
if len(class_ids):
boxes = result.boxes.xyxy # Boxes object for bbox outputs
sam_results = sam_model(result.orig_img, bboxes=boxes, verbose=False, save=False, device=device)
segments = sam_results[0].masks.xyn # noqa
with open(str(Path(output_dir) / Path(result.path).stem) + '.txt', 'w') as f:
with open(f'{str(Path(output_dir) / Path(result.path).stem)}.txt', 'w') as f:
for i in range(len(segments)):
s = segments[i]
if len(s) == 0:

@ -605,7 +605,8 @@ class Exporter:
# Generate calibration data for integer quantization
LOGGER.info(f"{prefix} collecting INT8 calibration images from 'data={self.args.data}'")
dataset = YOLODataset(check_det_dataset(self.args.data)['val'], imgsz=self.imgsz[0], augment=False)
data = check_det_dataset(self.args.data)
dataset = YOLODataset(data['val'], data=data, imgsz=self.imgsz[0], augment=False)
images = []
n_images = 100 # maximum number of images
for n, batch in enumerate(dataset):

@ -329,7 +329,10 @@ def yaml_load(file='data.yaml', append_filename=False):
s = re.sub(r'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010ffff]+', '', s)
# Add YAML filename to dict and return
return {**yaml.safe_load(s), 'yaml_file': str(file)} if append_filename else yaml.safe_load(s)
data = yaml.safe_load(s) or {} # always return a dict (yaml.safe_load() may return None for empty files)
if append_filename:
data['yaml_file'] = str(file)
return data
def yaml_print(yaml_file: Union[str, Path, dict]) -> None:

@ -91,29 +91,52 @@ def check_imgsz(imgsz, stride=32, min_dim=1, max_dim=2, floor=0):
def check_version(current: str = '0.0.0',
minimum: str = '0.0.0',
maximum: str = None,
name: str = 'version ',
pinned: bool = False,
hard: bool = False,
verbose: bool = False) -> bool:
"""
Check current version against the required minimum version.
Check current version against the required minimum and/or maximum version.
Args:
current (str): Current version.
minimum (str): Required minimum version.
maximum (str, optional): Required maximum version.
name (str): Name to be used in warning message.
pinned (bool): If True, versions must match exactly. If False, minimum version must be satisfied.
hard (bool): If True, raise an AssertionError if the minimum version is not met.
verbose (bool): If True, print warning message if minimum version is not met.
hard (bool): If True, raise an AssertionError if the minimum or maximum version is not met.
verbose (bool): If True, print warning message if minimum or maximum version is not met.
Returns:
(bool): True if minimum version is met, False otherwise.
(bool): True if minimum and maximum versions are met, False otherwise.
Example:
```python
# Check if current version is exactly 22.04
check_version(current='22.04', minimum='22.04', pinned=True)
# Check if current version is greater than or equal to 22.04
check_version(current='22.10', minimum='22.04')
# Check if current version is less than or equal to 22.04
check_version(current='22.04', maximum='22.04')
# Check if current version is between 20.04 (inclusive) and 22.04 (exclusive)
check_version(current='21.10', minimum='20.04', maximum='22.04')
```
"""
current, minimum = (pkg.parse_version(x) for x in (current, minimum))
result = (current == minimum) if pinned else (current >= minimum) # bool
warning_message = f'WARNING ⚠ {name}{minimum} is required by YOLOv8, but {name}{current} is currently installed'
current = pkg.parse_version(current)
minimum = pkg.parse_version(minimum)
maximum = pkg.parse_version(maximum) if maximum else None
if pinned:
result = (current == minimum)
else:
result = (current >= minimum) and (current <= maximum if maximum else True)
version_message = f'a version between {minimum} and {maximum}' if maximum else f'a minimum version {minimum}'
warning_message = f'WARNING ⚠ {name} requires {version_message}, but {name}{current} is currently installed.'
if hard:
assert result, emojis(warning_message) # assert min requirements met
assert result, emojis(warning_message) # assert version requirements met
if verbose and not result:
LOGGER.warning(warning_message)
return result
@ -209,6 +232,20 @@ def check_requirements(requirements=ROOT.parent / 'requirements.txt', exclude=()
exclude (Tuple[str]): Tuple of package names to exclude from checking.
install (bool): If True, attempt to auto-update packages that don't meet requirements.
cmds (str): Additional commands to pass to the pip install command when auto-updating.
Example:
```python
from ultralytics.utils.checks import check_requirements
# Check a requirements.txt file
check_requirements('path/to/requirements.txt')
# Check a single package
check_requirements('ultralytics>=8.0.0')
# Check multiple packages
check_requirements(['numpy', 'ultralytics>=8.0.0'])
```
"""
prefix = colorstr('red', 'bold', 'requirements:')
check_python() # check python version

Loading…
Cancel
Save