Merge branch 'main' into dev

pull/17020/head
Laughing 3 months ago committed by GitHub
commit 1544fdc62b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 47
      .github/workflows/ci.yaml
  2. 8
      .github/workflows/docker.yaml
  3. 6
      .github/workflows/docs.yml
  4. 2
      .github/workflows/format.yml
  5. 4
      .github/workflows/links.yml
  6. 19
      .github/workflows/publish.yml
  7. 2
      .github/workflows/stale.yml
  8. 1
      docker/Dockerfile
  9. 12
      docker/Dockerfile-cpu
  10. 1
      docker/Dockerfile-runner
  11. 1
      docs/en/datasets/index.md
  12. 141
      docs/en/datasets/pose/dog-pose.md
  13. 9
      docs/en/datasets/pose/index.md
  14. 2
      docs/en/guides/nvidia-jetson.md
  15. 2
      docs/en/macros/predict-args.md
  16. 21
      docs/en/modes/benchmark.md
  17. 343
      docs/overrides/javascript/extra.js
  18. 19
      docs/overrides/javascript/giscus.js
  19. 11
      docs/overrides/stylesheets/style.css
  20. 5
      mkdocs.yml
  21. 2
      ultralytics/__init__.py
  22. 23
      ultralytics/cfg/datasets/dog-pose.yaml
  23. 5
      ultralytics/data/augment.py
  24. 3
      ultralytics/engine/exporter.py
  25. 3
      ultralytics/models/fastsam/predict.py
  26. 3
      ultralytics/models/rtdetr/train.py
  27. 4
      ultralytics/solutions/heatmap.py
  28. 78
      ultralytics/solutions/object_counter.py
  29. 2
      ultralytics/utils/benchmarks.py
  30. 9
      ultralytics/utils/callbacks/wb.py

@ -52,16 +52,15 @@ jobs:
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
cache: "pip" # caching pip dependencies - uses: astral-sh/setup-uv@v3
- name: Install requirements - name: Install requirements
shell: bash # for Windows compatibility shell: bash # for Windows compatibility
run: | run: |
python -m pip install --upgrade pip wheel uv pip install --system . --extra-index-url https://download.pytorch.org/whl/cpu
pip install . --extra-index-url https://download.pytorch.org/whl/cpu
- name: Check environment - name: Check environment
run: | run: |
yolo checks yolo checks
pip list uv pip list
- name: Test HUB training - name: Test HUB training
shell: python shell: python
env: env:
@ -111,6 +110,7 @@ jobs:
- name: Install requirements - name: Install requirements
shell: bash # for Windows compatibility shell: bash # for Windows compatibility
run: | run: |
# Warnings: uv causes numpy errors during benchmarking
python -m pip install --upgrade pip wheel python -m pip install --upgrade pip wheel
pip install -e ".[export]" "coverage[toml]" --extra-index-url https://download.pytorch.org/whl/cpu pip install -e ".[export]" "coverage[toml]" --extra-index-url https://download.pytorch.org/whl/cpu
- name: Check environment - name: Check environment
@ -143,7 +143,7 @@ jobs:
coverage xml -o coverage-benchmarks.xml coverage xml -o coverage-benchmarks.xml
- name: Upload Coverage Reports to CodeCov - name: Upload Coverage Reports to CodeCov
if: github.repository == 'ultralytics/ultralytics' if: github.repository == 'ultralytics/ultralytics'
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
flags: Benchmarks flags: Benchmarks
env: env:
@ -172,12 +172,11 @@ jobs:
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
cache: "pip" # caching pip dependencies - uses: astral-sh/setup-uv@v3
- name: Install requirements - name: Install requirements
shell: bash # for Windows compatibility shell: bash # for Windows compatibility
run: | run: |
# CoreML must be installed before export due to protobuf error from AutoInstall # CoreML must be installed before export due to protobuf error from AutoInstall
python -m pip install --upgrade pip wheel
slow="" slow=""
torch="" torch=""
if [ "${{ matrix.torch }}" == "1.8.0" ]; then if [ "${{ matrix.torch }}" == "1.8.0" ]; then
@ -186,11 +185,11 @@ jobs:
if [[ "${{ github.event_name }}" =~ ^(schedule|workflow_dispatch)$ ]]; then if [[ "${{ github.event_name }}" =~ ^(schedule|workflow_dispatch)$ ]]; then
slow="faster-coco-eval mlflow" slow="faster-coco-eval mlflow"
fi fi
pip install -e ".[export]" $torch $slow pytest-cov --extra-index-url https://download.pytorch.org/whl/cpu uv pip install --system -e ".[export]" $torch $slow pytest-cov --extra-index-url https://download.pytorch.org/whl/cpu
- name: Check environment - name: Check environment
run: | run: |
yolo checks yolo checks
pip list uv pip list
- name: Pytest tests - name: Pytest tests
shell: bash # for Windows compatibility shell: bash # for Windows compatibility
run: | run: |
@ -201,7 +200,7 @@ jobs:
pytest $slow --cov=ultralytics/ --cov-report xml tests/ pytest $slow --cov=ultralytics/ --cov-report xml tests/
- name: Upload Coverage Reports to CodeCov - name: Upload Coverage Reports to CodeCov
if: github.repository == 'ultralytics/ultralytics' # && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' if: github.repository == 'ultralytics/ultralytics' # && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
flags: Tests flags: Tests
env: env:
@ -213,12 +212,13 @@ jobs:
runs-on: gpu-latest runs-on: gpu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- name: Install requirements - name: Install requirements
run: pip install . pytest-cov run: uv pip install --system . pytest-cov
- name: Check environment - name: Check environment
run: | run: |
yolo checks yolo checks
pip list uv pip list
- name: Pytest tests - name: Pytest tests
run: | run: |
slow="" slow=""
@ -227,7 +227,7 @@ jobs:
fi fi
pytest $slow --cov=ultralytics/ --cov-report xml tests/test_cuda.py pytest $slow --cov=ultralytics/ --cov-report xml tests/test_cuda.py
- name: Upload Coverage Reports to CodeCov - name: Upload Coverage Reports to CodeCov
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v5
with: with:
flags: GPU flags: GPU
env: env:
@ -294,13 +294,8 @@ jobs:
channels: conda-forge,defaults channels: conda-forge,defaults
channel-priority: true channel-priority: true
activate-environment: anaconda-client-env activate-environment: anaconda-client-env
- name: Cleanup toolcache - name: Cleanup disk space
run: | uses: ultralytics/actions/cleanup-disk@main
echo "Free space before deletion:"
df -h /
rm -rf /opt/hostedtoolcache
echo "Free space after deletion:"
df -h /
- name: Install Linux packages - name: Install Linux packages
run: | run: |
# Fix cv2 ImportError: 'libEGL.so.1: cannot open shared object file: No such file or directory' # Fix cv2 ImportError: 'libEGL.so.1: cannot open shared object file: No such file or directory'
@ -348,14 +343,14 @@ jobs:
Summary: Summary:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [HUB, Benchmarks, Tests, GPU, RaspberryPi, Conda] # Add job names that you want to check for failure needs: [HUB, Benchmarks, Tests, GPU, RaspberryPi, Conda]
if: always() # This ensures the job runs even if previous jobs fail if: always()
steps: steps:
- name: Check for failure and notify - name: Check for failure and notify
if: (needs.HUB.result == 'failure' || needs.Benchmarks.result == 'failure' || needs.Tests.result == 'failure' || needs.GPU.result == 'failure' || needs.RaspberryPi.result == 'failure' || needs.Conda.result == 'failure' ) && github.repository == 'ultralytics/ultralytics' && (github.event_name == 'schedule' || github.event_name == 'push') && github.run_attempt == '1' if: (needs.HUB.result == 'failure' || needs.Benchmarks.result == 'failure' || needs.Tests.result == 'failure' || needs.GPU.result == 'failure' || needs.RaspberryPi.result == 'failure' || needs.Conda.result == 'failure' ) && github.repository == 'ultralytics/ultralytics' && (github.event_name == 'schedule' || github.event_name == 'push') && github.run_attempt == '1'
uses: slackapi/slack-github-action@v1.27.0 uses: slackapi/slack-github-action@v2.0.0
with: with:
webhook-type: incoming-webhook
webhook: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}
payload: | payload: |
{"text": "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n"} text: "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}

@ -202,9 +202,9 @@ jobs:
steps: steps:
- name: Check for failure and notify - name: Check for failure and notify
if: needs.docker.result == 'failure' && github.repository == 'ultralytics/ultralytics' && github.event_name == 'push' && github.run_attempt == '1' if: needs.docker.result == 'failure' && github.repository == 'ultralytics/ultralytics' && github.event_name == 'push' && github.run_attempt == '1'
uses: slackapi/slack-github-action@v1.27.0 uses: slackapi/slack-github-action@v2.0.0
with: with:
webhook-type: incoming-webhook
webhook: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}
payload: | payload: |
{"text": "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n"} text: "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}

@ -29,7 +29,7 @@ on:
jobs: jobs:
Docs: Docs:
if: github.repository == 'ultralytics/ultralytics' if: github.repository == 'ultralytics/ultralytics'
runs-on: macos-14 runs-on: ubuntu-latest
steps: steps:
- name: Git config - name: Git config
run: | run: |
@ -46,9 +46,9 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
cache: "pip" # caching pip dependencies - uses: astral-sh/setup-uv@v3
- name: Install Dependencies - name: Install Dependencies
run: pip install ruff black tqdm minify-html mkdocs-material "mkdocstrings[python]" mkdocs-jupyter mkdocs-redirects mkdocs-ultralytics-plugin mkdocs-macros-plugin run: uv pip install --system ruff black tqdm minify-html mkdocs-material "mkdocstrings[python]" mkdocs-jupyter mkdocs-redirects mkdocs-ultralytics-plugin mkdocs-macros-plugin
- name: Ruff fixes - name: Ruff fixes
continue-on-error: true continue-on-error: true
run: ruff check --fix --unsafe-fixes --select D --ignore=D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 . run: ruff check --fix --unsafe-fixes --select D --ignore=D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 .

@ -15,7 +15,7 @@ on:
jobs: jobs:
format: format:
runs-on: macos-14 runs-on: ubuntu-latest
steps: steps:
- name: Run Ultralytics Formatting - name: Run Ultralytics Formatting
uses: ultralytics/actions@main uses: ultralytics/actions@main

@ -32,7 +32,7 @@ jobs:
uses: ultralytics/actions/retry@main uses: ultralytics/actions/retry@main
with: with:
timeout_minutes: 60 timeout_minutes: 60
retry_delay_seconds: 300 retry_delay_seconds: 900
retries: 2 retries: 2
run: | run: |
lychee \ lychee \
@ -62,7 +62,7 @@ jobs:
uses: ultralytics/actions/retry@main uses: ultralytics/actions/retry@main
with: with:
timeout_minutes: 60 timeout_minutes: 60
retry_delay_seconds: 300 retry_delay_seconds: 900
retries: 2 retries: 2
run: | run: |
lychee \ lychee \

@ -17,7 +17,7 @@ jobs:
if: github.repository == 'ultralytics/ultralytics' && github.actor == 'glenn-jocher' if: github.repository == 'ultralytics/ultralytics' && github.actor == 'glenn-jocher'
name: Publish name: Publish
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: # for GitHub Deployments tab environment: # for GitHub Deployments tab
name: Release - PyPI name: Release - PyPI
url: https://pypi.org/p/ultralytics url: https://pypi.org/p/ultralytics
permissions: permissions:
@ -90,19 +90,20 @@ jobs:
fi fi
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV
- name: Notify on Slack (Success) - name: Notify on Slack (Success)
if: success() && github.event_name == 'push' && steps.check_pypi.outputs.increment == 'True' if: success() && github.event_name == 'push' && steps.check_pypi.outputs.increment == 'True'
uses: slackapi/slack-github-action@v1.27.0 uses: slackapi/slack-github-action@v2.0.0
with: with:
webhook-type: incoming-webhook
webhook: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}
payload: | payload: |
{"text": "<!channel> GitHub Actions success for ${{ github.workflow }} ✅\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* NEW `${{ github.repository }} ${{ steps.check_pypi.outputs.current_tag }}` pip package published 😃\n*Job Status:* ${{ job.status }}\n*Pull Request:* <https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }}> ${{ env.PR_TITLE }}\n"} text: "<!channel> GitHub Actions success for ${{ github.workflow }} ✅\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* NEW `${{ github.repository }} ${{ steps.check_pypi.outputs.current_tag }}` pip package published 😃\n*Job Status:* ${{ job.status }}\n*Pull Request:* <https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }}> ${{ env.PR_TITLE }}\n"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}
- name: Notify on Slack (Failure) - name: Notify on Slack (Failure)
if: failure() if: failure()
uses: slackapi/slack-github-action@v1.27.0 uses: slackapi/slack-github-action@v2.0.0
with: with:
webhook-type: incoming-webhook
webhook: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}
payload: | payload: |
{"text": "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n*Job Status:* ${{ job.status }}\n*Pull Request:* <https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }}> ${{ env.PR_TITLE }}\n"} text: "<!channel> GitHub Actions error for ${{ github.workflow }} ❌\n\n\n*Repository:* https://github.com/${{ github.repository }}\n*Action:* https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n*Author:* ${{ github.actor }}\n*Event:* ${{ github.event_name }}\n*Job Status:* ${{ job.status }}\n*Pull Request:* <https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }}> ${{ env.PR_TITLE }}\n"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_YOLO }}

@ -8,7 +8,7 @@ on:
permissions: permissions:
pull-requests: write pull-requests: write
issues: write issues: write
jobs: jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest

@ -56,7 +56,6 @@ RUN pip install numpy==1.23.5
# Remove extra build files # Remove extra build files
RUN rm -rf tmp /root/.config/Ultralytics/persistent_cache.json RUN rm -rf tmp /root/.config/Ultralytics/persistent_cache.json
# Usage Examples ------------------------------------------------------------------------------------------------------- # Usage Examples -------------------------------------------------------------------------------------------------------
# Build and Push # Build and Push

@ -2,8 +2,8 @@
# Builds ultralytics/ultralytics:latest-cpu image on DockerHub https://hub.docker.com/r/ultralytics/ultralytics # Builds ultralytics/ultralytics:latest-cpu image on DockerHub https://hub.docker.com/r/ultralytics/ultralytics
# Image is CPU-optimized for ONNX, OpenVINO and PyTorch YOLO11 deployments # Image is CPU-optimized for ONNX, OpenVINO and PyTorch YOLO11 deployments
# Start FROM Ubuntu image https://hub.docker.com/_/ubuntu # Use official Python base image for reproducibility (3.11.10 for export and 3.12.6 for inference)
FROM ubuntu:23.10 FROM python:3.11.10-slim-bookworm
# Set environment variables # Set environment variables
ENV PYTHONUNBUFFERED=1 \ ENV PYTHONUNBUFFERED=1 \
@ -39,14 +39,14 @@ RUN pip install -e ".[export]" --extra-index-url https://download.pytorch.org/wh
RUN yolo export model=tmp/yolo11n.pt format=edgetpu imgsz=32 RUN yolo export model=tmp/yolo11n.pt format=edgetpu imgsz=32
RUN yolo export model=tmp/yolo11n.pt format=ncnn imgsz=32 RUN yolo export model=tmp/yolo11n.pt format=ncnn imgsz=32
# Requires Python<=3.10, bug with paddlepaddle==2.5.0 https://github.com/PaddlePaddle/X2Paddle/issues/991 # Requires Python<=3.10, bug with paddlepaddle==2.5.0 https://github.com/PaddlePaddle/X2Paddle/issues/991
# RUN pip install "paddlepaddle>=2.6.0" x2paddle RUN pip install "paddlepaddle>=2.6.0" x2paddle
# Creates a symbolic link to make 'python' point to 'python3'
RUN ln -sf /usr/bin/python3 /usr/bin/python
# Remove extra build files # Remove extra build files
RUN rm -rf tmp /root/.config/Ultralytics/persistent_cache.json RUN rm -rf tmp /root/.config/Ultralytics/persistent_cache.json
# Set default command to bash
CMD ["/bin/bash"]
# Usage Examples ------------------------------------------------------------------------------------------------------- # Usage Examples -------------------------------------------------------------------------------------------------------
# Build and Push # Build and Push

@ -35,7 +35,6 @@ ENTRYPOINT sh -c './config.sh --url https://github.com/ultralytics/ultralytics \
--replace && \ --replace && \
./run.sh' ./run.sh'
# Usage Examples ------------------------------------------------------------------------------------------------------- # Usage Examples -------------------------------------------------------------------------------------------------------
# Build and Push # Build and Push

@ -74,6 +74,7 @@ Pose estimation is a technique used to determine the pose of the object relative
- [COCO8-pose](pose/coco8-pose.md): A smaller dataset for pose estimation tasks, containing a subset of 8 COCO images with human pose annotations. - [COCO8-pose](pose/coco8-pose.md): A smaller dataset for pose estimation tasks, containing a subset of 8 COCO images with human pose annotations.
- [Tiger-pose](pose/tiger-pose.md): A compact dataset consisting of 263 images focused on tigers, annotated with 12 keypoints per tiger for pose estimation tasks. - [Tiger-pose](pose/tiger-pose.md): A compact dataset consisting of 263 images focused on tigers, annotated with 12 keypoints per tiger for pose estimation tasks.
- [Hand-Keypoints](pose/hand-keypoints.md): A concise dataset featuring over 26,000 images centered on human hands, annotated with 21 keypoints per hand, designed for pose estimation tasks. - [Hand-Keypoints](pose/hand-keypoints.md): A concise dataset featuring over 26,000 images centered on human hands, annotated with 21 keypoints per hand, designed for pose estimation tasks.
- [Dog-pose](pose/dog-pose.md): A comprehensive dataset featuring approximately 6,000 images focused on dogs, annotated with 24 keypoints per dog, tailored for pose estimation tasks.
## [Classification](classify/index.md) ## [Classification](classify/index.md)

@ -0,0 +1,141 @@
---
comments: true
description: Discover the Dog-Pose dataset for pose detection. Featuring 6,773 training and 1,703 test images, it's a robust dataset for training YOLO11 models.
keywords: Dog-Pose, Ultralytics, pose detection dataset, YOLO11, machine learning, computer vision, training data
---
# Dog-Pose Dataset
## Introduction
The [Ultralytics](https://www.ultralytics.com/) Dog-pose dataset is a high-quality and extensive dataset specifically curated for dog keypoint estimation. With 6,773 training images and 1,703 test images, this dataset provides a solid foundation for training robust pose estimation models. Each annotated image includes 24 keypoints with 3 dimensions per keypoint (x, y, visibility), making it a valuable resource for advanced research and development in computer vision.
<img src="https://github.com/ultralytics/docs/releases/download/0/ultralytics-dogs.avif" alt="Ultralytics Dog-pose display image" width="800">
This dataset is intended for use with Ultralytics [HUB](https://hub.ultralytics.com/) and [YOLO11](https://github.com/ultralytics/ultralytics).
## Dataset YAML
A YAML (Yet Another Markup Language) file is used to define the dataset configuration. It includes paths, keypoint details, and other relevant information. In the case of the Dog-pose dataset, The `dog-pose.yaml` is available at [https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/datasets/dog-pose.yaml](https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/datasets/dog-pose.yaml).
!!! example "ultralytics/cfg/datasets/dog-pose.yaml"
```yaml
--8<-- "ultralytics/cfg/datasets/dog-pose.yaml"
```
## Usage
To train a YOLO11n-pose model on the Dog-pose dataset for 100 [epochs](https://www.ultralytics.com/glossary/epoch) with an image size of 640, you can use the following code snippets. For a comprehensive list of available arguments, refer to the model [Training](../../modes/train.md) page.
!!! example "Train Example"
=== "Python"
```python
from ultralytics import YOLO
# Load a model
model = YOLO("yolo11n-pose.pt") # load a pretrained model (recommended for training)
# Train the model
results = model.train(data="dog-pose.yaml", epochs=100, imgsz=640)
```
=== "CLI"
```bash
# Start training from a pretrained *.pt model
yolo pose train data=dog-pose.yaml model=yolo11n-pose.pt epochs=100 imgsz=640
```
## Sample Images and Annotations
Here are some examples of images from the Dog-pose dataset, along with their corresponding annotations:
<img src="https://github.com/ultralytics/docs/releases/download/0/mosaiced-training-batch-2-dog-pose.avif" alt="Dataset sample image" width="800">
- **Mosaiced Image**: This image demonstrates a training batch composed of mosaiced dataset images. Mosaicing is a technique used during training that combines multiple images into a single image to increase the variety of objects and scenes within each training batch. This helps improve the model's ability to generalize to different object sizes, aspect ratios, and contexts.
The example showcases the variety and complexity of the images in the Dog-pose dataset and the benefits of using mosaicing during the training process.
## Citations and Acknowledgments
If you use the Dog-pose dataset in your research or development work, please cite the following paper:
!!! quote ""
=== "BibTeX"
```bibtex
@inproceedings{khosla2011fgvc,
title={Novel dataset for Fine-Grained Image Categorization},
author={Aditya Khosla and Nityananda Jayadevaprakash and Bangpeng Yao and Li Fei-Fei},
booktitle={First Workshop on Fine-Grained Visual Categorization (FGVC), IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
year={2011}
}
@inproceedings{deng2009imagenet,
title={ImageNet: A Large-Scale Hierarchical Image Database},
author={Jia Deng and Wei Dong and Richard Socher and Li-Jia Li and Kai Li and Li Fei-Fei},
booktitle={IEEE Computer Vision and Pattern Recognition (CVPR)},
year={2009}
}
```
We would like to acknowledge the Stanford team for creating and maintaining this valuable resource for the [computer vision](https://www.ultralytics.com/glossary/computer-vision-cv) community. For more information about the Dog-pose dataset and its creators, visit the [Stanford Dogs Dataset website](http://vision.stanford.edu/aditya86/ImageNetDogs/).
## FAQ
### What is the Dog-pose dataset, and how is it used with Ultralytics YOLO11?
The Dog-Pose dataset features 6,000 images annotated with 17 keypoints for dog pose estimation. Ideal for training and validating models with [Ultralytics YOLO11](https://docs.ultralytics.com/models/yolo11/), it supports applications like animal behavior analysis and veterinary studies.
### How do I train a YOLO11 model using the Dog-pose dataset in Ultralytics?
To train a YOLO11n-pose model on the Dog-pose dataset for 100 epochs with an image size of 640, follow these examples:
!!! example "Train Example"
=== "Python"
```python
from ultralytics import YOLO
# Load a model
model = YOLO("yolo11n-pose.pt")
# Train the model
results = model.train(data="dog-pose.yaml", epochs=100, imgsz=640)
```
=== "CLI"
```bash
yolo pose train data=dog-pose.yaml model=yolo11n-pose.pt epochs=100 imgsz=640
```
For a comprehensive list of training arguments, refer to the model [Training](../../modes/train.md) page.
### What are the benefits of using the Dog-pose dataset?
The Dog-pose dataset offers several benefits:
**Large and Diverse Dataset**: With 6,000 images, it provides a substantial amount of data covering a wide range of dog poses, breeds, and contexts, enabling robust model training and evaluation.
**Pose-specific Annotations**: Offers detailed annotations for pose estimation, ensuring high-quality data for training pose detection models.
**Real-World Scenarios**: Includes images from varied environments, enhancing the model's ability to generalize to real-world applications.
**Model Performance Improvement**: The diversity and scale of the dataset help improve model accuracy and robustness, particularly for tasks involving fine-grained pose estimation.
For more about its features and usage, see the [Dataset Introduction](#introduction) section.
### How does mosaicing benefit the YOLO11 training process using the Dog-pose dataset?
Mosaicing, as illustrated in the sample images from the Dog-pose dataset, merges multiple images into a single composite, enriching the diversity of objects and scenes in each training batch. This approach enhances the model's capacity to generalize across different object sizes, aspect ratios, and contexts, leading to improved performance. For example images, refer to the [Sample Images and Annotations](#sample-images-and-annotations) section.
### Where can I find the Dog-pose dataset YAML file and how do I use it?
The Dog-pose dataset YAML file can be found [here](https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/datasets/dog-pose.yaml). This file defines the dataset configuration, including paths, classes, and other relevant information. Use this file with the YOLO11 training scripts as mentioned in the [Train Example](#how-do-i-train-a-yolo11-model-using-the-dog-pose-dataset-in-ultralytics) section.
For more FAQs and detailed documentation, visit the [Ultralytics Documentation](https://docs.ultralytics.com/).

@ -127,6 +127,15 @@ This section outlines the datasets that are compatible with Ultralytics YOLO for
- **Usage**: Great for human hand pose estimation. - **Usage**: Great for human hand pose estimation.
- [Read more about Hand Keypoints](hand-keypoints.md) - [Read more about Hand Keypoints](hand-keypoints.md)
### Dog-Pose
- **Description**: The Dog Pose dataset contains approximately 6,000 images, providing a diverse and extensive resource for training and validation of dog pose estimation models.
- **Label Format**: Follows the Ultralytics YOLO format, with annotations for multiple keypoints specific to dog anatomy.
- **Number of Classes**: 1 (Dog).
- **Keypoints**: Includes 24 keypoints tailored to dog poses, such as limbs, joints, and head positions.
- **Usage**: Ideal for training models to estimate dog poses in various scenarios, from research to real-world applications.
- [Read more about Dog-Pose](dog-pose.md)
### Adding your own dataset ### Adding your own dataset
If you have your own dataset and would like to use it for training pose estimation models with Ultralytics YOLO format, ensure that it follows the format specified above under "Ultralytics YOLO format". Convert your annotations to the required format and specify the paths, number of classes, and class names in the YAML configuration file. If you have your own dataset and would like to use it for training pose estimation models with Ultralytics YOLO format, ensure that it follows the format specified above under "Ultralytics YOLO format". Convert your annotations to the required format and specify the paths, number of classes, and class names in the YAML configuration file.

@ -54,7 +54,7 @@ The first step after getting your hands on an NVIDIA Jetson device is to flash N
1. If you own an official NVIDIA Development Kit such as the Jetson Orin Nano Developer Kit, you can [download an image and prepare an SD card with JetPack for booting the device](https://developer.nvidia.com/embedded/learn/get-started-jetson-orin-nano-devkit). 1. If you own an official NVIDIA Development Kit such as the Jetson Orin Nano Developer Kit, you can [download an image and prepare an SD card with JetPack for booting the device](https://developer.nvidia.com/embedded/learn/get-started-jetson-orin-nano-devkit).
2. If you own any other NVIDIA Development Kit, you can [flash JetPack to the device using SDK Manager](https://docs.nvidia.com/sdk-manager/install-with-sdkm-jetson/index.html). 2. If you own any other NVIDIA Development Kit, you can [flash JetPack to the device using SDK Manager](https://docs.nvidia.com/sdk-manager/install-with-sdkm-jetson/index.html).
3. If you own a Seeed Studio reComputer J4012 device, you can [flash JetPack to the included SSD](https://wiki.seeedstudio.com/recomputer_j4012_flash_jetpack/) and if you own a Seeed Studio reComputer J1020 v2 device, you can [flash JetPack to the eMMC/ SSD](https://wiki.seeedstudio.com/reComputer_J2021_J202_Flash_Jetpack/). 3. If you own a Seeed Studio reComputer J4012 device, you can [flash JetPack to the included SSD](https://wiki.seeedstudio.com/reComputer_J4012_Flash_Jetpack/) and if you own a Seeed Studio reComputer J1020 v2 device, you can [flash JetPack to the eMMC/ SSD](https://wiki.seeedstudio.com/reComputer_J2021_J202_Flash_Jetpack/).
4. If you own any other third party device powered by the NVIDIA Jetson module, it is recommended to follow [command-line flashing](https://docs.nvidia.com/jetson/archives/r35.5.0/DeveloperGuide/IN/QuickStart.html). 4. If you own any other third party device powered by the NVIDIA Jetson module, it is recommended to follow [command-line flashing](https://docs.nvidia.com/jetson/archives/r35.5.0/DeveloperGuide/IN/QuickStart.html).
!!! note !!! note

@ -13,7 +13,7 @@
| `augment` | `bool` | `False` | Enables test-time augmentation (TTA) for predictions, potentially improving detection robustness at the cost of inference speed. | | `augment` | `bool` | `False` | Enables test-time augmentation (TTA) for predictions, potentially improving detection robustness at the cost of inference speed. |
| `agnostic_nms` | `bool` | `False` | Enables class-agnostic Non-Maximum Suppression (NMS), which merges overlapping boxes of different classes. Useful in multi-class detection scenarios where class overlap is common. | | `agnostic_nms` | `bool` | `False` | Enables class-agnostic Non-Maximum Suppression (NMS), which merges overlapping boxes of different classes. Useful in multi-class detection scenarios where class overlap is common. |
| `classes` | `list[int]` | `None` | Filters predictions to a set of class IDs. Only detections belonging to the specified classes will be returned. Useful for focusing on relevant objects in multi-class detection tasks. | | `classes` | `list[int]` | `None` | Filters predictions to a set of class IDs. Only detections belonging to the specified classes will be returned. Useful for focusing on relevant objects in multi-class detection tasks. |
| `retina_masks` | `bool` | `False` | Uses high-resolution segmentation masks if available in the model. This can enhance mask quality for segmentation tasks, providing finer detail. | | `retina_masks` | `bool` | `False` | Returns high-resolution segmentation masks. The returned masks (`masks.data`) will match the original image size if enabled. If disabled, they have the image size used during inference. |
| `embed` | `list[int]` | `None` | Specifies the layers from which to extract feature vectors or [embeddings](https://www.ultralytics.com/glossary/embeddings). Useful for downstream tasks like clustering or similarity search. | | `embed` | `list[int]` | `None` | Specifies the layers from which to extract feature vectors or [embeddings](https://www.ultralytics.com/glossary/embeddings). Useful for downstream tasks like clustering or similarity search. |
| `project` | `str` | `None` | Name of the project directory where prediction outputs are saved if `save` is enabled. | | `project` | `str` | `None` | Name of the project directory where prediction outputs are saved if `save` is enabled. |
| `name` | `str` | `None` | Name of the prediction run. Used for creating a subdirectory within the project folder, where prediction outputs are stored if `save` is enabled. | | `name` | `str` | `None` | Name of the prediction run. Used for creating a subdirectory within the project folder, where prediction outputs are stored if `save` is enabled. |

@ -18,15 +18,18 @@ keywords: model benchmarking, YOLO11, Ultralytics, performance evaluation, expor
<div style="display: flex; align-items: flex-start;"> <div style="display: flex; align-items: flex-start;">
<div style="margin-right: 20px;"> <div style="margin-right: 20px;">
<label><input type="checkbox" name="algorithm" value="YOLO11" checked><span>Ultralytics YOLO11</span></label><br> <label><input type="checkbox" name="algorithm" value="YOLO11" checked><span>YOLO11</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOv6" checked><span>YOLOv6</span></label><br> <label><input type="checkbox" name="algorithm" value="YOLOv10" checked><span>YOLOv10</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOv7" checked><span>YOLOv7</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOv10" checked><span>YOLOv10</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOv9" checked><span>YOLOv9</span></label><br> <label><input type="checkbox" name="algorithm" value="YOLOv9" checked><span>YOLOv9</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOv8" checked><span>Ultralytics YOLOv8</span></label><br> <label><input type="checkbox" name="algorithm" value="YOLOv8" checked><span>YOLOv8</span></label><br>
<label><input type="checkbox" name="algorithm" value="PPYOLOE" checked><span>PPYOLOE</span></label><br> <label><input type="checkbox" name="algorithm" value="YOLOv7" checked><span>YOLOv7</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOv5" checked><span>Ultralytics YOLOv5</span></label> <label><input type="checkbox" name="algorithm" value="YOLOv6-3.0" checked><span>YOLOv6-3.0</span></label><br>
</div> <label><input type="checkbox" name="algorithm" value="YOLOv5" checked><span>YOLOv5</span></label><br>
<label><input type="checkbox" name="algorithm" value="PP-YOLOE+" checked><span>PP-YOLOE+</span></label><br>
<label><input type="checkbox" name="algorithm" value="DAMO-YOLO" checked><span>DAMO-YOLO</span></label><br>
<label><input type="checkbox" name="algorithm" value="YOLOX" checked><span>YOLOX</span></label><br>
<label><input type="checkbox" name="algorithm" value="RTDETRv2" checked><span>RTDETRv2</span></label>
</div>
<div style="flex-grow: 1;"><canvas id="chart"></canvas></div> <!-- Canva for plotting benchmarks --> <div style="flex-grow: 1;"><canvas id="chart"></canvas></div> <!-- Canva for plotting benchmarks -->
</div> </div>
@ -102,7 +105,7 @@ Arguments such as `model`, `data`, `imgsz`, `half`, `device`, and `verbose` prov
| `imgsz` | `640` | The input image size for the model. Can be a single integer for square images or a tuple `(width, height)` for non-square, e.g., `(640, 480)`. | | `imgsz` | `640` | The input image size for the model. Can be a single integer for square images or a tuple `(width, height)` for non-square, e.g., `(640, 480)`. |
| `half` | `False` | Enables FP16 (half-precision) inference, reducing memory usage and possibly increasing speed on compatible hardware. Use `half=True` to enable. | | `half` | `False` | Enables FP16 (half-precision) inference, reducing memory usage and possibly increasing speed on compatible hardware. Use `half=True` to enable. |
| `int8` | `False` | Activates INT8 quantization for further optimized performance on supported devices, especially useful for edge devices. Set `int8=True` to use. | | `int8` | `False` | Activates INT8 quantization for further optimized performance on supported devices, especially useful for edge devices. Set `int8=True` to use. |
| `device` | `None` | Defines the computation device(s) for benchmarking, such as `"cpu"`, `"cuda:0"`, or a list of devices like `"cuda:0,1"` for multi-GPU setups. | | `device` | `None` | Defines the computation device(s) for benchmarking, such as `"cpu"` or `"cuda:0"`. |
| `verbose` | `False` | Controls the level of detail in logging output. A boolean value; set `verbose=True` for detailed logs or a float for thresholding errors. | | `verbose` | `False` | Controls the level of detail in logging output. A boolean value; set `verbose=True` for detailed logs or a float for thresholding errors. |
## Export Formats ## Export Formats

@ -1,4 +1,4 @@
// Apply theme based on user preference // Light/Dark Mode -----------------------------------------------------------------------------------------------------
const applyTheme = (isDark) => { const applyTheme = (isDark) => {
document.body.setAttribute( document.body.setAttribute(
"data-md-color-scheme", "data-md-color-scheme",
@ -12,24 +12,7 @@ const applyTheme = (isDark) => {
// Check and apply auto theme // Check and apply auto theme
const checkAutoTheme = () => { const checkAutoTheme = () => {
const supportedLangCodes = [ const palette = JSON.parse(localStorage.getItem(".__palette") || "{}");
"en",
"zh",
"ko",
"ja",
"ru",
"de",
"fr",
"es",
"pt",
"it",
"tr",
"vi",
"ar",
];
const langCode = window.location.pathname.split("/")[1];
const localStorageKey = `${supportedLangCodes.includes(langCode) ? `/${langCode}` : ""}/.__palette`;
const palette = JSON.parse(localStorage.getItem(localStorageKey) || "{}");
if (palette.index === 0) { if (palette.index === 0) {
applyTheme(window.matchMedia("(prefers-color-scheme: dark)").matches); applyTheme(window.matchMedia("(prefers-color-scheme: dark)").matches);
@ -47,45 +30,51 @@ checkAutoTheme();
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
const autoThemeInput = document.getElementById("__palette_1"); const autoThemeInput = document.getElementById("__palette_1");
autoThemeInput?.addEventListener("click", () => { autoThemeInput?.addEventListener("click", () => {
if (autoThemeInput.checked) { if (autoThemeInput.checked) setTimeout(checkAutoTheme);
setTimeout(checkAutoTheme);
}
}); });
}); });
// Iframe navigation // Inkeep --------------------------------------------------------------------------------------------------------------
window.onhashchange = () => {
window.parent.postMessage(
{
type: "navigation",
hash:
window.location.pathname +
window.location.search +
window.location.hash,
},
"*",
);
};
// Add Inkeep button
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
const enableSearchBar = true;
const inkeepScript = document.createElement("script"); const inkeepScript = document.createElement("script");
inkeepScript.src = "https://unpkg.com/@inkeep/uikit-js@0.3.11/dist/embed.js"; inkeepScript.src = "https://unpkg.com/@inkeep/uikit-js@0.3.18/dist/embed.js";
inkeepScript.type = "module"; inkeepScript.type = "module";
inkeepScript.defer = true; inkeepScript.defer = true;
document.head.appendChild(inkeepScript); document.head.appendChild(inkeepScript);
// Configure and initialize the widget if (enableSearchBar) {
const addInkeepWidget = () => { const containerDiv = document.createElement("div");
containerDiv.style.transform = "scale(0.7)";
containerDiv.style.transformOrigin = "left center";
const inkeepDiv = document.createElement("div");
inkeepDiv.id = "inkeepSearchBar";
containerDiv.appendChild(inkeepDiv);
const headerElement = document.querySelector(".md-header__inner");
const searchContainer = headerElement.querySelector(".md-header__source");
if (headerElement && searchContainer) {
headerElement.insertBefore(containerDiv, searchContainer);
}
}
// configure and initialize the widget
const addInkeepWidget = (componentType, targetElementId) => {
const inkeepWidget = Inkeep().embed({ const inkeepWidget = Inkeep().embed({
componentType: "ChatButton", componentType,
...(componentType !== "ChatButton"
? { targetElement: targetElementId }
: {}),
colorModeSync: { colorModeSync: {
observedElement: document.documentElement, observedElement: document.documentElement,
isDarkModeCallback: (el) => { isDarkModeCallback: (el) => {
const currentTheme = el.getAttribute("data-color-mode"); const currentTheme = el.getAttribute("data-color-mode");
return currentTheme === "dark"; return currentTheme === "dark";
}, },
colorModeAttribute: "data-color-mode", colorModeAttribute: "data-color-mode-scheme",
}, },
properties: { properties: {
chatButtonType: "PILL", chatButtonType: "PILL",
@ -101,13 +90,12 @@ document.addEventListener("DOMContentLoaded", () => {
theme: { theme: {
stylesheetUrls: ["/stylesheets/style.css"], stylesheetUrls: ["/stylesheets/style.css"],
}, },
// ...optional settings
}, },
modalSettings: { modalSettings: {
// optional settings // optional settings
}, },
searchSettings: { searchSettings: {
// optional settings placeholder: "Search",
}, },
aiChatSettings: { aiChatSettings: {
chatSubjectName: "Ultralytics", chatSubjectName: "Ultralytics",
@ -146,101 +134,206 @@ document.addEventListener("DOMContentLoaded", () => {
}); });
}; };
inkeepScript.addEventListener("load", () => { inkeepScript.addEventListener("load", () => {
addInkeepWidget(); // initialize the widget const widgetContainer = document.getElementById("inkeepSearchBar");
addInkeepWidget("ChatButton");
widgetContainer && addInkeepWidget("SearchBar", "#inkeepSearchBar");
}); });
}); });
// This object contains the benchmark data for various object detection models. // YOLO models chart ---------------------------------------------------------------------------------------------------
const data = { 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}}, YOLO11: {
'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}}, n: { speed: 1.55, mAP: 39.5 },
'YOLOv7': {l: {speed: 6.84, mAP: 51.4}, x: {speed: 11.57, mAP: 53.1}}, s: { speed: 2.63, mAP: 47.0 },
'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}}, m: { speed: 5.27, mAP: 51.4 },
'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}}, l: { speed: 6.84, mAP: 53.2 },
'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}}, x: { speed: 12.49, mAP: 54.7 },
'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}} 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 },
},
YOLOv9: {
t: { speed: 2.3, 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 },
},
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 },
},
YOLOv7: { l: { speed: 6.84, mAP: 51.4 }, x: { speed: 11.57, mAP: 53.1 } },
"YOLOv6-3.0": {
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 },
},
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 },
},
"PP-YOLOE+": {
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 },
},
"DAMO-YOLO": {
t: { speed: 2.32, mAP: 42.0 },
s: { speed: 3.45, mAP: 46.0 },
m: { speed: 5.09, mAP: 49.2 },
l: { speed: 7.18, mAP: 50.8 },
},
YOLOX: {
s: { speed: 2.56, mAP: 40.5 },
m: { speed: 5.43, mAP: 46.9 },
l: { speed: 9.04, mAP: 49.7 },
x: { speed: 16.1, mAP: 51.1 },
},
RTDETRv2: {
s: { speed: 5.03, mAP: 48.1 },
m: { speed: 7.51, mAP: 51.9 },
l: { speed: 9.76, mAP: 53.4 },
x: { speed: 15.03, mAP: 54.3 },
},
}; };
let chart = null; // chart variable will hold the reference to the current chart instance. let chart = null; // chart variable will hold the reference to the current chart instance.
// Function to lighten a hex color by a specified amount.
function lightenHexColor(color, amount = 0.5) {
const r = parseInt(color.slice(1, 3), 16);
const g = parseInt(color.slice(3, 5), 16);
const b = parseInt(color.slice(5, 7), 16);
const newR = Math.min(255, Math.round(r + (255 - r) * amount));
const newG = Math.min(255, Math.round(g + (255 - g) * amount));
const newB = Math.min(255, Math.round(b + (255 - b) * amount));
return `#${newR.toString(16).padStart(2, "0")}${newG.toString(16).padStart(2, "0")}${newB.toString(16).padStart(2, "0")}`;
}
// This function is responsible for updating the benchmarks chart. // Function to update the benchmarks chart.
function updateChart() { function updateChart() {
// If a chart instance already exists, destroy it. if (chart) {
if (chart) { chart.destroy();
chart.destroy(); } // If a chart instance already exists, destroy it.
}
// Get the selected algorithms from the checkboxes. // Define a specific color map for models.
const selectedAlgorithms = [...document.querySelectorAll('input[name="algorithm"]:checked')].map(e => e.value); const colorMap = {
YOLO11: "#0b23a9",
// Create the datasets for the selected algorithms. YOLOv10: "#ff7f0e",
const datasets = selectedAlgorithms.map((algorithm, index) => ({ YOLOv9: "#2ca02c",
label: algorithm, // Label for the data points in the legend. YOLOv8: "#d62728",
data: Object.entries(data[algorithm]).map(([version, point]) => ({ YOLOv7: "#9467bd",
x: point.speed, // Speed data points on the x-axis. "YOLOv6-3.0": "#8c564b",
y: point.mAP, // mAP data points on the y-axis. YOLOv5: "#e377c2",
version: version.toUpperCase() // Store the version as additional data. "PP-YOLOE+": "#7f7f7f",
})), "DAMO-YOLO": "#bcbd22",
fill: false, // Don't fill the chart. YOLOX: "#17becf",
borderColor: `hsl(${index * 90}, 70%, 50%)`, // Assign a unique color to each dataset. RTDETRv2: "#eccd22",
tension: 0.3, // Smooth the line. };
pointRadius: 5, // Increase the dot size.
pointHoverRadius: 10, // Increase the dot size on hover. // Get the selected algorithms from the checkboxes.
borderWidth: 2 // Set the line thickness. const selectedAlgorithms = [
})); ...document.querySelectorAll('input[name="algorithm"]:checked'),
].map((e) => e.value);
// If there are no selected algorithms, return without creating a new chart.
if (datasets.length === 0) {
return;
}
// Create a new chart instance. // Create the datasets for the selected algorithms.
chart = new Chart(document.getElementById('chart').getContext('2d'), { const datasets = selectedAlgorithms.map((algorithm, i) => {
type: 'line', // Set the chart type to line. const baseColor =
data: { datasets }, colorMap[algorithm] || `hsl(${Math.random() * 360}, 70%, 50%)`;
options: { const lineColor = i === 0 ? baseColor : lightenHexColor(baseColor, 0.6); // Lighten non-primary lines.
plugins: {
legend: { display: true, position: 'top', labels: {color: '#808080'} }, // Configure the legend. return {
tooltip: { label: algorithm, // Label for the data points in the legend.
callbacks: { data: Object.entries(data[algorithm]).map(([version, point]) => ({
label: (tooltipItem) => { x: point.speed, // Speed data points on the x-axis.
const { dataset, dataIndex } = tooltipItem; y: point.mAP, // mAP data points on the y-axis.
const point = dataset.data[dataIndex]; version: version.toUpperCase(), // Store the version as additional data.
return `${dataset.label}${point.version.toLowerCase()}: Speed = ${point.x}, mAP = ${point.y}`; // Custom tooltip label. })),
} fill: false, // Don't fill the chart.
}, borderColor: lineColor, // Use the lightened color for the line.
mode: 'nearest', tension: 0.3, // Smooth the line.
intersect: false pointRadius: i === 0 ? 7 : 4, // Highlight primary dataset points.
} // Configure the tooltip. pointHoverRadius: i === 0 ? 9 : 6, // Highlight hover for primary dataset.
pointBackgroundColor: lineColor, // Fill points with the line color.
pointBorderColor: "#ffffff", // Add a border around points for contrast.
borderWidth: i === 0 ? 3 : 1.5, // Slightly increase line size for the primary dataset.
};
});
if (datasets.length === 0) {
return;
} // If there are no selected algorithms, return without creating a new chart.
// 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: "#808080" },
}, // 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.
}, },
interaction: { mode: 'nearest', axis: 'x', intersect: false }, // Configure the interaction mode. },
scales: { mode: "nearest",
x: { intersect: false,
type: 'linear', position: 'bottom', }, // Configure the tooltip.
title: { display: true, text: 'Latency T4 TensorRT10 FP16 (ms/img)', color: '#808080'}, // X-axis title. },
grid: { color: '#e0e0e0' }, // Grid line color. interaction: { mode: "nearest", axis: "x", intersect: false }, // Configure the interaction mode.
ticks: { color: '#808080' } // Tick label color. scales: {
}, x: {
y: { type: "linear",
title: { display: true, text: 'mAP', color: '#808080'}, // Y-axis title. position: "bottom",
grid: { color: '#e0e0e0' }, // Grid line color. title: {
ticks: { color: '#808080' } // Tick label color. display: true,
} text: "Latency T4 TensorRT10 FP16 (ms/img)",
} color: "#808080",
} }, // X-axis title.
}); grid: { color: "#e0e0e0" }, // Grid line color.
ticks: { color: "#808080" }, // Tick label color.
},
y: {
title: { display: true, text: "mAP", color: "#808080" }, // Y-axis title.
grid: { color: "#e0e0e0" }, // Grid line color.
ticks: { color: "#808080" }, // Tick label color.
},
},
},
});
} }
// Poll for Chart.js to load, then initialize checkboxes and chart // Poll for Chart.js to load, then initialize checkboxes and chart
function initializeApp() { function initializeApp() {
if (typeof Chart !== 'undefined') { if (typeof Chart !== "undefined") {
document.querySelectorAll('input[name="algorithm"]').forEach(checkbox => document
checkbox.addEventListener('change', updateChart) .querySelectorAll('input[name="algorithm"]')
); .forEach((checkbox) => checkbox.addEventListener("change", updateChart));
updateChart(); updateChart();
} else { } else {
setTimeout(initializeApp, 100); // Retry every 100ms setTimeout(initializeApp, 100); // Retry every 100ms
} }
} }
document.addEventListener("DOMContentLoaded", initializeApp); // Initial chart rendering on page load document.addEventListener("DOMContentLoaded", initializeApp); // Initial chart rendering on page load

@ -57,14 +57,17 @@ function setupGiscusLoader() {
const giscusContainer = document.getElementById("giscus-container"); const giscusContainer = document.getElementById("giscus-container");
if (giscusContainer) { if (giscusContainer) {
const observer = new IntersectionObserver((entries) => { const observer = new IntersectionObserver(
entries.forEach((entry) => { (entries) => {
if (entry.isIntersecting) { entries.forEach((entry) => {
loadGiscus(); if (entry.isIntersecting) {
observer.unobserve(entry.target); loadGiscus();
} observer.unobserve(entry.target);
}); }
}, { threshold: 0.1 }); // Trigger when 10% of the element is visible });
},
{ threshold: 0.1 },
); // Trigger when 10% of the element is visible
observer.observe(giscusContainer); observer.observe(giscusContainer);
} }

@ -265,8 +265,15 @@ div.highlight {
} }
/* MkDocs Ultralytics Plugin ---------------------------------------------------------------------------------------- */ /* MkDocs Ultralytics Plugin ---------------------------------------------------------------------------------------- */
/* Inkeep button font color ----------------------------------------------------------------------------------------- */ /* Inkeep ----------------------------------------------------------------------------------------------------------- */
.ikp-floating-button { .ikp-floating-button {
color: #111f68; color: #111f68;
} }
/* Inkeep button ---------------------------------------------------------------------------------------------------- */ #inkeepSearchBar {
transition: all 0.2s ease-in-out;
}
#inkeepSearchBar:hover {
transform: scale(1.1);
filter: brightness(1.2);
}
/* Inkeep ----------------------------------------------------------------------------------------------------------- */

@ -291,6 +291,7 @@ nav:
- COCO8-pose: datasets/pose/coco8-pose.md - COCO8-pose: datasets/pose/coco8-pose.md
- Tiger-pose: datasets/pose/tiger-pose.md - Tiger-pose: datasets/pose/tiger-pose.md
- Hand-keypoints: datasets/pose/hand-keypoints.md - Hand-keypoints: datasets/pose/hand-keypoints.md
- Dog-pose: datasets/pose/dog-pose.md
- Classification: - Classification:
- datasets/classify/index.md - datasets/classify/index.md
- Caltech 101: datasets/classify/caltech101.md - Caltech 101: datasets/classify/caltech101.md
@ -627,8 +628,8 @@ nav:
# Plugins including 301 redirects navigation --------------------------------------------------------------------------- # Plugins including 301 redirects navigation ---------------------------------------------------------------------------
plugins: plugins:
- macros - macros
- search: # - search:
lang: en # lang: en
- mkdocstrings: - mkdocstrings:
enabled: true enabled: true
default_handler: python default_handler: python

@ -1,6 +1,6 @@
# Ultralytics YOLO 🚀, AGPL-3.0 license # Ultralytics YOLO 🚀, AGPL-3.0 license
__version__ = "8.3.31" __version__ = "8.3.34"
import os import os

@ -0,0 +1,23 @@
# Ultralytics YOLO 🚀, AGPL-3.0 license
# Dogs dataset http://vision.stanford.edu/aditya86/ImageNetDogs/ by Stanford
# Documentation: https://docs.ultralytics.com/datasets/pose/dog-pose/
# Example usage: yolo train data=dog-pose.yaml
# parent
# ├── ultralytics
# └── datasets
# └── dog-pose ← downloads here (337 MB)
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../datasets/dog-pose # dataset root dir
train: train # train images (relative to 'path') 6773 images
val: val # val images (relative to 'path') 1703 images
# Keypoints
kpt_shape: [24, 3] # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
# Classes
names:
0: dog
# Download script/URL (optional)
download: https://github.com/ultralytics/assets/releases/download/v0.0.0/dog-pose.zip

@ -2280,7 +2280,7 @@ def v8_transforms(dataset, imgsz, hyp, stretch=False):
Args: Args:
dataset (Dataset): The dataset object containing image data and annotations. dataset (Dataset): The dataset object containing image data and annotations.
imgsz (int): The target image size for resizing. imgsz (int): The target image size for resizing.
hyp (Dict): A dictionary of hyperparameters controlling various aspects of the transformations. hyp (Namespace): A dictionary of hyperparameters controlling various aspects of the transformations.
stretch (bool): If True, applies stretching to the image. If False, uses LetterBox resizing. stretch (bool): If True, applies stretching to the image. If False, uses LetterBox resizing.
Returns: Returns:
@ -2288,8 +2288,9 @@ def v8_transforms(dataset, imgsz, hyp, stretch=False):
Examples: Examples:
>>> from ultralytics.data.dataset import YOLODataset >>> from ultralytics.data.dataset import YOLODataset
>>> from ultralytics.utils import IterableSimpleNamespace
>>> dataset = YOLODataset(img_path="path/to/images", imgsz=640) >>> dataset = YOLODataset(img_path="path/to/images", imgsz=640)
>>> hyp = {"mosaic": 1.0, "copy_paste": 0.5, "degrees": 10.0, "translate": 0.2, "scale": 0.9} >>> hyp = IterableSimpleNamespace(mosaic=1.0, copy_paste=0.5, degrees=10.0, translate=0.2, scale=0.9)
>>> transforms = v8_transforms(dataset, imgsz=640, hyp=hyp) >>> transforms = v8_transforms(dataset, imgsz=640, hyp=hyp)
>>> augmented_data = transforms(dataset[0]) >>> augmented_data = transforms(dataset[0])
""" """

@ -79,7 +79,6 @@ from ultralytics.utils import (
ARM64, ARM64,
DEFAULT_CFG, DEFAULT_CFG,
IS_JETSON, IS_JETSON,
IS_RASPBERRYPI,
LINUX, LINUX,
LOGGER, LOGGER,
MACOS, MACOS,
@ -265,8 +264,6 @@ class Exporter:
"WARNING ⚠ INT8 export requires a missing 'data' arg for calibration. " "WARNING ⚠ INT8 export requires a missing 'data' arg for calibration. "
f"Using default 'data={self.args.data}'." 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 # Input
im = torch.zeros(self.args.batch, 3, *self.imgsz).to(self.device) im = torch.zeros(self.args.batch, 3, *self.imgsz).to(self.device)

@ -64,6 +64,9 @@ class FastSAMPredictor(SegmentationPredictor):
if not isinstance(results, list): if not isinstance(results, list):
results = [results] results = [results]
for result in results: for result in results:
if len(result) == 0:
prompt_results.append(result)
continue
masks = result.masks.data masks = result.masks.data
if masks.shape[1:] != result.orig_shape: if masks.shape[1:] != result.orig_shape:
masks = scale_masks(masks[None], result.orig_shape)[0] masks = scale_masks(masks[None], result.orig_shape)[0]

@ -68,8 +68,11 @@ class RTDETRTrainer(DetectionTrainer):
hyp=self.args, hyp=self.args,
rect=False, rect=False,
cache=self.args.cache or None, cache=self.args.cache or None,
single_cls=self.args.single_cls or False,
prefix=colorstr(f"{mode}: "), prefix=colorstr(f"{mode}: "),
classes=self.args.classes,
data=self.data, data=self.data,
fraction=self.args.fraction if mode == "train" else 1.0,
) )
def get_validator(self): def get_validator(self):

@ -104,12 +104,12 @@ class Heatmap(ObjectCounter):
self.annotator.draw_region(reg_pts=self.region, color=(104, 0, 123), thickness=self.line_width * 2) self.annotator.draw_region(reg_pts=self.region, color=(104, 0, 123), thickness=self.line_width * 2)
self.store_tracking_history(track_id, box) # Store track history self.store_tracking_history(track_id, box) # Store track history
self.store_classwise_counts(cls) # store classwise counts in dict self.store_classwise_counts(cls) # store classwise counts in dict
current_centroid = ((box[0] + box[2]) / 2, (box[1] + box[3]) / 2)
# Store tracking previous position and perform object counting # Store tracking previous position and perform object counting
prev_position = None prev_position = None
if len(self.track_history[track_id]) > 1: if len(self.track_history[track_id]) > 1:
prev_position = self.track_history[track_id][-2] prev_position = self.track_history[track_id][-2]
self.count_objects(self.track_line, box, track_id, prev_position, cls) # Perform object counting self.count_objects(current_centroid, track_id, prev_position, cls) # Perform object counting
if self.region is not None: if self.region is not None:
self.display_counts(im0) # Display the counts on the frame self.display_counts(im0) # Display the counts on the frame

@ -46,13 +46,12 @@ class ObjectCounter(BaseSolution):
self.show_in = self.CFG["show_in"] self.show_in = self.CFG["show_in"]
self.show_out = self.CFG["show_out"] self.show_out = self.CFG["show_out"]
def count_objects(self, track_line, box, track_id, prev_position, cls): def count_objects(self, current_centroid, track_id, prev_position, cls):
""" """
Counts objects within a polygonal or linear region based on their tracks. Counts objects within a polygonal or linear region based on their tracks.
Args: Args:
track_line (Dict): Last 30 frame track record for the object. current_centroid (Tuple[float, float]): Current centroid values in the current frame.
box (List[float]): Bounding box coordinates [x1, y1, x2, y2] for the specific track in the current frame.
track_id (int): Unique identifier for the tracked object. track_id (int): Unique identifier for the tracked object.
prev_position (Tuple[float, float]): Last frame position coordinates (x, y) of the track. prev_position (Tuple[float, float]): Last frame position coordinates (x, y) of the track.
cls (int): Class index for classwise count updates. cls (int): Class index for classwise count updates.
@ -64,34 +63,55 @@ class ObjectCounter(BaseSolution):
>>> track_id = 1 >>> track_id = 1
>>> prev_position = (120, 220) >>> prev_position = (120, 220)
>>> cls = 0 >>> cls = 0
>>> counter.count_objects(track_line, box, track_id, prev_position, cls) >>> counter.count_objects(current_centroid, track_id, prev_position, cls)
""" """
if prev_position is None or track_id in self.counted_ids: if prev_position is None or track_id in self.counted_ids:
return return
centroid = self.r_s.centroid if len(self.region) == 2: # Linear region (defined as a line segment)
dx = (box[0] - prev_position[0]) * (centroid.x - prev_position[0]) line = self.LineString(self.region) # Check if the line intersects the trajectory of the object
dy = (box[1] - prev_position[1]) * (centroid.y - prev_position[1]) if line.intersects(self.LineString([prev_position, current_centroid])):
# Determine orientation of the region (vertical or horizontal)
if len(self.region) >= 3 and self.r_s.contains(self.Point(track_line[-1])): if abs(self.region[0][0] - self.region[1][0]) < abs(self.region[0][1] - self.region[1][1]):
self.counted_ids.append(track_id) # Vertical region: Compare x-coordinates to determine direction
# For polygon region if current_centroid[0] > prev_position[0]: # Moving right
if dx > 0: self.in_count += 1
self.in_count += 1 self.classwise_counts[self.names[cls]]["IN"] += 1
self.classwise_counts[self.names[cls]]["IN"] += 1 else: # Moving left
else: self.out_count += 1
self.out_count += 1 self.classwise_counts[self.names[cls]]["OUT"] += 1
self.classwise_counts[self.names[cls]]["OUT"] += 1 else:
# Horizontal region: Compare y-coordinates to determine direction
elif len(self.region) < 3 and self.LineString([prev_position, box[:2]]).intersects(self.r_s): if current_centroid[1] > prev_position[1]: # Moving downward
self.counted_ids.append(track_id) self.in_count += 1
# For linear region self.classwise_counts[self.names[cls]]["IN"] += 1
if dx > 0 and dy > 0: else: # Moving upward
self.in_count += 1 self.out_count += 1
self.classwise_counts[self.names[cls]]["IN"] += 1 self.classwise_counts[self.names[cls]]["OUT"] += 1
else: self.counted_ids.append(track_id)
self.out_count += 1
self.classwise_counts[self.names[cls]]["OUT"] += 1 elif len(self.region) > 2: # Polygonal region
polygon = self.Polygon(self.region)
if polygon.contains(self.Point(current_centroid)):
# Determine motion direction for vertical or horizontal polygons
region_width = max([p[0] for p in self.region]) - min([p[0] for p in self.region])
region_height = max([p[1] for p in self.region]) - min([p[1] for p in self.region])
if region_width < region_height: # Vertical-oriented polygon
if current_centroid[0] > prev_position[0]: # Moving right
self.in_count += 1
self.classwise_counts[self.names[cls]]["IN"] += 1
else: # Moving left
self.out_count += 1
self.classwise_counts[self.names[cls]]["OUT"] += 1
else: # Horizontal-oriented polygon
if current_centroid[1] > prev_position[1]: # Moving downward
self.in_count += 1
self.classwise_counts[self.names[cls]]["IN"] += 1
else: # Moving upward
self.out_count += 1
self.classwise_counts[self.names[cls]]["OUT"] += 1
self.counted_ids.append(track_id)
def store_classwise_counts(self, cls): def store_classwise_counts(self, cls):
""" """
@ -174,12 +194,12 @@ class ObjectCounter(BaseSolution):
self.annotator.draw_centroid_and_tracks( self.annotator.draw_centroid_and_tracks(
self.track_line, color=colors(int(cls), True), track_thickness=self.line_width self.track_line, color=colors(int(cls), True), track_thickness=self.line_width
) )
current_centroid = ((box[0] + box[2]) / 2, (box[1] + box[3]) / 2)
# store previous position of track for object counting # store previous position of track for object counting
prev_position = None prev_position = None
if len(self.track_history[track_id]) > 1: if len(self.track_history[track_id]) > 1:
prev_position = self.track_history[track_id][-2] prev_position = self.track_history[track_id][-2]
self.count_objects(self.track_line, box, track_id, prev_position, cls) # Perform object counting self.count_objects(current_centroid, track_id, prev_position, cls) # Perform object counting
self.display_counts(im0) # Display the counts on the frame self.display_counts(im0) # Display the counts on the frame
self.display_output(im0) # display output with base class function self.display_output(im0) # display output with base class function

@ -114,8 +114,6 @@ def benchmark(
assert LINUX or MACOS, "Windows Paddle exports not supported yet" assert LINUX or MACOS, "Windows Paddle exports not supported yet"
if i == 12: # MNN if i == 12: # MNN
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 MNN exports not supported yet" 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 if i == 13: # NCNN
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 NCNN exports not supported yet" assert not isinstance(model, YOLOWorld), "YOLOWorldv2 NCNN exports not supported yet"
if i == 14: # IMX if i == 14: # IMX

@ -109,7 +109,12 @@ def _log_plots(plots, step):
def on_pretrain_routine_start(trainer): def on_pretrain_routine_start(trainer):
"""Initiate and start project if module is present.""" """Initiate and start project if module is present."""
wb.run or wb.init(project=trainer.args.project or "Ultralytics", name=trainer.args.name, config=vars(trainer.args)) if not wb.run:
wb.init(
project=str(trainer.args.project).replace("/", "-") if trainer.args.project else "Ultralytics",
name=str(trainer.args.name).replace("/", "-"),
config=vars(trainer.args),
)
def on_fit_epoch_end(trainer): def on_fit_epoch_end(trainer):
@ -138,7 +143,7 @@ def on_train_end(trainer):
art.add_file(trainer.best) art.add_file(trainer.best)
wb.run.log_artifact(art, aliases=["best"]) wb.run.log_artifact(art, aliases=["best"])
# Check if we actually have plots to save # Check if we actually have plots to save
if trainer.args.plots: if trainer.args.plots and hasattr(trainer.validator.metrics, "curves_results"):
for curve_name, curve_values in zip(trainer.validator.metrics.curves, trainer.validator.metrics.curves_results): for curve_name, curve_values in zip(trainer.validator.metrics.curves, trainer.validator.metrics.curves_results):
x, y, x_title, y_title = curve_values x, y, x_title, y_title = curve_values
_plot_curve( _plot_curve(

Loading…
Cancel
Save