These are the docs for the current stable release line, v1.3.x. Earlier versions stay available from the version menu.

Two companion guides go deeper on specialized topics. The LibreVLM guide covers the vision-language tier (Qwen3-VL, Florence-2), which generates text that LibreYOLO parses into boxes. That is a different thing from open-vocabulary detection, new in v1.3.1, which uses purpose-built detectors conditioned on text and is documented on this page. The experimental tasks guide covers additional experimental workflows, including LoRA / DoRA fine-tuning.

Introduction

v1.3.1 validation scope

The heavily tested path is detection, training and inference for YOLO9 and RF-DETR, including RF-DETR segmentation.

Other model families, tasks, and multi-GPU workflows are available but experimental.

LibreYOLO is an MIT-licensed computer-vision toolkit. v1.3.1 ships a broad catalogue across detection, segmentation, classification, depth and more, but the validated support surface is intentionally narrow:

  • YOLO9 detection - the CNN path.
  • RF-DETR detection - the transformer path.
  • RF-DETR segmentation - the heavily tested segmentation path.

We recommend those paths as the default choice for new projects because they receive the heaviest testing around detection, training and inference. Other supported families and tasks work through the same unified LibreYOLO() factory, but they are experimental in v1.3.1. Use them if you have a specific reason.

python
1from libreyolo import LibreYOLO, SAMPLE_IMAGE
2
3# Default: YOLO9 detection
4model = LibreYOLO("LibreYOLO9c.pt")
5result = model(SAMPLE_IMAGE, conf=0.25, save=True)
6
7print(f"Detected {len(result)} objects")
8print(result.boxes.xyxy)
9print(result.saved_path)

Key features

  • Heavy testing and recommended defaults for YOLO9 detection, RF-DETR detection, and RF-DETR segmentation
  • Unified LibreYOLO() factory for checkpoints, exported artifacts, and runtime loading
  • Detection, segmentation, pose, and gaze tasks through one consistent API
  • Image, directory, and video inference (with optional tiled inference for large frames)
  • Built-in multi-object tracking via ByteTrack
  • ONNX, TorchScript, TensorRT, OpenVINO, NCNN, and CoreML export with embedded metadata, plus matching runtime backends
  • COCO-compatible validation with mAP metrics, plus segmentation and pose validators
  • A libreyolo command-line tool for predict / train / val / export
  • Accepts any image format: file paths, URLs, PIL, NumPy, PyTorch tensors, raw bytes

Breaking changes in v1.3.0

  • DAMO-YOLO removed with no alias: LibreDAMOYOLO raises AttributeError, and DAMO-YOLO checkpoints are rejected on load.
  • YOLO9 is detect-only. The -seg, -pose, -cls, -obb, and -sem YOLO9 variants were removed.
  • RF-DETR lost classify, semantic, and depth. Its tasks are now detect, segment, pose, and obb. Classification and semantic moved to the new LibreDINOv2 family; depth moved to the new LibreDepthAnythingV2 family.
  • TFLite export needs Python 3.12+ (onnx2tf wheel constraint). The onnx2tf floor was raised to >=2.4.3 and the old onnx2tf runtime patches were removed.

Compatibility

Use this matrix as the quick v1.3.1 support map. marks a validated path, exp is experimental, prev is a research preview, and empty cells are not currently supported. Only YOLO9 and RF-DETR detection (plus RF-DETR segmentation) are heavily tested; everything else, including the new classification, semantic, depth and point families, is experimental.

Model familyv1.3.1 statusInferenceTrainingDetectSegmentSemanticClassifyPoseOBBDepthPointGazeRestoreONNXTorchScriptTensorRTOpenVINONCNNCoreMLTFLite
YOLO9Validated detect, single GPUNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexp
RF-DETRValidated detect + segment; pose / OBB previewNot currently supportedNot currently supportedprevprevNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexp
YOLOXExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpexpexpNot currently supported
YOLO9-E2EExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpNot currently supportedNot currently supportedNot currently supported
YOLO-NASExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpexpNot currently supportedNot currently supported
D-FINEExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpexpNot currently supportedNot currently supported
DEIMExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpexpNot currently supportedNot currently supported
DEIMv2ExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpexpNot currently supportedNot currently supported
RT-DETRExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpexpexpexpNot currently supported
RT-DETRv2ExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
RT-DETRv4ExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
PicoDetExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supported
RTMDetExperimentalexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
ECExperimentalexpexpexpexpNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
DINOv2New, experimental (needs transformers)expexpNot currently supportedNot currently supportedexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
MobileNetV4New, experimental classifier (Apache)expexpNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
ConvNeXtNew, experimental classifier (Apache)expexpNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
EfficientNetV2New, experimental classifier (Apache)expexpNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
Depth Anything V2New, experimental; no exportexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
FOMONew, experimental; no auto-downloadexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
L2CSExperimental, inference-onlyexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
YOLO9-P2New; small objects. VisDrone weights only (non-commercial)expexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
YOLO2 / YOLO3 / YOLO4 / YOLO7New; legacy baselines, inference-onlyexpNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedexp
PIDNetNew; semantic. Inference and val only, no exportexpNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
EoMTNew; semantic. Size l only, imgsz locked to 512expNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
NAFNetNew; image restoration (denoise / deblur)expexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
CLIPZero-shot classificationexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported
ResNetExperimental classifierexpexpNot currently supportedNot currently supportedNot currently supportedexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supportedexpexpNot currently supportedNot currently supportedNot currently supportedNot currently supportedNot currently supported

Depth Anything V2 has no export path. TFLite export is experimental and limited to YOLO9 detection and RF-DETR detect / segment / pose. The classification families (MobileNetV4, ConvNeXt, EfficientNetV2) support ONNX export. CoreML exports produce .mlpackage bundles and require libreyolo[coreml]: macOS only, no INT8, and no embedded NMS for RF-DETR, D-FINE, DEIM, DEIMv2, or EC.

Installation

Requirements

  • Python 3.10+
  • PyTorch 1.13+ and torchvision 0.11+

From PyPI

bash
1pip install libreyolo

v1.3.1 is the current release on PyPI, and it is what these docs describe. Everything on this page works from the published package: you do not need a source install.

From source

bash
1git clone https://github.com/LibreYOLO/libreyolo.git
2cd libreyolo
3pip install -e .

Optional dependencies

bash
1# ONNX export and inference
2pip install libreyolo[onnx]
3# or: pip install onnx onnxsim onnxruntime
4
5# RT-DETR compatibility extra (currently no extra packages)
6pip install libreyolo[rtdetr]
7
8# RF-DETR support
9pip install libreyolo[rfdetr]
10# or: pip install transformers
11
12# TensorRT export and inference (NVIDIA GPU)
13pip install libreyolo[tensorrt]
14# Installs TensorRT CUDA 12 Python packages on Linux/Windows.
15# Host driver/CUDA compatibility still matters.
16
17# OpenVINO export and inference (Intel CPU/GPU/VPU)
18pip install libreyolo[openvino]
19# INT8 export also needs: pip install nncf
20
21# NCNN export and inference
22pip install libreyolo[ncnn]
23# or: pip install pnnx ncnn
24
25# ByteTrack API compatibility extra
26pip install libreyolo[tracking]
27# Tracking dependencies are part of the base install in v1.3.1.
28
29# CoreML export and inference (macOS only for runtime)
30pip install libreyolo[coreml]
31# or: pip install coremltools
32
33# L2CS gaze optional auto-download helper
34pip install libreyolo[gaze]
35
36# Promptable segmentation (LibreSAM: SAM-1, SAM-2, MobileSAM)
37pip install libreyolo[sam]
38
39# Open-vocabulary detection (Grounding DINO, OWLv2)
40pip install libreyolo[openvocab]
41
42# LibreLabel AI assist (SAM click-to-mask)
43pip install libreyolo[label]
44
45# Zero-shot classification (CLIP)
46pip install libreyolo[clip]
47
48# Install every optional LibreYOLO extra
49pip install libreyolo[all]

If using uv, the most reliable path is an isolated venv per extra:

bash
1# ONNX environment
2uv venv .venv-onnx
3uv pip install --python .venv-onnx/bin/python -e '.[onnx]'
4
5# RT-DETR environment
6uv venv .venv-rtdetr
7uv pip install --python .venv-rtdetr/bin/python -e '.[rtdetr]'
8
9# Repeat with .[rfdetr], .[openvino], .[ncnn], .[coreml], .[gaze], .[tracking], or .[tensorrt] as needed

This avoids mutating the project environment and keeps optional dependencies isolated. Vendor-specific extras such as TensorRT, OpenVINO, NCNN, and CoreML may still require platform-specific native packages.

Quickstart

For the most tested path, pick single-GPU YOLO9 detection, RF-DETR detection, or RF-DETR segmentation. They load through the same factory, accept the same inputs, and return the same Results object, so you can swap between them without changing surrounding code.

YOLO9 - CNN flagship

python
1from libreyolo import LibreYOLO, SAMPLE_IMAGE
2
3# Use the official checkpoint name and let the factory resolve the details
4model = LibreYOLO("LibreYOLO9c.pt")
5
6# Run on a single image (SAMPLE_IMAGE ships with the package)
7result = model(SAMPLE_IMAGE)
8
9print(f"Found {len(result)} objects")
10print(result.boxes.xyxy) # bounding boxes (N, 4)
11print(result.boxes.conf) # confidence scores (N,)
12print(result.boxes.cls) # class IDs (N,)

RF-DETR - transformer flagship

python
1from libreyolo import LibreYOLO, SAMPLE_IMAGE
2
3# Same factory, same call shape - just point at an RF-DETR checkpoint
4model = LibreYOLO("LibreRFDETRs.pt")
5result = model(SAMPLE_IMAGE)
6
7print(f"Found {len(result)} objects")
8print(result.boxes.xyxy)

Save annotated output

python
1result = model(SAMPLE_IMAGE, save=True)
2print(result.saved_path) # e.g. runs/detect/predict/parkour.jpg

Process a directory

python
1results = model("images/", save=True, batch=4)
2for r in results:
3 print(f"{r.path}: {len(r)} detections")

Available Models

Recommended validated path: YOLO9 detection or RF-DETR detection / segmentation

Detection, training and inference for these models receive the heaviest testing. Treat other families, tasks, and multi-GPU workflows as experimental in v1.3.1.

LibreYOLO v1.3.1 ships two validated flagship families plus a broader catalogue of supported and freshly added models. Every model loads through the same LibreYOLO() factory, but only the validated paths below should be treated as heavily tested.

YOLO9 - CNN flagship

Recommended
Default: LibreYOLO9c.ptHeavily tested: detection, training and inferenceDetect-only in v1.3.1Experimental: multi-GPU
SizeCodeInput sizeUse caseDetection checkpoint
Tiny"t"640Fast inferenceLibreYOLO9t.pt
Small"s"640BalancedLibreYOLO9s.pt
Medium"m"640Higher accuracyLibreYOLO9m.pt
Compact"c"640Best accuracyLibreYOLO9c.pt

YOLO9 is detection-only in v1.3.1. The non-detect flagship variants (including the old -seg checkpoints) were removed; for segmentation use RF-DETR or EdgeCrafter below.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreYOLO9c.pt") # detection

RF-DETR - transformer flagship

Recommended
Recommended transformer pathHeavily tested: detection, segmentation, training and inferenceResearch preview: pose, OBBExperimental: multi-GPU
SizeCodeInput sizeUse caseDetection checkpoint
Nano"n"384EdgeLibreRFDETRn.pt
Small"s"512BalancedLibreRFDETRs.pt
Medium"m"576Higher accuracyLibreRFDETRm.pt
Large"l"704Maximum accuracyLibreRFDETRl.pt

LibreYOLO ships the Apache-clean RF-DETR detect sizes N/S/M/L on the Hugging Face org. The XL/2XL tiers are intentionally not shipped.

Heavily tested Segmentation: LibreRFDETRn-seg.pt, LibreRFDETRs-seg.pt, LibreRFDETRm-seg.pt, LibreRFDETRl-seg.pt. Larger -seg sizes (x, xx) pull upstream RF-DETR seg-XL / seg-2XL weights under a non-commercial license and are not hosted on the LibreYOLO org. See the Segmentation section.

Research preview Pose: LibreRFDETRx-pose.pt (ported from RF-DETR v1.8.0 GroupPose; only size x at 576 ships). OBB: LibreRFDETRn-obb.pt, LibreRFDETRs-obb.pt, LibreRFDETRm-obb.pt, LibreRFDETRl-obb.pt (oriented boxes, uses detection input sizes). Treat both as research previews, not validated paths.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreRFDETRs.pt") # detect (validated)
4# model = LibreYOLO("LibreRFDETRs-seg.pt") # segment (validated)
5# model = LibreYOLO("LibreRFDETRx-pose.pt") # pose (research preview)
6# model = LibreYOLO("LibreRFDETRn-obb.pt") # obb (research preview)

Additional detection families

Detection-capable families that share the same factory and API surface as the validated paths. These are experimental in v1.3.1. Each checkpoint name links to its model card on the LibreYOLO org; pass any name to LibreYOLO() and the factory fetches it on first use.

FamilyStatusTasksCheckpoints
YOLOXExperimentaldetectLibreYOLOXn.pt, LibreYOLOXt.pt, LibreYOLOXs.pt, LibreYOLOXm.pt, LibreYOLOXl.pt, LibreYOLOXx.pt
YOLO9-E2EExperimentaldetectLibreYOLO9E2Et.pt, LibreYOLO9E2Es.pt, LibreYOLO9E2Em.pt, LibreYOLO9E2Ec.pt
YOLO-NASExperimentaldetect, poseLibreYOLONASs.pt, LibreYOLONASm.pt, LibreYOLONASl.pt, LibreYOLONASn-pose.pt, LibreYOLONASs-pose.pt, LibreYOLONASm-pose.pt, LibreYOLONASl-pose.pt
D-FINEExperimentaldetectLibreDFINEn.pt, LibreDFINEs.pt, LibreDFINEm.pt, LibreDFINEl.pt, LibreDFINEx.pt
DEIMExperimentaldetectLibreDEIMn.pt, LibreDEIMs.pt, LibreDEIMm.pt, LibreDEIMl.pt, LibreDEIMx.pt
DEIMv2ExperimentaldetectLibreDEIMv2atto.pt, LibreDEIMv2femto.pt, LibreDEIMv2pico.pt, LibreDEIMv2n.pt, LibreDEIMv2s.pt, LibreDEIMv2m.pt, LibreDEIMv2l.pt, LibreDEIMv2x.pt
RT-DETRExperimentaldetectLibreRTDETRr18.pt, LibreRTDETRr34.pt, LibreRTDETRr50.pt, LibreRTDETRr50m.pt, LibreRTDETRr101.pt, LibreRTDETRl.pt, LibreRTDETRx.pt
RT-DETRv2ExperimentaldetectLibreRTDETRv2r18.pt, LibreRTDETRv2r34.pt, LibreRTDETRv2r50.pt, LibreRTDETRv2r50m.pt, LibreRTDETRv2r101.pt
RT-DETRv4ExperimentaldetectLibreRTDETRv4s.pt, LibreRTDETRv4m.pt, LibreRTDETRv4l.pt, LibreRTDETRv4x.pt
PicoDetExperimentaldetectLibrePICODETs.pt, LibrePICODETm.pt, LibrePICODETl.pt
RTMDetExperimentaldetectLibreRTMDett.pt, LibreRTMDets.pt, LibreRTMDetm.pt, LibreRTMDetl.pt, LibreRTMDetx.pt
EdgeCrafterExperimentaldetect, pose, segmentLibreECs.pt, LibreECm.pt, LibreECl.pt, LibreECx.pt, LibreECs-pose.pt, LibreECm-pose.pt, LibreECl-pose.pt, LibreECx-pose.pt, LibreECs-seg.pt, LibreECm-seg.pt, LibreECl-seg.pt, LibreECx-seg.pt

Hosting note: YOLO-NAS checkpoints (plain text above) are hosted on Deci's CDN under their proprietary weights license, not on the LibreYOLO Hugging Face org. The factory still downloads them automatically on first use. DAMO-YOLO was removed in v1.3.0 and is no longer loadable.

New model families in v1.3.0

v1.3.0 adds classification, dense semantic segmentation, monocular depth and point-localization families. They load through the same factory but are newly added and experimental. DINOv2 needs pip install libreyolo[rfdetr] (transformers).

FamilyStatusTaskCheckpoints
MobileNetV4ExperimentalclassifyLibreMobileNetV4s-cls.pt, LibreMobileNetV4m-cls.pt, LibreMobileNetV4l-cls.pt
ConvNeXtExperimentalclassifyLibreConvNeXtt-cls.pt, LibreConvNeXts-cls.pt, LibreConvNeXtb-cls.pt
EfficientNetV2ExperimentalclassifyLibreEfficientNetV2b0-cls.pt, LibreEfficientNetV2b1-cls.pt, LibreEfficientNetV2b2-cls.pt, LibreEfficientNetV2b3-cls.pt
DINOv2Experimentalsemantic, classifyLibreDINOv2n.pt, LibreDINOv2s.pt, LibreDINOv2m.pt, LibreDINOv2l.pt, LibreDINOv2n-cls.pt, LibreDINOv2s-cls.pt, LibreDINOv2m-cls.pt, LibreDINOv2l-cls.pt
Depth Anything V2ExperimentaldepthLibreDepthAnythingV2s-depth.pt, LibreDepthAnythingV2b-depth.pt, LibreDepthAnythingV2l-depth.pt, LibreDepthAnythingV2g-depth.pt
FOMOExperimentalpointLibreFOMOs-point.pt, LibreFOMOm-point.pt, LibreFOMOl-point.pt
  • MobileNetV4 is the commercially clean classification path: Apache-2.0 ImageNet-1k weights (s/m/l at 224/224/256), with predict, top-1/top-5 validation, fine-tune training and ONNX export.
  • ConvNeXt (V1 Tiny/Small/Base, 224) and EfficientNetV2 (b0-b3, 224-300) are additional Apache-2.0 ImageNet-1k classifiers (the accuracy tier).
  • DINOv2 is a DINOv2 backbone with a task head: dense semantic segmentation at 518 (default) and a classification linear probe at 224. It is not the RF-DETR detector. Classification was moved here from RF-DETR in v1.3.0.
  • Depth Anything V2 does monocular depth (sizes s/b/l/g, all at 518). ViT-S weights are Apache-2.0; ViT-B/L/G are CC-BY-NC-4.0 (non-commercial). Inference and zero-shot validation only: not trainable and with no export.
  • FOMO is a point-localizer emitting (x, y, class, confidence) per object. Pretrained weights are not redistributed: pass a local checkpoint or train from scratch.

Promptable and VLM tiers: LibreSAM (promptable segmentation, libreyolo[sam]) and the LibreVLM tier of vision-language detectors (libreyolo[vlm]) are separate categories that load upstream Hugging Face snapshots and are not routed through the LibreYOLO() detector factory. Their weights inherit each upstream model's license.

Specialized models

FamilyStatusTasksCheckpoints
L2CSExperimentalgaze (inference-only) - see Gaze EstimationLibreL2CSr50.pt

L2CS architecture sizes include r18, r34, r50, r101, and r152, but the upstream-published Gaze360 checkpoint is ResNet-50. Install libreyolo[gaze] for the optional download helper, or pass a local checkpoint path for other sizes. L2CS weights are not hosted by LibreYOLO (the Gaze360 dataset license forbids redistribution).

Factory function

Use the LibreYOLO() factory for every model and runtime. Give it an official checkpoint name or exported artifact path, then let it choose the right model family, task, class count, and runtime:

python
1from libreyolo import LibreYOLO
2
3# Default: YOLO9 detection
4model = LibreYOLO("LibreYOLO9c.pt")
5
6# Flagship transformer: RF-DETR
7model = LibreYOLO("LibreRFDETRs.pt")
8model = LibreYOLO("LibreRFDETRs-seg.pt") # validated segmentation
9
10# New in v1.3.0
11model = LibreYOLO("LibreMobileNetV4s-cls.pt") # classification (Apache, ImageNet-1k)
12model = LibreYOLO("LibreDINOv2n.pt") # semantic segmentation
13model = LibreYOLO("LibreDepthAnythingV2s-depth.pt") # monocular depth
14model = LibreYOLO("LibreFOMOs-point.pt") # point localization (local weights)
15
16# Exported deployment formats
17model = LibreYOLO("model.onnx") # ONNX Runtime
18model = LibreYOLO("model.engine") # TensorRT
19model = LibreYOLO("model.mlpackage") # CoreML (macOS)
20model = LibreYOLO("model_openvino/") # OpenVINO (directory)
21model = LibreYOLO("model_ncnn/") # NCNN (directory)

For recognized official checkpoint filenames, LibreYOLO can auto-download missing weights. For custom filenames, point at an explicit local path. Keep new projects on YOLO9 detection or RF-DETR detection / segmentation; other families, tasks, and the new families are experimental in v1.3.1.

Tasks & Filenames

LibreYOLO uses a uniform filename convention so the factory can detect family, size, and task from the checkpoint name alone:

text
1Libre<FAMILY><size>[-<task>].pt

Task suffixes

TaskCanonical nameFilename suffixOwned by
Detection"detect"(none - implicit)most families (default)
Instance segmentation"segment"-segRF-DETR, EdgeCrafter
Semantic segmentation"semantic"-semDINOv2
Pose estimation"pose"-poseYOLO-NAS, EdgeCrafter, RF-DETR (preview)
Oriented boxes"obb"-obbRF-DETR (preview)
Classification"classify"-clsMobileNetV4, ConvNeXt, EfficientNetV2, DINOv2
Monocular depth"depth"-depthDepth Anything V2
Point localization"point"-pointFOMO
Gaze estimation"gaze"-gazeL2CS

Detection is implicit (no suffix), following the common YOLO convention. The factory accepts aliases at the API boundary ("detection", "seg","keypoints", "cls", etc.); only the canonical names above appear in filenames. A task is available only when it is in that family's supported-task set.

Resolution precedence

When you load a model, the task is resolved in this order:

text
1explicit task= → checkpoint["task"] → filename suffix → family default
python
1from libreyolo import LibreYOLO
2
3# 1. Filename suffix decides → segment
4model = LibreYOLO("LibreRFDETRs-seg.pt")
5
6# 2. Override regardless of filename
7model = LibreYOLO("custom_weights.pt", task="segment")
8
9# 3. Detection is implicit
10model = LibreYOLO("LibreYOLO9c.pt") # task="detect"

Per-family task support

Familyv1.3.1 statusDefaultSupported tasks
YOLO9detect single-GPU heavily tested; multi-GPU experimentaldetectdetect
RF-DETRdetect and segment single-GPU heavily tested; pose and OBB research previewdetectdetect, segment, pose, obb
YOLOXexperimentaldetectdetect
YOLO9-E2Eexperimentaldetectdetect
YOLO9-P2new, experimental (small objects)detectdetect
YOLO-NASexperimentaldetectdetect, pose
D-FINE / DEIM / DEIMv2experimentaldetectdetect
RT-DETR / RT-DETRv2 / RT-DETRv4experimentaldetectdetect
PicoDet / RTMDetexperimentaldetectdetect
EdgeCrafter (EC)experimentaldetectdetect, pose, segment
YOLO2 / YOLO3 / YOLO4 / YOLO7new, legacy baselines (inference-only)detectdetect
PIDNetnew, experimentalsemanticsemantic (inference and val only)
EoMTnew, experimentalsemanticsemantic (inference and val only)
DINOv2experimentalsemanticsemantic, classify
MobileNetV4 / ConvNeXt / EfficientNetV2 / ResNetexperimentalclassifyclassify
CLIPexperimentalclassifyzero-shot classify
Depth Anything V2experimentaldepthdepth (inference and val only)
NAFNetnew, experimentalrestorerestore
FOMOexperimentalpointpoint
L2CSexperimentalgazegaze (inference-only)

Three tiers sit outside the LibreYOLO() factory and are imported directly instead: LibreSAM (promptable segmentation), LibreOpenVocab (open-vocabulary detection), and LibreVLM. They are not checkpoint families, so LibreYOLO("sam_b") and friends will not resolve.

Legacy YOLO baselines

v1.3.1 adds the historical Darknet lineage so you can reproduce old baselines against modern ones with one API. These are inference-only: none of them can be trained in LibreYOLO, and they are not the path to pick for new work. Reach for YOLO9 or RF-DETR instead.

FamilyCheckpointsInput sizeWeights license
LibreYOLO2LibreYOLO2{t,b}.pt416 / 608Public domain
LibreYOLO3LibreYOLO3{t,b,spp}.pt416 / 416 / 608Public domain
LibreYOLO4LibreYOLO4{t,b}.pt416 / 608Public domain
LibreYOLO7LibreYOLO7b.pt640MIT

All four are COCO-80. LibreYOLO7 is ported from the MIT-licensed MultimediaTechLab/YOLO, deliberately not from the GPL-3.0 reference implementation, so it is safe to use commercially.

YOLO9-P2, for small objects

LibreYOLO9P2 adds a stride-4 detection scale to YOLO9. That extra high-resolution head is what makes it worth the cost when your objects are tiny in frame, which is the classic aerial and drone-footage problem. It trains and exports like YOLO9.

One published checkpoint ships: LibreYOLO9P2s-visdrone.pt, trained on VisDrone. There is no COCO-pretrained P2 checkpoint. Note the licence carefully: the VisDrone weights are CC BY-NC-SA 3.0, so they are non-commercial. Train your own P2 weights on a permissive dataset if you need commercial use.

Two rough edges in v1.3.1. TFLite export is not available for P2 (though it is available for the legacy families above), and the CLI cannot resolve the variant filename, so load the VisDrone checkpoint from Python.

Examples

text
1# Detection (implicit)
2LibreYOLO9c.pt
3LibreRFDETRs.pt
4LibreRTDETRr50.pt
5
6# Instance segmentation (-seg)
7LibreRFDETRs-seg.pt
8LibreECm-seg.pt
9
10# Semantic segmentation (-sem)
11LibreDINOv2n.pt # semantic is DINOv2's default; -sem optional
12
13# Pose (-pose)
14LibreYOLONASn-pose.pt
15LibreECs-pose.pt
16LibreRFDETRx-pose.pt # preview; size x only
17
18# Oriented boxes (-obb)
19LibreRFDETRn-obb.pt # preview
20
21# Classification (-cls)
22LibreMobileNetV4s-cls.pt
23LibreConvNeXtt-cls.pt
24LibreEfficientNetV2b0-cls.pt
25LibreDINOv2n-cls.pt # DINOv2 linear probe
26
27# Depth (-depth)
28LibreDepthAnythingV2s-depth.pt
29
30# Point (-point)
31LibreFOMOs-point.pt
32
33# Gaze (-gaze optional; only task for L2CS)
34LibreL2CSr50.pt

Deprecated aliases

LibreYOLORTDETR and LibreYOLORFDETR are old names for LibreRTDETR and LibreRFDETR respectively. They still resolve with a DeprecationWarning - update imports when convenient.

Prediction

The single-GPU prediction path is heavily tested for YOLO9 detection, RF-DETR detection, and RF-DETR segmentation. Other families and tasks use the same API but are experimental in v1.3.1.

Basic prediction

python
1result = model("image.jpg")

All prediction parameters

python
1result = model(
2 "image.jpg",
3 conf=0.25, # confidence threshold (default: 0.25)
4 iou=0.45, # NMS IoU threshold (default: 0.45)
5 imgsz=640, # input size override (default: model's native)
6 device="auto", # "auto", "cpu", "mps", "0", "cuda:0", ...
7 classes=[0, 2, 5], # filter to specific class IDs (default: all)
8 max_det=300, # max detections per image (default: 300)
9 augment=False, # test-time augmentation where implemented
10 save=True, # save annotated image (default: False)
11 batch=4, # directory batch size
12 stream=False, # video only: yield frame results instead of a list
13 vid_stride=1, # video only: process every N-th frame
14 show=False, # video only: display annotated frames
15 tiling=False, # large-image tiled detection
16 overlap_ratio=0.2, # tile overlap ratio
17 output_path="out/", # where to save (default: runs/detect/predict*/)
18 color_format="auto", # "auto", "rgb", or "bgr"
19 output_file_format="png", # output format: "jpg", "png", "webp"
20)

model.predict(...) is an alias for model(...).

Supported input formats

LibreYOLO accepts images in any of these formats:

python
1# File path (string or pathlib.Path)
2result = model("photo.jpg")
3result = model(Path("photo.jpg"))
4
5# URL
6result = model("https://example.com/image.jpg")
7result = model("s3://bucket/image.jpg")
8result = model("gs://bucket/image.jpg")
9
10# PIL Image
11from PIL import Image
12img = Image.open("photo.jpg")
13result = model(img)
14
15# NumPy array (HWC or CHW, RGB or BGR, uint8 or float32)
16import numpy as np
17arr = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
18result = model(arr)
19
20# OpenCV (BGR) - specify color_format
21import cv2
22frame = cv2.imread("photo.jpg")
23result = model(frame, color_format="bgr")
24
25# PyTorch tensor (CHW or NCHW)
26import torch
27tensor = torch.randn(3, 640, 640)
28result = model(tensor)
29
30# Raw bytes
31with open("photo.jpg", "rb") as f:
32 result = model(f.read())
33
34# BytesIO
35from io import BytesIO
36result = model(BytesIO(open("photo.jpg", "rb").read()))
37
38# Directory of images
39results = model("images/", batch=4)

Working with results

Every prediction returns a Results object (or a list of them for directories):

python
1result = model("image.jpg")
2
3# Number of detections
4len(result) # e.g., 5
5
6# Bounding boxes in xyxy format (x1, y1, x2, y2)
7result.boxes.xyxy # tensor of shape (N, 4)
8
9# Bounding boxes in xywh format (center_x, center_y, width, height)
10result.boxes.xywh # tensor of shape (N, 4)
11
12# Confidence scores
13result.boxes.conf # tensor of shape (N,)
14
15# Class IDs
16result.boxes.cls # tensor of shape (N,)
17
18# Combined data: [x1, y1, x2, y2, conf, cls]
19# Tracking adds a track_id column before conf/cls.
20result.boxes.data # shape (N, 6), or (N, 7) when tracked
21
22# Metadata
23result.orig_shape # (height, width) of original image
24result.path # source file path (or None)
25result.names # {0: "person", 1: "bicycle", ...}
26
27# Move to CPU / convert to numpy
28result_cpu = result.cpu()
29boxes_np = result.boxes.numpy()

Class filtering

Filter detections to specific class IDs:

python
1# Only detect people (class 0) and cars (class 2)
2result = model("image.jpg", classes=[0, 2])

Batched in-memory inference

New in v1.3.0: model.predict() accepts a list or tuple of in-memory images (NumPy arrays, PIL images, or tensors) and runs them as a true stacked-forward batch. Set batch > 1 to actually batch the forward pass on families that support it; a list of results is returned, one per input.

python
1import numpy as np
2from libreyolo import LibreYOLO
3
4model = LibreYOLO("LibreYOLO9c.pt")
5
6frames = [
7 np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8),
8 np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8),
9 np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8),
10]
11
12results = model(frames, batch=4) # list/tuple -> true batched inference
13for r in results:
14 print(len(r), r.boxes.xyxy.shape)

Model info

model.info() (new in v1.3.0) returns a JSON-friendly dict of family, size, task, parameter counts, input size, and class names, and logs a human-readable summary when verbose=True.

python
1meta = model.info(detailed=False, verbose=True)
2# meta -> {"family": ..., "size": ..., "task": ..., "params": ..., "imgsz": ..., "names": {...}, ...}

Tiled Inference

For images much larger than the model's input size (e.g., satellite imagery, drone footage), tiled inference splits the image into overlapping tiles, runs detection on each, and merges results.

Tiling is detection-only in v1.3.1. It rejects segmentation masks, and it cannot be combined with augment=True.

python
1result = model(
2 "large_aerial_image.jpg",
3 tiling=True,
4 overlap_ratio=0.2, # 20% overlap between tiles (default)
5 save=True,
6)
7
8# Extra metadata on tiled results
9result.tiled # True
10result.num_tiles # number of tiles used
11result.saved_path # output directory when save=True
12result.tiles_path # directory containing per-tile crops
13result.grid_path # grid visualization image

When save=True with tiling, LibreYOLO saves:

  • final_image.jpg - full image with all merged detections drawn
  • grid_visualization.jpg - image showing tile grid overlay
  • tiles/ - individual tile crops
  • metadata.json - tiling parameters and detection counts

If the image is already smaller than the model's input size, tiling is skipped automatically.

Video Inference

Pass any video file to a flagship and LibreYOLO auto-detects the format from the extension. Supported: .mp4, .avi, .mov, .mkv, .webm, .gif, and other common containers.

Save annotated video

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreYOLO9c.pt")
4results = model("clip.mp4", save=True)
5# Saved under runs/detect/predict*/clip.mp4

Stream results (memory-flat)

For long videos, pass stream=True to get a generator. Each iteration yields the Results for one frame - no full list buffered in RAM.

python
1for result in model("long_clip.mp4", stream=True):
2 print(f"frame {result.frame_idx}: {len(result)} detections")

Frame subsampling

python
1# Process every 2nd frame (halves compute and saved fps)
2results = model("clip.mp4", vid_stride=2, save=True)

Live preview

python
1# Display annotated frames in an OpenCV window while processing
2results = model("clip.mp4", show=True)

VideoSource / VideoWriter for custom pipelines

When you need full control of decoding and encoding - custom frame transforms, mixing tracker output, writing to a non-default codec - use the building blocks directly:

python
1from libreyolo import LibreYOLO
2from libreyolo.utils.video import VideoSource, VideoWriter
3
4model = LibreYOLO("LibreYOLO9c.pt")
5
6with VideoSource("clip.mp4", vid_stride=1) as src, \
7 VideoWriter("out.mp4", fps=src.fps, width=src.width, height=src.height) as out:
8 for frame_bgr, frame_idx in src:
9 result = model(frame_bgr, color_format="bgr")
10 # ... draw, transform, etc.
11 out.write_frame(frame_bgr)

Tracking

LibreYOLO ships two motion trackers that consume Results from any detector and add persistent track IDs: ByteTrack (default) and OC-SORT (new in v1.3.0), which is more robust to occlusion and non-linear motion. Tracking is most tested with single-GPU YOLO9 detection and RF-DETR detection; other detection families are experimental in v1.3.1.

Install

bash
1pip install libreyolo[tracking] # compatibility extra; tracking deps ship in base dev install

Video tracking helper

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreYOLO9c.pt")
4
5for result in model.track(
6 "clip.mp4",
7 track_conf=0.25,
8 iou=0.45,
9 save=True, # writes runs/track/<video_stem>.mp4 by default
10 vid_stride=1,
11):
12 print(result.frame_idx, result.track_id)

model.track() is a generator for video files. It runs detection frame by frame, uses the lower ByteTrack confidence internally for recovery, and yields Results with result.track_id and result.boxes.id populated.

Basic loop

python
1from libreyolo import LibreYOLO, ByteTracker
2from libreyolo.utils.video import VideoSource
3
4model = LibreYOLO("LibreYOLO9c.pt")
5tracker = ByteTracker()
6
7with VideoSource("clip.mp4") as src:
8 for frame_bgr, frame_idx in src:
9 result = model(frame_bgr, color_format="bgr", conf=0.1)
10 tracked = tracker.update(result)
11
12 for i in range(len(tracked.boxes)):
13 track_id = int(tracked.boxes.id[i])
14 xyxy = tracked.boxes.xyxy[i].tolist()
15 cls = int(tracked.boxes.cls[i])
16 print(f"frame {frame_idx} - id {track_id} cls {cls} {xyxy}")

After tracker.update(), result.boxes.id holds the track IDs and result.boxes.is_track is True.

TrackConfig knobs

python
1from libreyolo import ByteTracker, TrackConfig
2
3cfg = TrackConfig(
4 track_high_thresh=0.25, # first-stage match threshold
5 track_low_thresh=0.1, # second-stage (low-conf recovery)
6 new_track_thresh=0.25, # minimum conf to start a new track
7 match_thresh=0.8, # IoU cost cutoff (stage 1)
8 match_thresh_low=0.5, # IoU cost cutoff (stage 2)
9 match_thresh_unconfirmed=0.7, # IoU cost cutoff for unconfirmed tracks
10 track_buffer=30, # frames to keep lost tracks before removal
11 frame_rate=30, # scales track_buffer
12 fuse_score=True, # multiply IoU by detection score
13 minimum_consecutive_frames=1, # frames to confirm a new track
14)
15tracker = ByteTracker(config=cfg)

Reset between clips

python
1tracker.reset() # clears tracked / lost / removed lists and the ID counter

OC-SORT (occlusion-robust)

Select OC-SORT with tracker="ocsort" on model.track(). ByteTrack stays the default. With OC-SORT, track_conf maps to the tracker's det_thresh (for ByteTrack it maps to track_high_thresh).

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreYOLO9c.pt")
4
5for result in model.track(
6 "clip.mp4",
7 tracker="ocsort", # "bytetrack" (default) or "ocsort"
8 track_conf=0.25, # maps to OC-SORT det_thresh
9 iou=0.45,
10 save=True,
11):
12 print(result.frame_idx, result.track_id)

Pass an OCSortConfig for full control. Supplying a config instance selects the tracker by type, so the tracker= string is then ignored.

python
1from libreyolo import LibreYOLO, OCSortConfig
2
3cfg = OCSortConfig(
4 det_thresh=0.25, # boxes above this drive association and spawn new tracks
5 max_age=30, # frames a track survives without an observation
6 min_hits=3, # consecutive hits before a track is reported
7 iou_threshold=0.3, # minimum IoU for a valid association
8 delta_t=3, # frame span used to estimate velocity direction
9 inertia=0.2, # weight of the velocity-direction (momentum) term
10 use_byte=False, # enable the BYTE low-score recovery pass
11)
12
13model = LibreYOLO("LibreYOLO9c.pt")
14for result in model.track("clip.mp4", tracker_config=cfg, save=True):
15 print(result.frame_idx, result.track_id)

Ensembling

Detection onlyPython API only

LibreEnsemble runs two or more detection models and fuses their detections into one ordinary Results. Fusion happens at the detection level, never at the tensor level, so every member keeps its own input size, normalization and NMS. That is what lets you mix a grid detector with a DETR, or a .pt checkpoint with an exported backend, in the same ensemble.

Class spaces do not have to match. Members are unified by class name: identical name maps pass straight through, otherwise LibreYOLO builds the union and remaps each member into it. Boxes are only fused with boxes of the same unified class, and a class that only one member knows passes through unfused.

Fuse two detectors

python
1from libreyolo import LibreEnsemble
2
3# Weighted Boxes Fusion (the default), keep only boxes BOTH models found
4ens = LibreEnsemble(["LibreYOLO9s.pt", "LibreRFDETRs.pt"], min_votes=2)
5
6result = ens("image.jpg", conf=0.25)
7print(result.boxes.xyxy)
8print(result.names) # the unified (union) class map
9print(result.speed) # per-member timings plus fusion

Trust weights and per-member settings

weights expresses how much you trust each member (set it proportional to each model's validation mAP). conf, iou and device accept either one value for everyone or one value per member.

python
1ens = LibreEnsemble(
2 ["LibreYOLO9s.pt", "LibreRFDETRs.pt"],
3 weights=[1.0, 1.4], # pull fused coordinates and scores toward member 2
4 fusion="wbf", # "wbf" | "wbf_seeded" | "nms" | your own callable
5 fusion_iou=0.55, # IoU used to CLUSTER boxes for fusion, not member NMS
6 min_votes=1, # keep boxes confirmed by at least N members
7)
8
9result = ens("image.jpg", conf=[0.25, 0.4]) # per-member confidence

Bring an outside detector

ExternalDetector wraps any callable that returns boxes, so a model that is not a LibreYOLO model can still join the ensemble. The function receives a PIL image and must return boxes in original-image pixels.

python
1from libreyolo import LibreEnsemble, ExternalDetector
2
3def my_detector(image):
4 # -> (boxes_xyxy, scores, labels) in ORIGINAL-image pixels
5 return boxes, scores, labels
6
7member = ExternalDetector(my_detector, names={0: "person"})
8ens = LibreEnsemble(["LibreYOLO9s.pt", member])

Limits

  • Detection members only. Any member whose task is not detect raises. Segmentation and pose models cannot be ensembled.
  • At least two members are required.
  • min_votes above 1 requires a voting fusion. It raises with fusion="nms"; use wbf or wbf_seeded.
  • Images and image directories only. Video sources and stream=True raise: run the members individually for video.
  • ens.val() and ens.export() both raise. Validate and export the members individually.
  • batch is accepted for API parity but images are still processed one at a time.

Instance Segmentation

v1.3.1 validation scope

The heavily tested path is detection, training and inference for YOLO9 and RF-DETR, including RF-DETR segmentation.

Other model families, tasks, and multi-GPU workflows are available but experimental.

RF-DETR segmentation is the segmentation path in v1.3.1 and is the heavily tested option. EdgeCrafter (-seg) also exposes a segmentation head but is experimental. YOLO9 no longer ships a segmentation head: it is detect-only as of v1.3.1.

Run segmentation

python
1from libreyolo import LibreYOLO
2
3# RF-DETR segmentation, the heavily tested segmentation path
4model = LibreYOLO("LibreRFDETRs-seg.pt")
5result = model("photo.jpg")
6
7# EdgeCrafter segmentation is also available but experimental
8# model = LibreYOLO("LibreECs-seg.pt")
9
10# Segmentation returns boxes + masks
11print(result.boxes.xyxy) # bounding boxes (N, 4)
12print(result.boxes.cls) # class IDs (N,)
13print(result.masks.data.shape) # (N, H, W) tensor of binary masks

Mask representations

python
1# Raw bitmasks
2result.masks.data # tensor (N, H, W) - original image resolution
3
4# Polygon contours (one ndarray of (M, 2) per instance)
5result.masks.xy # absolute pixel coords
6result.masks.xyn # normalized to [0, 1]
7
8# Move / convert like Boxes
9result.masks.cpu()
10result.masks.numpy()

Save annotated output

save=True draws boxes and translucent mask overlays automatically.

python
1model("photo.jpg", save=True)

Training segmentation

RF-DETR segmentation uses the RF-DETR COCO-format training pipeline and is part of the heavily tested single-GPU scope. EdgeCrafter segmentation training is available but experimental. YOLO9 segmentation training was removed in v1.3.0.

Semantic Segmentation

New in v1.3.1No export

Semantic segmentation labels every pixel with a class. It is a different task from instance segmentation: there are no object instances and no boxes, just one dense class map. Pass task="semantic" (aliases: semseg, sem), and read the result from result.semantic_mask. On a semantic model result.boxes and result.masks are both None.

Models

FamilyCheckpointsBackboneTrained onClassesTrain?
LibrePIDNetLibrePIDNet{s,m,l}-sem.ptPIDNet 3-branch CNNCityscapes19No
LibreEoMTLibreEoMTl-sem.ptDINOv2 ViT-LADE20K150No
LibreDINOv2none published: you train itDINOv2 + dense headyour datayou chooseYes

The three behave quite differently, so pick deliberately. LibrePIDNet is a fast real-time CNN carrying Cityscapes road-scene classes. LibreEoMT carries ADE20K's 150 general scene classes. Both ship pretrained weights and cannot be trained inside LibreYOLO: fine-tune them upstream and convert the result.

LibreDINOv2 is the mirror image, and the distinction matters: it is the fine-tuning family. There is no published LibreDINOv2 semantic checkpoint. You construct it from the pretrained DINOv2 backbone with a fresh dense head and train it on your own masks, so it is the family to reach for when your classes are not Cityscapes or ADE20K.

Run semantic segmentation

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibrePIDNets-sem.pt") # Cityscapes, 19 classes
4result = model.predict("street.jpg")
5
6sm = result.semantic_mask # SemanticMask
7print(sm.data.shape) # (H, W) int class ids, on the ORIGINAL image canvas
8print(sm.classes) # sorted class ids present, 255 (ignore) excluded
9print(model.names[13]) # 'car'
10
11car = sm.class_mask(13) # (H, W) bool mask for one class
12
13result.plot().save("out.png") # class map overlaid on the image
14
15print(result.boxes, result.masks) # None None: semantic has no instances

SemanticMask API

python
1sm = result.semantic_mask
2
3sm.data # (H, W) integer class ids at original resolution
4sm.orig_shape # (H, W)
5sm.classes # list[int] of ids present, excluding the ignore index
6sm.class_mask(cid) # (H, W) bool
7SemanticMask.IGNORE_INDEX # 255: the void label, never counted as a class
8
9sm.cpu(); sm.numpy()

Validate

Validation reports mean IoU and pixel accuracy. Classes never seen in either the prediction or the ground truth are excluded from the mean rather than scored as zero. fitness is an alias of mIoU, so it is what drives best-checkpoint selection during training.

python
1metrics = model.val(data="cityscapes.yaml")
2print(metrics["metrics/mIoU"])
3print(metrics["metrics/pixel_accuracy"])
bash
1libreyolo val model=LibrePIDNets-sem.pt data=cityscapes.yaml split=val

Train (LibreDINOv2)

Masks are single-channel lossless images whose pixel value is the class id, paired to each image by filename stem. 255 means ignore and is excluded from both loss and metrics.

bash
1dataset/
2 images/train/*.jpg
3 images/val/*.jpg
4 masks/train/*.png # same stem as the image; pixel value = class id
5 masks/val/*.png
python
1from libreyolo import LibreDINOv2
2
3# model_path=None -> pretrained DINOv2 backbone + a fresh dense head
4model = LibreDINOv2(model_path=None, size="s", task="semantic", nb_classes=19)
5model.train(data="cityscapes.yaml", epochs=100, batch_size=4, lr=1e-4)

In the dataset YAML, masks_dir names the mask directory (default masks). If you omit it, LibreYOLO rasterizes masks from YOLO polygon labels at load time and appends a background class. label_mapping remaps source pixel values to training ids, and anything unmapped becomes ignore.

Limits

  • No export, in any format. Semantic export is blocked at the framework level, not just per model: ONNX, TensorRT, OpenVINO, NCNN, CoreML and TFLite all raise. A semantic export contract (dense logits plus backend argmax) has not landed yet.
  • Only LibreDINOv2 trains. LibrePIDNet.train() and LibreEoMT.train() raise.
  • EoMT is size l only and locked to imgsz=512 (its checkpoint uses fixed position embeddings), and it cannot batch: val(batch=N) warns and still runs one image at a time.
  • imgsz divisibility differs per family: PIDNet needs a multiple of 8, EoMT of 16, DINOv2 of 14. Violations raise.
  • No tracking and no test-time augmentation for semantic models.
  • Cityscapes, ADE20K and COCO-Stuff all require a manual download. LibreYOLO ships the dataset YAMLs, not the data.
  • Raw upstream checkpoints are rejected. Convert with weights/convert_pidnet_weights.py or weights/convert_eomt_weights.py.

Promptable Segmentation

New in v1.3.1Python API onlyInference only

LibreSAM is a separate tier from the detector factory, because a promptable segmenter has a different contract: it runs a heavy image encoder once, then answers cheap spatial prompts (a click, a box) with a mask. There is no fixed class list. Install it with pip install "libreyolo[sam]".

Two things surprise people. First, LibreSAM is a factory function, not a class, and it is deliberately kept outside the LibreYOLO() loader, so LibreYOLO("sam_b") does not work. Import it directly. Second, the whole tier is Python-only: there is no CLI path to it.

Models

FamilyPass to LibreSAM()EncoderNotes
SAM-1"base" (default), "large", "huge"ViT-B / L / HApache-2.0
SAM-2.1"sam2-tiny", "sam2-small", "sam2-base-plus", "sam2-large"HieraImages only, no video
MobileSAM"mobilesam"TinyViTFastest; native LibreYOLO port

Those short aliases only work through the LibreSAM() factory. The concrete classes take canonical sizes, so LibreSAM1("base") is right and LibreSAM1("sam_b") raises.

Prompt with a click or a box

python
1from libreyolo import LibreSAM
2
3model = LibreSAM("base") # SAM-1 ViT-B
4
5# a single click
6r = model.predict("img.jpg", points=[640, 360], labels=[1])
7print(r.masks.data.shape) # (1, H, W) bool, at the original resolution
8print(r.boxes.xyxy) # a tight box derived from the mask
9print(r.boxes.conf) # SAM's predicted mask quality, NOT a detection score
10
11# a box prompt
12r = model.predict("img.jpg", bboxes=[100, 100, 500, 500])
13
14# segment everything (a coarse grid); lower the grid on CPU, it is slow
15r = model.predict("img.jpg", points_per_side=16)

Encode once, prompt many times

This is the pattern that makes interactive use fast. The expensive encoder runs once per image and every later prompt reuses the embedding.

python
1model.set_image("img.jpg") # heavy encoder runs ONCE
2a = model.predict(points=[500, 375], labels=[1]) # cheap: decoder only
3b = model.predict(bboxes=[100, 100, 200, 200]) # cheap: reuses the embedding
4model.reset_image()

How prompts are shaped

Nesting depth carries meaning, and this is the single easiest thing to get wrong. Points are plain [x, y] pixels. A label of 1 means include, 0 means exclude.

You passIt means
points=[x, y]one object, one point
points=[[x, y], [x, y]]TWO objects, one point each
points=[[[x, y], [x, y]]]ONE object, two points
python
1# refine ONE object with a positive and a negative click
2r = model.predict(
3 "img.jpg",
4 points=[[[500, 375], [620, 400]]], # one object, two points
5 labels=[1, 0], # include, then exclude
6)
7
8# all three whole-vs-part candidate masks for an ambiguous click
9r = model.predict("img.jpg", points=[640, 360], labels=[1], multimask=True)

Limits

  • SAM-2 is images only. There is no video segmentation and no memory propagation across frames in v1.3.1: track() raises. Call predict() per frame.
  • No training, no validation, no export, for any SAM family. All three raise, including export(format="onnx").
  • Mask prompts (masks=) are not supported and raise. Use points or boxes.
  • conf here filters on SAM's predicted mask quality, not on detection confidence. Detector intuition does not transfer.
  • Everything runs in fp32, even on CUDA. This is deliberate: half precision rounds prompt coordinates by several pixels at SAM's 1024px working size, which silently moves where you clicked.
  • Segment-everything is a simplified grid, not the reference automatic mask generator. It under-segments crowded scenes.
  • Weights download into ./weights/ relative to your working directory, so running from elsewhere re-downloads.

Open-Vocabulary Detection

New in v1.3.1Python API onlyApache-2.0 weights

Give the model a list of class names as text and get real detection boxes back. No training, no labelled data. Change the list and you change what it detects. Install with pip install "libreyolo[openvocab]".

This is not the same as the LibreVLM tier, and the difference matters. These are purpose-built detectors conditioned on text: the detector head returns boxes with real model scores. A VLM instead generates text that LibreYOLO parses into boxes. The rule of thumb: boxes for named classes, use open-vocab; describe or instruct, use a VLM. The other practical difference is licensing: every weight in this tier is Apache-2.0, while the VLM tier contains non-commercial models.

Models

Pass to LibreOpenVocab()ClassBackboneDefault conf
"grounding-dino" (default, tiny)LibreGroundingDINOSwin-T + BERT0.25
"grounding-dino-base"LibreGroundingDINOSwin-B + BERT0.25
"owlv2"LibreOWLv2ViT-B/160.1
"owlv2-large"LibreOWLv2ViT-L/140.1

Detect anything you can name

The vocabulary is set on the model, with set_classes(), and it is sticky across later calls. There is no prompts= or text= argument on predict().

python
1from libreyolo import LibreOpenVocab
2
3model = LibreOpenVocab("grounding-dino")
4model.set_classes(["person", "dog", "skateboard"]) # sticky vocabulary
5
6result = model.predict("street.jpg", conf=0.25, text_threshold=0.25)
7print(result.boxes.xyxy, result.boxes.conf)
8print(result.names) # {0: 'person', 1: 'dog', 2: 'skateboard'}
9
10result = model.predict("another.jpg") # same vocabulary, still set
11
12# or set it at construction
13model = LibreOpenVocab("owlv2", names=["forklift", "pallet"])

Watch out for the lookalike. predict(classes=...) is not the text API. It is the standard integer class-id filter and takes a list of ints. The text vocabulary goes through set_classes().

Practical notes

  • Short noun phrases work best. "remote control" beats "remote". Phrases that cannot be mapped back to one of your class names unambiguously are dropped, so a missing detection is sometimes a mapping drop rather than a detector miss.
  • There is no cap on how many classes you may pass. Grounding DINO automatically splits a long vocabulary into chunks that fit its text encoder and runs one forward pass per chunk, so cost grows with vocabulary size. That is the main latency knob you control.
  • text_threshold is Grounding DINO only. Passing it to OWLv2 raises.
  • The two families score differently, so tune conf per family rather than reusing a number.
  • Expect this to be far slower than a LibreYOLO detector. The honest workflow: use open-vocab to explore or auto-label an open vocabulary, then train a fast detector on the result.

Limits

  • No CLI. libreyolo predict model=grounding-dino does not work. This tier is reachable only from Python.
  • No training, no validation, no export, no tracking. All four raise.
  • imgsz and augment=True are rejected: the processor owns resizing. iou is accepted but ignored, since no LibreYOLO NMS runs here.
  • Batching gives no speedup: images run one at a time. Everything is fp32.

Pose Estimation

Pose (human keypoint) estimation runs on YOLO-NAS (-pose), EdgeCrafter (-pose), and, new in v1.3.0, an RF-DETR (-pose) preview. Each pose model is single-class ("person") with 17 COCO keypoints.

Run pose

python
1from libreyolo import LibreYOLO
2
3# YOLO-NAS pose
4model = LibreYOLO("LibreYOLONASs-pose.pt")
5result = model("people.jpg")
6
7# EdgeCrafter pose
8# model = LibreYOLO("LibreECs-pose.pt")
9
10# Per-person bbox + 17 keypoints
11print(result.boxes.xyxy) # person boxes (N, 4)
12print(result.keypoints.xy.shape) # (N, 17, 2) pixel coordinates

Preview RF-DETR pose ships a single checkpoint at size x only: LibreRFDETRx-pose.pt. It is a research preview in v1.3.1.

python
1# RF-DETR pose preview (size x only)
2model = LibreYOLO("LibreRFDETRx-pose.pt")
3result = model("people.jpg")
4print(result.keypoints.xy.shape) # (N, 17, 2)

Keypoint API

python
1result.keypoints.xy # (N, K, 2) absolute pixel coords
2result.keypoints.xyn # (N, K, 2) normalized to [0, 1]
3result.keypoints.conf # (N, K) per-keypoint confidence (None if model doesn't emit it)
4result.keypoints.has_visible # (N, K) bool - conf > 0
5
6result.keypoints.cpu()
7result.keypoints.numpy()

Save annotated output

python
1model("people.jpg", save=True) # draws boxes + skeleton

Pose training is supported for YOLO-NAS; EdgeCrafter pose is currently inference-only. RF-DETR pose is a preview (size x only). YOLO9 is detect-only and ships no pose checkpoints.

Gaze Estimation

Gaze direction estimation is provided by the LibreL2CS family, an L2CS-Net port with a ResNet trunk and two angle-bin classification heads. It is a two-stage model: an upstream face detector locates faces, then the gaze head predicts per-face pitch and yaw in radians. It is inference-only and experimental in v1.3.1.

Install

bash
1pip install libreyolo[gaze] # optional Google Drive helper for Gaze360 weights

The published L2CS ResNet-50 weights are trained on Gaze360 and are not mirrored by LibreYOLO. Without the optional helper, pass a local checkpoint path or follow the manual download instructions printed by LibreL2CS.

Two-stage inference

python
1from libreyolo import LibreYOLO
2from libreyolo.models.l2cs.face import resolve_face_detector
3
4# Gaze head
5gaze = LibreYOLO("LibreL2CSr50.pt")
6
7# Wire any LibreYOLO detector trained on faces
8face = LibreYOLO("path/to/face-detector.pt")
9gaze.face_detector = resolve_face_detector(face)
10
11result = gaze("portrait.jpg")
12print(result.boxes.xyxy) # face boxes
13print(result.gaze.data) # (N, 2) tensor - pitch, yaw in radians

Decode angles

python
1import math
2
3for i in range(len(result.gaze)):
4 pitch_rad, yaw_rad = result.gaze.data[i].tolist()
5 pitch_deg = pitch_rad * 180.0 / math.pi
6 yaw_deg = yaw_rad * 180.0 / math.pi
7 print(f"face {i}: pitch={pitch_deg:.1f} deg, yaw={yaw_deg:.1f} deg")

From the CLI: libreyolo predict model=LibreL2CSr50.pt source=portrait.jpg --face-detector path/to/face.pt.

Classification

New in v1.3.0: whole-image classification. Two families ship, and they target different needs. LibreMobileNetV4 is the production classifier (Apache-2.0 ImageNet-1k weights, exportable to ONNX). LibreDINOv2 with task=classify is a DINOv2 backbone plus linear probe, ideal for transfer learning, but its published weights are demo-grade and it cannot export yet. Classification is new in v1.3.0, so details may still change.

FamilyCheckpointsInputWeightsFine-tuneONNX export
LibreMobileNetV4LibreMobileNetV4{s,m,l}-cls.pt224 / 224 / 256Apache-2.0 ImageNet-1k (production)Cross-entropyYes
LibreDINOv2 (classify)LibreDINOv2{n,s,m,l}-cls.pt224Imagenette demo-grade (10 classes)Linear probeNot supported

LibreMobileNetV4 (production classifier)

Apache-2.0 ImageNet-1k weightsNew in v1.3.0

A native MobileNetV4-conv port (derived from timm) whose 1000-class ImageNet-1k weights load bit-identically. Sizes s / m run at 224, l at 256. Checkpoints:

LibreMobileNetV4s-cls.pt, LibreMobileNetV4m-cls.pt, LibreMobileNetV4l-cls.pt

Load and predict. A single image returns one Results; read .probs directly off it (pass a list to get a list back).

python
1from libreyolo import LibreYOLO
2
3# MobileNetV4-conv-Small, Apache-2.0 ImageNet-1k weights (auto-downloaded if missing)
4model = LibreYOLO("LibreMobileNetV4s-cls.pt")
5result = model("cat.jpg") # single image -> one Results
6
7probs = result.probs # whole-image class vector, length = num classes
8print(probs.top1, probs.top1conf) # top-1 class id (int) and its confidence
9print(probs.top5, probs.top5conf) # 5 class ids and 5 confidences
10print(result.names[probs.top1]) # human-readable class name

Fine-tune to a custom class set (ImageFolder layout). The head is rebuilt to the dataset class count automatically; the ImageNet-pretrained backbone transfers cleanly.

python
1from libreyolo import LibreMobileNetV4
2
3model = LibreMobileNetV4(size="s") # ImageNet-pretrained backbone
4model.train(
5 data="imagenette160", # known name, dataset root, or .zip URL
6 epochs=5,
7 batch=64,
8 lr0=1e-3, # AdamW + cosine, 1-epoch warmup
9 imgsz=224,
10)

Validate (top-1 / top-5 accuracy):

python
1model = LibreYOLO("LibreMobileNetV4s-cls.pt")
2metrics = model.val(data="imagenette160")
3print(metrics["metrics/accuracy_top1"])
4print(metrics["metrics/accuracy_top5"])

Export to ONNX (verified bit-exact against eager). The ONNX graph emits a single logits tensor.

python
1model = LibreYOLO("LibreMobileNetV4s-cls.pt")
2path = model.export(format="onnx", imgsz=224) # single output: logits [batch, num_classes]
3
4# Interop note: the ONNX output is RAW LOGITS, not softmaxed. The PyTorch
5# predict path applies softmax for you; non-Python consumers must apply it
6# themselves before reading probabilities.

LibreDINOv2 classify (linear probe / transfer)

Demo-grade weights (Imagenette)No export

A frozen-style DINOv2-S encoder with a trainable linear head, run at 224. The n / s / m / l sizes control only the projector width: all four share the same DINOv2-S encoder, so the published checkpoints land at near-identical accuracy. The shipped -cls weights are demo-grade (trained on Imagenette, 10 classes), so treat this family as the transfer-learning option, not a drop-in 1000-class classifier. Checkpoints:

LibreDINOv2n-cls.pt, LibreDINOv2s-cls.pt, LibreDINOv2m-cls.pt, LibreDINOv2l-cls.pt

Load and predict (same Probs surface as MobileNetV4):

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreDINOv2s-cls.pt") # DINOv2-S backbone + linear probe (224)
4result = model("springer.jpg")
5print(result.probs.top1, result.probs.top1conf)

Fine-tune for transfer. Build a fresh model with task="classify" for a brand-new head, or load a shipped -cls checkpoint and continue training. For the best accuracy, fine-tune from a shipped checkpoint rather than a fresh head, and keep the default lr=1e-4 (higher learning rates converge worse).

python
1from libreyolo import LibreDINOv2
2
3# Fresh DINOv2 backbone + random linear head, sized to the dataset
4model = LibreDINOv2(size="s", task="classify", nb_classes=3)
5model.train(data="path/to/imagefolder", epochs=5, lr=1e-4, batch=4)
6
7# Validate the same way (top-1 / top-5)
8metrics = model.val(data="path/to/imagefolder")
9print(metrics["metrics/accuracy_top1"])

Export is not implemented for LibreDINOv2. If you need an exportable classifier, use LibreMobileNetV4.

python
1model = LibreYOLO("LibreDINOv2s-cls.pt")
2model.export(format="onnx")
3# raises NotImplementedError: Export is not yet implemented for LibreDINOv2.

Dataset layout (both families)

Classification uses an ImageNet-style ImageFolder tree (folders, not label files). Class index is assigned by sorted folder name. data= accepts a dataset root, a known name (e.g. imagenette160), or a .zip URL.

text
1dataset_root/
2 train/ # required; one subfolder per class
3 class_a/img001.jpg
4 class_a/img002.jpg
5 class_b/img003.jpg
6 val/ # required for validation; same class folders as train
7 class_a/img010.jpg
8 class_b/img011.jpg

Results.probs reference

python
1probs = result.probs # Probs payload, 1-D vector of length = num classes
2probs.data # raw tensor / ndarray of class probabilities
3probs.top1 # int - argmax class id
4probs.top5 # list - 5 class ids, highest first
5probs.top1conf # float - confidence of the top-1 class
6probs.top5conf # 5 confidences, aligned with probs.top5
  • MobileNetV4 weights are production grade (Apache-2.0 ImageNet-1k, bit-identical load). DINOv2 classify weights are demo-grade (Imagenette, 10 classes).
  • There is no LibreRFDETR classifier in v1.3.0. Classification moved into the LibreMobileNetV4 and LibreDINOv2 families; legacy LibreRFDETR*-cls checkpoints are rejected on load.
  • A fresh DINOv2 fine-tune with the default recipe tops out around 0.93 top-1 on Imagenette, below the shipped 0.976. Fine-tune from a shipped -cls checkpoint to recover accuracy.
  • ONNX classify output is raw logits. Apply softmax in non-Python consumers.
  • Predicting a single image returns one Results. Read result.probs directly, or pass a list and index the list: model(["a.jpg"])[0].probs.

Depth Estimation

New in v1.3.0Inference and val only

New in v1.3.0: monocular depth via LibreDepthAnythingV2, a Depth Anything V2 port (DINOv2 encoder plus DPT head, NeurIPS 2024). It predicts a dense relative inverse-depth map: higher values are closer to the camera, with no metric unit implied. Sizes s / b / l / g map to ViT-S / B / L / G and all run at 518. Depth is new in v1.3.0 and supports inference and zero-shot validation only: no training and no export.

Checkpoints. Only the ViT-S checkpoint is Apache-2.0 and auto-hosted: LibreDepthAnythingV2s-depth.pt. The larger encoders LibreDepthAnythingV2b-depth.pt, LibreDepthAnythingV2l-depth.pt, LibreDepthAnythingV2g-depth.pt are CC-BY-NC-4.0 and are not redistributed by LibreYOLO; convert the official upstream checkpoints with weights/convert_depth_anything_v2_weights.py.

Run depth estimation

Input imgsz must be divisible by 14 (the DINOv2 patch grid). The depth map is returned on the original image canvas.

python
1from libreyolo import LibreYOLO
2
3# ViT-S encoder, Apache-2.0 weights (commercial use OK)
4model = LibreYOLO("LibreDepthAnythingV2s-depth.pt")
5result = model("street.jpg")
6
7depth = result.depth_map # DepthMap payload, (H, W) float on the original canvas
8print(depth.data.shape) # (H, W)
9print(depth.min, depth.max, depth.mean) # relative inverse depth: higher = closer
10norm = depth.normalized() # rescaled to [0, 1] over finite values

DepthMap API

python
1depth = result.depth_map
2depth.data # (H, W) float tensor / ndarray, relative inverse depth
3depth.min # min over finite values
4depth.max # max over finite values
5depth.mean # mean over finite values
6depth.normalized() # (H, W) rescaled to [0, 1]; non-finite pixels become 0
7
8depth.cpu()
9depth.numpy()

Zero-shot validation

Validation runs zero-shot through the shared depth validator and reports standard depth metrics (AbsRel, RMSE, and delta thresholds). The validator letterboxes to a fixed square and excludes padded pixels; because predict uses Depth Anything's native keep-aspect resize, non-square val metrics are a documented approximation of predict.

python
1metrics = model.val(data="depth_dataset.yaml")
2print(metrics["metrics/abs_rel"]) # absolute relative error (lower is better)
3print(metrics["metrics/rmse"]) # root mean squared error
4print(metrics["metrics/delta1"]) # fraction within a 1.25x ratio (higher is better)

Not supported

python
1model.train(data="...") # raises NotImplementedError - DA V2 is inference + val only
2model.export(format="onnx") # raises NotImplementedError - depth export is out of scope
  • Licensing is split: ViT-S (size s) weights are Apache-2.0 and fine for commercial use. ViT-B / ViT-L / ViT-G (sizes b / l / g) are CC-BY-NC-4.0 (non-commercial) and are not redistributed by LibreYOLO.
  • For commercial use, stick to size s.
  • Depth is relative inverse depth with no metric unit. Calibrate on your side if you need meters.
  • imgsz must be divisible by 14. Batched predict is disabled because keep-aspect resize yields variable per-image sizes.

Image Restoration

New in v1.3.1Trainable

The restore task takes a degraded image and returns a clean one. v1.3.1 ships LibreNAFNet, a port of NAFNet. Unlike most tasks here there is nothing to detect: the output is an image, returned as result.restored_image.

What a restoration model actually fixes, whether it denoises or deblurs, is a property of the weights it was trained on, not of the model size. Sizes s and l differ only in width (32 and 64 channels).

Checkpoints

One checkpoint is published: LibreNAFNetl-restore-sidd.pt, a real-image denoiser trained on SIDD, converted bit-exactly from upstream NAFNet, MIT licensed. For deblurring there is no published LibreYOLO checkpoint: convert the upstream GoPro weights yourself with weights/convert_nafnet_weights.py. Note that the plain names LibreNAFNets-restore.pt and LibreNAFNetl-restore.pt are not hosted, so asking for them will fail to download.

Clean up an image

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreNAFNetl-restore-sidd.pt") # SIDD denoiser
4result = model("noisy.jpg")
5
6img = result.restored_image # RestoredImage
7print(img.array.shape) # (H, W, 3) uint8 RGB, at the original resolution
8img.save("clean.png") # save lossless

Restoration runs at the image's native resolution: the input is padded to a multiple of 16 and cropped back afterwards, so you get the same size out that you put in.

Save losslessly, or you undo the work

This is the one thing to get right. libreyolo predict --save writes JPEG by default, which re-introduces compression artefacts into an image you just spent a model cleaning up. Ask for PNG.

bash
1libreyolo predict model=LibreNAFNetl-restore-sidd.pt source=noisy.jpg \
2 save=true output-file-format=png

Train and validate

Training takes paired degraded and clean images. Validation reports PSNR and SSIM.

python
1model = LibreYOLO("LibreNAFNetl-restore-sidd.pt")
2model.train(data="gopro.yaml", epochs=100)
3
4metrics = model.val(data="gopro.yaml")
5print(metrics["metrics/psnr"], metrics["metrics/ssim"])
  • Two reporting quirks to expect while training: the console prints PSNR under the mAP50 column heading (a labelling bug, the number is PSNR), and PSNR/SSIM are computed with no border crop, so they are not directly comparable to published NAFNet benchmark figures.
  • Export: ONNX (static shapes only, and imgsz must be a multiple of 16) and TorchScript work. TFLite and CoreML raise.

Point Localization

Experimental

LibreFOMO is a FOMO-style point localizer (sizes s / m / l) for centroid-style detection: instead of boxes, each detection is a single image coordinate. Predictions arrive as result.points. Pretrained LibreFOMO weights are not auto-downloaded, so pass a local checkpoint path (or train from scratch, which is experimental and requires allow_experimental=True).

python
1from libreyolo import LibreYOLO
2
3# LibreFOMO weights are not hosted by LibreYOLO - pass a local checkpoint
4model = LibreYOLO("path/to/LibreFOMOm-point.pt")
5result = model("scene.jpg")
6
7points = result.points # Points payload, (N, 4) rows: x, y, class, confidence
8print(points.xy) # (N, 2) absolute pixel coords
9print(points.xyn) # (N, 2) normalized to [0, 1]
10print(points.cls, points.conf)

Annotation (LibreLabel)

New in v1.3.1

libreyolo label starts a local, browser-based annotation tool. It writes LibreYOLO-native label files exactly where the trainer already reads them, so a folder of images becomes a trainable dataset with no conversion step, no cloud account and no database. The server is Python standard library only, and it runs entirely on your machine.

Label a folder of images

bash
1# open an existing dataset
2libreyolo label data=path/to/data.yaml
3
4# a bare folder works too: LibreYOLO scaffolds the dataset around it
5libreyolo label data=path/to/images
6
7# start on the project home screen and create a project in the browser
8libreyolo label

Options

OptionDefaultWhat it does
data(none)Dataset YAML or a folder. Omit to open the project home screen.
host127.0.0.1Interface to bind. See the sharing note below before changing this.
port8000Port to bind. Auto-bumps up to port+19 if taken.
deviceautoDevice used by the AI assist features.
no_assistfalseHard-disable every AI assist feature.
no_browserfalseDo not auto-open a browser.
sharefalseBind 0.0.0.0 so teammates on your LAN can label with you.

What you can label

Bounding boxes (detect), polygons (segment) and oriented boxes (obb, with a rotate handle). Keypoints, masks and depth files open read-only, so a save can never silently drop fields it does not understand. Classification labelling is not available yet.

AI assist, and the one rule it never breaks

LibreLabel can pre-label with one of your own detectors, turn a click into a mask with SAM, audit your existing labels for likely mistakes, find near-duplicate images, and detect train/val leakage. No AI path ever writes a label file. Every suggestion is held in memory until a human accepts it. AI assist also never downloads weights: if a checkpoint is not already on disk it refuses and tells you, rather than pulling hundreds of megabytes behind your back.

  • Box pre-labelling with any in-package detector works on the base install, no extra needed.
  • SAM click-to-mask needs pip install "libreyolo[label]" and the LibreSAM weights already downloaded.
  • Assist is task-aware: on an OBB project it is refused entirely, and on a segmentation project only the mask tools stay available.

Export

Export to YOLO, COCO or VOC (or several at once) from the Export dialog in the browser, with reproducible train/val/test splits. Note it is a browser action: there is no CLI export flag. Import is YOLO only, so COCO and VOC are export formats, not entry points.

Sharing, and a trap worth knowing

There is no authentication of any kind. Access is controlled purely by network position, so only share on a network you trust.

The counter-intuitive part: share=true is the safe way to let teammates in. It binds a wildcard address, and because admin rights require a loopback connection, you keep admin on your machine while teammates get a labelling-only view. Binding a specific address instead (host=192.168.1.50) makes your machine indistinguishable from a teammate, which hands full admin to every client on the LAN. Prefer share=true.

Training

v1.3.1 validation scope

The heavily tested path is detection, training and inference for YOLO9 and RF-DETR, including RF-DETR segmentation.

Other model families, tasks, and multi-GPU workflows are available but experimental.

The heavily tested training paths are single-GPU YOLO9 detection, RF-DETR detection, and RF-DETR segmentation. Other model-family trainers and multi-GPU workflows are available but experimental. YOLO9 is detect-only in v1.3.0, so there is no YOLO9 segmentation or pose training.

YOLO9 - CNN flagship training

python
1from libreyolo import LibreYOLO
2
3# Fine-tune from a pretrained checkpoint (recommended)
4model = LibreYOLO("LibreYOLO9c.pt")
5
6results = model.train(
7 data="coco128.yaml", # path to data.yaml (required)
8
9 # Schedule
10 epochs=300, # default: 300
11 batch=16,
12 imgsz=640,
13
14 # Optimizer
15 lr0=0.01, # initial learning rate
16 optimizer="SGD", # "SGD", "Adam", "AdamW"
17
18 # System
19 device="0", # "" | "cpu" | "cuda" | "0" | "0,1"
20 workers=8,
21 seed=0,
22
23 # Output
24 project="runs/train",
25 name="yolo9_exp",
26 exist_ok=False,
27
28 # Training features
29 amp=True, # automatic mixed precision
30 patience=50, # early stopping patience
31 resume=False, # resume from loaded checkpoint
32 pretrained=True, # transfer-learning init (True, a path, or None)
33 cache="disk", # cache decoded images: False | True/"ram" | "disk"
34 freeze=10, # freeze first N groups, or a list of indices / module names
35 save_plots=True, # write final validation plots to the run dir
36)
37
38print(f"Best mAP50-95: {results['best_mAP50_95']:.3f}")
39print(f"Best checkpoint: {results['best_checkpoint']}")

After training completes, the model instance is automatically reloaded with the best weights so you can call model(...) immediately. freeze, cache, pretrained, and save_plots are new in v1.3.0 and accepted across the trainer-backed families.

RF-DETR - transformer flagship training

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreRFDETRs.pt")
4
5results = model.train(
6 data="path/to/data.yaml",
7 epochs=100,
8 batch_size=4, # NOTE: RF-DETR uses batch_size, not batch
9 lr=1e-4,
10 output_dir="runs/train/rfdetr_exp",
11)

RF-DETR has its own training signature (batch_size, lr, output_dir) but shares LibreYOLO's dataset loader. Pass a data.yaml for detection or segmentation in either YOLO TXT or native COCO JSON layout — see Dataset Format.

LoRA fine-tuning (RF-DETR)

Experimental lora=True injects LoRA adapters into the RF-DETR backbone for low-VRAM fine-tuning. It requires the optional peft dependency (pip install "libreyolo[lora]") and is currently limited to RF-DETR; other families raise a clear error rather than ignoring the flag.

python
1model = LibreYOLO("LibreRFDETRs.pt")
2results = model.train(data="data.yaml", epochs=50, lora=True)

Experiment loggers

New in v1.3.0: pass loggers= to stream metrics to TensorBoard, MLflow, or Weights & Biases. Accepts a name ("tensorboard", "mlflow", "wandb"), a configured logger instance, or an iterable mixing both. Each backend is an optional extra (libreyolo[tensorboard], [mlflow], [wandb]).

python
1from libreyolo import LibreYOLO
2from libreyolo.training.loggers import MLflowLogger
3
4model = LibreYOLO("LibreYOLO9c.pt")
5
6# By name
7model.train(data="coco128.yaml", loggers="tensorboard")
8
9# Mix configured instances and names
10model.train(
11 data="coco128.yaml",
12 loggers=[MLflowLogger(experiment_name="my-exp"), "tensorboard"],
13)

Loggers are a Python-API feature only. There is no CLI flag for them; the rest of the new training knobs (--task, --cache, --lora, --freeze, --save-plots) are exposed on the CLI.

Training results dict

python
1{
2 "final_loss": 2.31,
3 "best_mAP50": 0.682,
4 "best_mAP50_95": 0.451,
5 "best_epoch": 87,
6 "save_dir": "runs/train/yolo9_exp",
7 "best_checkpoint": "runs/train/yolo9_exp/weights/best.pt",
8 "last_checkpoint": "runs/train/yolo9_exp/weights/last.pt",
9}

Resuming training

python
1# Load the checkpoint with the factory, then resume
2model = LibreYOLO("runs/train/yolo9_exp/weights/last.pt")
3results = model.train(data="coco128.yaml", resume=True)

Custom dataset YAML format

data.yaml
1path: /path/to/dataset
2train: images/train
3val: images/val
4test: images/test # optional
5
6nc: 3
7names: ["cat", "dog", "bird"]

Additional training paths

Other families have trainer hooks, but they are not the recommended path in v1.3.0. Keep new work on YOLO9 detection or RF-DETR detection/segmentation; use experimental trainers only for compatibility, benchmark reproduction, or targeted research. PicoDet, RTMDet, and EC training require an explicit allow_experimental=True acknowledgement.

Training from a YAML config

Every model.train(...) accepts cfg="train.yaml" to load all parameters from a file. Explicit kwargs still win over yaml values, so you can use a yaml for the baseline and override individual fields per run.

python
1model = LibreYOLO("LibreYOLO9c.pt")
2results = model.train(cfg="configs/yolo9_finetune.yaml")
3# Override individual fields:
4# results = model.train(cfg="configs/yolo9_finetune.yaml", epochs=50)

Gradient accumulation

Pass nbs (nominal batch size) to opt into gradient accumulation. The trainer steps the optimizer every nbs / batch forward passes, which lets you train at the recipe's reference batch size on smaller hardware.

python
1# Effective batch 64 on a single GPU that only fits batch=8
2model.train(data="coco128.yaml", batch=8, nbs=64)

Distributed training (DDP, experimental)

YOLO9 and RF-DETR support multi-GPU training through PyTorch DistributedDataParallel, but multi-GPU is outside the heavily tested v1.3.0 scope. Launch the training script with torchrun:

bash
1# 4-GPU node
2torchrun --nproc_per_node=4 train_yolo9.py
3
4# Multi-node - see PyTorch's torchrun docs for --nnodes / --rdzv_endpoint
train_yolo9.py
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreYOLO9c.pt")
4# Pass device="" (auto-detect) and let torchrun set the rank
5model.train(data="coco128.yaml", epochs=300, batch=16)

Distillation

New in v1.3.1YOLO9 and YOLOX only

Knowledge distillation trains a small student model against a larger frozen teacher, so the student learns from the teacher's intermediate features on top of its own labels. You get a model that runs at the student's speed but recovers some of the teacher's accuracy. Point distill_model at a teacher checkpoint and distillation turns on.

Distill a big model into a small one

python
1from libreyolo import LibreYOLO
2
3student = LibreYOLO("LibreYOLO9t.pt") # small student
4
5student.train(
6 data="coco.yaml",
7 epochs=100,
8 distill_model="LibreYOLO9c.pt", # the frozen teacher: this turns distillation ON
9 distill_loss_type="mgd", # "mgd" (default) or "cwd"
10 dis=2e-5, # global weight; omit to take the per-loss default
11)
bash
1libreyolo train model=LibreYOLO9t.pt data=coco.yaml epochs=100 \
2 distill-model=LibreYOLO9c.pt distill-loss-type=mgd dis=2e-5

During training the distillation term shows up as a distill loss component alongside the usual ones.

Arguments

ArgumentDefaultMeaning
distill_modelNoneTeacher checkpoint path. Setting it enables distillation.
disNoneGlobal distillation loss weight. Falls back to 2e-5 for MGD, 1.0 for CWD.
distill_loss_type"mgd"Feature loss: "mgd" or "cwd".
distill_mask_ratio0.65MGD only: fraction of spatial positions masked. Python API only.
distill_tau1.0CWD only: softmax temperature. Python API only.

Note the short name: the weight argument is dis, not distill_loss_weight. Three of these have CLI flags (distill-model, dis, distill-loss-type); distill_mask_ratio and distill_tau are reachable from Python or a training YAML only.

MGD or CWD

MGD (Masked Generative Distillation, the default) masks random spatial positions in the student features and asks it to regenerate the teacher's. Because it regresses raw feature magnitudes, its default weight is small: 2e-5.

CWD (Channel-Wise Distillation) turns each channel into a spatial distribution and matches them with a KL divergence. Normalizing per channel makes it scale invariant, so it copes better when teacher and student feature magnitudes are far apart. Its default weight is 1.0.

We do not publish a head-to-head accuracy comparison of the two, so treat MGD as the default and try CWD if the loss scale looks unhealthy.

Limits

  • Only the YOLO9 and YOLOX families can distill. Every other family raises at setup, because distillation needs feature tap points that only these two declare.
  • Teacher and student strides must match exactly. Both supported families use strides 8/16/32, so in practice you distill within a family, across sizes. Channel widths may differ freely: a 1x1 adapter bridges them.
  • Multi-GPU, mixed precision and gradient accumulation all work with distillation on.
  • Resuming works, and the adapter state is restored, but the teacher is not stored in the checkpoint: pass distill_model again when you resume.

Training Monitor

New in v1.3.1

Every training run, for every model family, writes machine-readable progress files into its run directory. You do not have to enable anything. libreyolo monitor serves them as a live dashboard, and because it only reads files it works equally well on a running job, a finished one, or one that crashed.

bash
1libreyolo monitor # watch runs/ on http://127.0.0.1:8420
2libreyolo monitor runs/train/exp # open one run directly
3libreyolo monitor --port 9000 --no-browser

Run artifacts

The two files below are the contract, and they are the reason this is useful to scripts and agents as well as to humans: you can poll a run's state without parsing logs.

FileWhat it is
status.jsonCurrent state of the run, rewritten atomically every epoch.
metrics.jsonlAppend-only, one JSON object per epoch. The full metric history.
train.logThe run log.

status.json always carries state (running, completed or failed), pid, progress, eta_seconds, and the current and best metric. If the run dies it records state: "failed" plus an error object with the exception type and message, so a crash is visible in the file rather than only in a terminal you have closed.

python
1import json, time
2
3def wait_for_run(run_dir):
4 while True:
5 status = json.load(open(f"{run_dir}/status.json"))
6 if status["state"] != "running":
7 return status
8 print(f'{status["progress"]:.0%} eta {status["eta_seconds"]:.0f}s '
9 f'best {status["best_metric"]}')
10 time.sleep(30)
11
12final = wait_for_run("runs/train/exp")
13if final["state"] == "failed":
14 print(final["error"]["type"], final["error"]["message"])
15else:
16 print(final["checkpoints"]["best"])

The monitor also exposes the same data over HTTP (/api/status, /api/metrics, /api/log, /api/images), so you can drive a dashboard of your own from it.

Profiling

New in v1.3.1

libreyolo profile measures where the time actually goes, in training and in inference. It is deliberately a measuring tool and nothing else: it never edits your config or tunes anything for you. It tells you what is slow and leaves the decision to you.

Profile training or inference

bash
1# training: is the GPU actually busy, or am I dataloader-bound?
2libreyolo profile run coco128 --weights LibreYOLO9t.pt --batch 16 --repeat 3
3
4# inference: latency percentiles and where they are spent
5libreyolo profile infer bus.jpg --weights LibreYOLO9t.pt --runs 200

profile infer reports p50, p90 and p99 latency, throughput, and a split across preprocess, forward and postprocess (NMS), plus a verdict on what is bounding you. That split is usually the punchline: a model that looks slow is often spending its time in NMS or in preprocessing rather than in the network.

Then look closer

Both commands write the same profile.json, and the analysis subcommands all read it, so you profile once and then interrogate the result from several angles.

SubcommandWhat it answers
summaryThe high-level diagnosis: utilisation, what is bounding you, the kernel mix.
phasesWhere the time went: forward, backward, dataload, optimizer.
kernelsWhich individual GPU kernels dominate.
opsThe framework view: which operations cost the most CPU time.
getPrint one metric, for use inside a script.
compareDiff two profiles, before and after a change.
what-ifEstimate the payoff of a change before you write it.
bash
1libreyolo profile summary runs/profile/prof/profile.json
2libreyolo profile kernels runs/profile/prof/profile.json --top 20
3libreyolo profile compare before.json after.json

Two practical notes. Every subcommand takes --json, which makes the profiler usable inside an automated optimize loop. And compare will only report statistical significance if both profiles were captured with --repeat 2 or higher: a single run is noisy enough to mislead you, especially when the job is launch-bound.

Validation

Run COCO-standard evaluation on a validation set. The heavily tested validation paths are single-GPU YOLO9 detection, RF-DETR detection, and RF-DETR segmentation.

python
1results = model.val(
2 data="coco128.yaml", # dataset config
3 batch=16,
4 imgsz=640,
5 conf=0.001, # low conf for mAP calculation
6 iou=0.6, # NMS IoU threshold
7 split="val", # "val", "test", or "train"
8 save_json=False, # save predictions as COCO JSON
9 verbose=True, # print per-class metrics
10 plots=True, # save validation plots (metrics, per-class AP, confusion matrix); alias for save_plots
11)
12
13print(f"mAP50: {results['metrics/mAP50']:.3f}")
14print(f"mAP50-95: {results['metrics/mAP50-95']:.3f}")

Validation results dict

By default, LibreYOLO uses COCO evaluation and returns precision, recall, AP/AR metrics, and per-image timing:

python
1{
2 "metrics/mAP50-95": 0.489, # COCO primary metric (AP@[.5:.95])
3 "metrics/mAP50": 0.721, # AP@0.5 (PASCAL VOC style)
4 "metrics/mAP75": 0.534, # AP@0.75 (strict)
5 "metrics/precision": 0.68,
6 "metrics/recall": 0.61,
7 "metrics/precision(B)": 0.68, # bbox aliases
8 "metrics/recall(B)": 0.61,
9 "metrics/mAP50(B)": 0.721,
10 "metrics/mAP50-95(B)": 0.489,
11 "metrics/mAP_small": 0.291,
12 "metrics/mAP_medium": 0.532,
13 "metrics/mAP_large": 0.648,
14 "metrics/AR1": 0.362, # Average Recall (max 1 det)
15 "metrics/AR10": 0.571,
16 "metrics/AR100": 0.601,
17 "metrics/AR_small": 0.387,
18 "metrics/AR_medium": 0.641,
19 "metrics/AR_large": 0.739,
20 "speed/preprocess_ms": 1.2,
21 "speed/inference_ms": 6.8,
22 "speed/postprocess_ms": 0.9,
23 "speed/total_ms": 8.9,
24 "speed/total_s": 12.3,
25 "speed/images_seen": 1382,
26}

Segmentation validation returns mask metrics with (M) suffixes alongside bbox metrics with (B) suffixes; OBB validation adds (OBB) metrics. Pose validation returns COCO keypoint metrics through PoseValidator. v1.3.0 adds validators for classify (top-1 / top-5), semantic (mIoU / pixel accuracy), point, and depth (zero-shot). Pass plots=True (or --save-plots on the CLI) to write metric, per-class AP, confusion-matrix, and sample plots to the run directory.

Export

Export PyTorch models to ONNX, TorchScript, TensorRT, OpenVINO, NCNN, CoreML, or (new in v1.3.0) TFLite for deployment. TensorRT now covers every model family. The heavily tested export paths remain single-GPU YOLO9 detection, RF-DETR detection, and RF-DETR segmentation.

Quick export

python
1# ONNX (default)
2model.export()
3
4# TorchScript
5model.export(format="torchscript")
6
7# TensorRT (requires NVIDIA GPU + TensorRT)
8model.export(format="tensorrt")
9
10# OpenVINO (optimized for Intel hardware)
11model.export(format="openvino")
12
13# NCNN (via PNNX)
14model.export(format="ncnn")
15
16# CoreML (.mlpackage, macOS runtime)
17model.export(format="coreml")
18
19# TFLite (RF-DETR detect/seg/pose + YOLO9 detect; experimental, needs Python 3.12+)
20model.export(format="tflite")

All export parameters

python
1path = model.export(
2 format="onnx", # "onnx", "torchscript", "tensorrt", "openvino", "ncnn", "coreml", or "tflite"
3 output_path="model.onnx", # output file (auto-generated if None)
4 imgsz=640, # input resolution (default: model's native); also accepts (h, w) for rectangular
5 opset=None, # ONNX opset (auto: 13, or 17 for wrappers that need it)
6 simplify=True, # run onnxsim graph simplification
7 dynamic=True, # enable dynamic batch axis (ONNX); TFLite requires static shapes
8 half=False, # export in FP16
9 batch=1, # batch size for static graph
10 device=None, # device to trace on (default: model's current device)
11 int8=False, # INT8 quantization: TensorRT, OpenVINO, or ONNX (YOLO9 detection only)
12 data=None, # calibration dataset for INT8
13 fraction=1.0, # fraction of calibration data to use
14 allow_download_scripts=False, # allow data.yaml download hooks during calibration
15 workspace=4.0, # TensorRT workspace size (GB)
16 min_batch=1, # TensorRT dynamic profile minimum batch
17 opt_batch=1, # TensorRT dynamic profile optimal batch
18 max_batch=8, # TensorRT dynamic profile maximum batch
19 hardware_compatibility="none", # TensorRT compatibility mode
20 gpu_device=0, # GPU device index for TensorRT
21 trt_config=None, # optional TensorRT YAML config path
22 compute_units="all", # CoreML routing: all, cpu_only, cpu_and_gpu, cpu_and_ne
23 nms=False, # embed NMS in the graph (ONNX YOLO9 detection, or CoreML)
24 iou=0.45, # embedded-NMS IoU threshold
25 conf=0.25, # embedded-NMS confidence threshold
26 max_det=300, # embedded-NMS max detections (ONNX only)
27 verbose=False, # verbose logging
28)

OpenVINO INT8 export additionally requires nncf. NCNN export writes a directory containing model.ncnn.param, model.ncnn.bin, and metadata.yaml. CoreML export writes a .mlpackage bundle, requires coremltools, and does not support INT8.

ONNX embedded NMS (YOLO9 detection)

New in v1.3.0: pass nms=True to bake NMS into an exported ONNX graph so the model emits final boxes directly. This is currently limited to the yolo9 family on the detect task (other families/tasks raise). It forces a fixed batch-1 graph (dynamic=False) and records nms / nms_conf / nms_iou / max_det in the ONNX metadata.

python
1model = LibreYOLO("LibreYOLO9c.pt")
2model.export(format="onnx", nms=True, conf=0.25, iou=0.45, max_det=300)

int8=True is now also supported for ONNX (in addition to TensorRT and OpenVINO), again limited to YOLO9 detection; it needs a calibration data= dataset.

TFLite (LiteRT) export

Experimental LibreYOLO has a TFLite export path built on onnx2tf. TFLite is the format of Google's LiteRT runtime (TensorFlow Lite was renamed LiteRT in 2024; the .tflite file format is unchanged). It is validated for RF-DETR detect / segment / pose and YOLO9 detect. It requires Python 3.12+ (the onnx2tf 2.4.x wheels do not target older Python) plus the optional extra libreyolo[tflite](onnx2tf>=2.4.3, onnx-graphsurgeon, onnx-simplifier). Export is FP32 and static-shape only (no half, int8, or dynamic yet).

bash
1pip install "libreyolo[tflite]" # Python 3.12+
python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreRFDETRs-seg.pt")
4model.export(format="tflite") # writes a .tflite file

For RF-DETR, the exporter rewrites each GridSample node into a TFLite-safe bilinear subgraph because onnx2tf's default lowering is numerically broken. In v1.3.0 the old runtime monkeypatches against onnx2tf were removed now that onnx2tf>=2.4.3 ships the RF-DETR fixes upstream; only the static ONNX-graph rewrite remains.

No TFLite runtime backend. LibreYOLO cannot load or run a .tflite file; this format is export-only. Run the exported model with Google's LiteRT runtime (pip install ai-edge-litert) on your target device. Avoid the older tflite-runtime package, which is no longer updated.

ONNX metadata

Exported ONNX files include embedded metadata:

KeyExample value
libreyolo_version"1.3.0"
model_family"yolox"
model_size"s"
nb_classes"80"
names'{"0": "person", "1": "bicycle", ...}'
imgsz"640"
dynamic"True"
half"False"

This metadata is automatically read back when loading the exported file with LibreYOLO("model.onnx").

TorchScript Inference

Run an exported .torchscript model through the same runtime-backend prediction API.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model.torchscript")
4
5result = model("image.jpg", conf=0.25, iou=0.45, save=True)
6print(result.boxes.xyxy)

ONNX Inference

Run inference using ONNX Runtime instead of PyTorch. Useful for deployment environments without PyTorch.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model.onnx")
4
5result = model("image.jpg", conf=0.25, iou=0.45, save=True)
6print(result.boxes.xyxy)

Auto-metadata

If the ONNX file was exported by LibreYOLO, class names and class count are read automatically from the embedded metadata:

python
1# Export with metadata
2model.export(format="onnx", output_path="model.onnx")
3
4# Load - names and nb_classes auto-populated
5onnx_model = LibreYOLO("model.onnx")
6print(onnx_model.names) # {0: "person", 1: "bicycle", ...}
7print(onnx_model.nb_classes) # 80

For ONNX files without metadata (e.g., exported by other tools), specify nb_classes manually:

python
1model = LibreYOLO("external_model.onnx", nb_classes=20)

Device selection

python
1# Auto-detect (CUDA if available, else CPU)
2model = LibreYOLO("model.onnx", device="auto")
3
4# Force CPU
5model = LibreYOLO("model.onnx", device="cpu")
6
7# Force CUDA
8model = LibreYOLO("model.onnx", device="cuda")

Prediction parameters

Runtime artifacts loaded through LibreYOLO() support the shared runtime prediction API:

python
1result = model(
2 "image.jpg",
3 conf=0.25,
4 iou=0.45,
5 imgsz=640,
6 classes=[0, 2],
7 max_det=300,
8 save=True,
9 output_path="output/annotated.jpg", # final file path when save=True
10 color_format="auto",
11)

Runtime backends do not expose PyTorch-only options such as tiling, overlap_ratio, or output_file_format.

Runtime backends also handle saving a little differently from the PyTorch wrappers: if you set output_path, pass a final file path, not a directory. If you omit it, the current backend default is under runs/detections/.

TensorRT Inference

Run inference using TensorRT for maximum throughput on NVIDIA GPUs. Requires CUDA plus the TensorRT Python bindings.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model.engine")
4
5result = model("image.jpg", conf=0.25, iou=0.45, save=True)
6print(result.boxes.xyxy)

TensorRT artifacts loaded through LibreYOLO() support the same core runtime prediction API as ONNX and OpenVINO, including the same file-path-only output_path behavior for save=True.

OpenVINO Inference

Run inference using OpenVINO, optimized for Intel CPUs, GPUs, and VPUs.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model_openvino/")
4
5result = model("image.jpg", conf=0.25, iou=0.45, save=True)
6print(result.boxes.xyxy)

OpenVINO directories loaded through LibreYOLO() read metadata.yaml when present and support the same core runtime prediction API.

NCNN Inference

Run inference using NCNN for lightweight deployment on CPU or Vulkan-capable GPU targets.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model_ncnn/")
4
5result = model("image.jpg", conf=0.25, iou=0.45, save=True)
6print(result.boxes.xyxy)

An NCNN export directory contains model.ncnn.param, model.ncnn.bin, and usually metadata.yaml.

CoreML Inference

Run an exported .mlpackage through CoreML on macOS. CoreML routes execution with compute_units instead of PyTorch device strings.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model.mlpackage", compute_units="all")
4
5result = model("image.jpg", conf=0.25, iou=0.45, save=True)
6print(result.boxes.xyxy)

Supported compute_units values are all, cpu_only, cpu_and_gpu, and cpu_and_ne.

CLI

Installing LibreYOLO registers a libreyolo command on your PATH (entry point in pyproject.toml). The CLI mirrors the Python API and accepts key=value syntax.

Subcommands

CommandPurpose
predictRun inference on images, directories, or videos
trainTrain a model on a dataset
valEvaluate a model on a dataset
exportExport to ONNX / TorchScript / TensorRT / OpenVINO / NCNN / CoreML / TFLite
labelLaunch LibreLabel, the local browser annotation tool (new in v1.3.1)
monitorServe a live dashboard over training runs (new in v1.3.1)
profileProfile training or inference, then analyse the result (new in v1.3.1)
uiLaunch a local drag-and-drop / paste browser inference UI
doctorRun pre-training dataset health checks (YOLO detection format)
checksPrint Python, torch, CUDA, GPU, and optional-package info
modelsList registered model families and CLI shortcut names
formatsList supported export formats
cfgPrint the default training configuration YAML
infoLoad a model and print resolved family, size, task, device, and classes
metadataInspect raw checkpoint metadata from a .pt file
versionPrint LibreYOLO + Python + torch versions

Model name shortcuts

The CLI accepts short names (yolo9-c) that resolve to weight filenames (LibreYOLO9c.pt) - discoverable via libreyolo models. You can also pass any explicit checkpoint path.

Common options

CommandImportant options
predictconf, iou, imgsz, classes, max_det, half, batch, tiling, overlap_ratio, output_file_format, project, name, exist_ok, face_detector
trainepochs, batch, imgsz, lr0, optimizer, scheduler, workers, seed, resume, amp, task, cache, lora, freeze, save_plots, allow_download_scripts, dry_run
valsplit, batch, imgsz, conf, iou, max_det, half, save_plots, data_dir, use_coco_eval, project, name, exist_ok, save_json, allow_download_scripts
exportformat, imgsz, batch, half, int8, dynamic, simplify, nms, conf, iou, max_det, opset, data, fraction, device, allow_download_scripts, verbose

Predict

bash
1# Flagship: YOLO9
2libreyolo predict model=yolo9-c source=image.jpg conf=0.25 save=true
3
4# Flagship: RF-DETR
5libreyolo predict model=rfdetr-s source=image.jpg save=true
6
7# Video - saved under runs/detect/predict*/
8libreyolo predict model=yolo9-c source=clip.mp4 save=true
9
10# Tiled inference for very large images
11libreyolo predict model=yolo9-c source=aerial.jpg tiling=true save=true
12
13# Gaze (requires a face detector)
14libreyolo predict model=LibreL2CSr50.pt source=portrait.jpg \
15 --face-detector path/to/face.pt save=true

Train

bash
1libreyolo train model=yolo9-c data=coco128.yaml epochs=300 batch=16 device=0
2
3# Dry-run prints the resolved config without launching training
4libreyolo train model=yolo9-c data=coco128.yaml --dry-run

Validate

bash
1libreyolo val model=runs/train/exp/weights/best.pt data=coco128.yaml split=val

Export

bash
1libreyolo export model=runs/train/exp/weights/best.pt format=onnx dynamic=true
2libreyolo export model=best.pt format=tensorrt half=true
3libreyolo export model=best.pt format=openvino int8=true data=coco128.yaml
4libreyolo export model=best.pt format=coreml

Export with embedded NMS and rectangular size

bash
1# Embed NMS into an ONNX YOLO9 detection graph
2libreyolo export model=yolo9-c format=onnx nms=true conf=0.25 iou=0.45 max_det=300
3
4# Rectangular export size (imgsz accepts a single value or two comma-separated dims)
5libreyolo export model=yolo9-c format=onnx imgsz=640,480
6
7# TFLite (Python 3.12+, libreyolo[tflite])
8libreyolo export model=rfdetr-s format=tflite

Local inference UI

libreyolo ui serves a local browser page where you drop, paste, or pick images, choose a model, and view results. It binds 127.0.0.1:8000 by default and auto-bumps the port if taken.

bash
1libreyolo ui # opens http://127.0.0.1:8000
2libreyolo ui --port 9000 --no-browser --device 0

Dataset health check

libreyolo doctor runs pre-training checks on a YOLO detection-format dataset and exits non-zero when errors are found (--strict also fails on warnings), so it can gate CI.

bash
1libreyolo doctor coco8.yaml
2libreyolo doctor --data coco8.yaml --strict --json
3libreyolo doctor coco8.yaml --fast --only labels # skip image decoding, run one check family

Machine-readable output

Every command accepts --json (structured stdout for piping into scripts or agents) and --quiet (suppress stderr progress lines). The core predict, train, val, and export commands also accept --help-json to dump their parameter schema as JSON.

bash
1libreyolo predict model=yolo9-c source=img.jpg --json | jq .
2
3libreyolo train --help-json > train_schema.json

API Reference

LibreYOLO (factory)

python
1LibreYOLO(
2 model_path: str,
3 *,
4 device: str = "auto",
5 task: str | None = None, # override only when a custom artifact is ambiguous
6 nb_classes: int | None = None, # mainly for external exported artifacts
7 compute_units: str = "all", # CoreML only: all, cpu_only, cpu_and_gpu, cpu_and_ne
8) -> model wrapper or runtime backend

Prefer official checkpoint filenames and exported artifact paths, then let the factory resolve the details. It handles PyTorch checkpoints, .onnx, .torchscript, .engine, .tensorrt, .mlpackage, OpenVINO directories containing model.xml, and NCNN directories containing model.ncnn.param plus model.ncnn.bin. The task argument is for ambiguous custom artifacts; otherwise resolution comes from checkpoint metadata, filename suffix, and family default.

Prediction (PyTorch model wrappers)

python
1model(
2 source, # image input (see supported formats)
3 *,
4 conf: float = 0.25,
5 iou: float = 0.45,
6 imgsz: int = None,
7 device: str = "auto",
8 classes: list[int] = None,
9 max_det: int = 300,
10 augment: bool = False,
11 save: bool = False,
12 batch: int = 1,
13 stream: bool = False,
14 vid_stride: int = 1,
15 show: bool = False,
16 output_path: str = None,
17 color_format: str = "auto",
18 tiling: bool = False,
19 overlap_ratio: float = 0.2,
20 output_file_format: str = None,
21) -> Results | list[Results] | Generator[Results, None, None]

Prediction (runtime backends)

python
1backend(
2 source,
3 *,
4 conf: float = 0.25,
5 iou: float = 0.45,
6 imgsz: int = None,
7 classes: list[int] = None,
8 max_det: int = 300,
9 save: bool = False,
10 batch: int = 1,
11 output_path: str = None, # final file path when save=True
12 color_format: str = "auto",
13) -> Results | list[Results]

If output_path is omitted for a runtime backend, the current default save location is runs/detections/.

Results

python
1result = Results(
2 boxes: Boxes | None,
3 orig_shape: tuple[int, int], # (height, width)
4 path: str | None,
5 names: dict[int, str],
6 masks: Masks | None = None,
7 keypoints: Keypoints | None = None,
8 probs: Probs | None = None,
9 obb: OBB | None = None,
10 gaze: Gaze | None = None,
11 speed: dict[str, float] | None = None,
12 track_id = None,
13 frame_idx: int | None = None,
14)
15
16len(result) # number of detections
17result.cpu() # copy with tensors on CPU
18result.cuda() # copy with tensors on CUDA
19result.numpy() # copy with numpy arrays
20result.summary() # list[dict] with boxes, masks, gaze, and track_id when present
21result.to_json() # JSON string from summary()

Boxes

python
1boxes = Boxes(boxes, conf, cls)
2
3boxes.xyxy # (N, 4) tensor - x1, y1, x2, y2
4boxes.xywh # (N, 4) tensor - cx, cy, w, h
5boxes.conf # (N,) tensor - confidence scores
6boxes.cls # (N,) tensor - class IDs
7boxes.id # (N,) track IDs when tracking, else None
8boxes.is_track # True when track IDs are attached
9boxes.data # (N, 6) [xyxy, conf, cls], or (N, 7) with track IDs
10
11len(boxes) # number of boxes
12boxes.cpu() # copy on CPU
13boxes.numpy() # copy as numpy arrays

Task payloads

python
1result.masks.data # segmentation masks, (N, H, W)
2result.masks.xy # list of mask contours in pixel coordinates
3result.masks.xyn # normalized mask contours
4
5result.keypoints.xy # pose keypoint coordinates
6result.keypoints.xyn # normalized keypoint coordinates
7result.keypoints.conf # keypoint confidence when present
8
9result.gaze.data # (N, 2): pitch, yaw in radians
10result.gaze.pitch_deg # pitch in degrees
11result.gaze.yaw_deg # yaw in degrees
12result.gaze.direction_3d # approximate 3D direction vectors

model.export()

python
1model.export(
2 format: str = "onnx", # "onnx", "torchscript", "tensorrt", "openvino", "ncnn", or "coreml"
3 *,
4 output_path: str | None = None,
5 imgsz: int | None = None,
6 opset: int | None = None, # auto: 13, or 17 for wrappers that need it
7 simplify: bool = True,
8 dynamic: bool = True,
9 half: bool = False,
10 batch: int = 1,
11 device: str | None = None,
12 int8: bool = False,
13 data: str | None = None, # calibration data for INT8
14 fraction: float = 1.0, # fraction of calibration data
15 allow_download_scripts: bool = False,
16 workspace: float = 4.0, # TensorRT workspace (GB)
17 min_batch: int = 1, # TensorRT dynamic profile minimum batch
18 opt_batch: int = 1, # TensorRT dynamic profile optimal batch
19 max_batch: int = 8, # TensorRT dynamic profile maximum batch
20 hardware_compatibility: str = "none",
21 gpu_device: int = 0,
22 trt_config = None, # optional TensorRT YAML config path
23 compute_units: str = "all", # CoreML only
24 nms: bool = False, # CoreML embedded NMS where supported
25 iou: float = 0.45, # CoreML embedded NMS IoU threshold
26 conf: float = 0.25, # CoreML embedded NMS confidence threshold
27 verbose: bool = False,
28) -> str # path to exported file or directory

model.val()

python
1model.val(
2 data: str = None, # path to data.yaml
3 batch: int = 16,
4 imgsz: int = None,
5 conf: float = 0.001,
6 iou: float = 0.6,
7 workers: int = 4,
8 allow_download_scripts: bool = False,
9 device: str = None,
10 split: str = "val", # "val", "test", or "train"
11 augment: bool = False,
12 save_json: bool = False,
13 verbose: bool = True,
14) -> dict

Returns (COCO evaluation, default):

python
1{
2 "metrics/mAP50-95": float, # COCO primary metric
3 "metrics/mAP50": float,
4 "metrics/mAP75": float,
5 "metrics/mAP_small": float,
6 "metrics/mAP_medium": float,
7 "metrics/mAP_large": float,
8 "metrics/AR1": float,
9 "metrics/AR10": float,
10 "metrics/AR100": float,
11 "metrics/AR_small": float,
12 "metrics/AR_medium": float,
13 "metrics/AR_large": float,
14}

model.train() (YOLO9)

python
1model.train(
2 data: str, # path to data.yaml (required)
3 *,
4 epochs: int = 300,
5 batch: int = 16,
6 imgsz: int = 640,
7 lr0: float = 0.01,
8 optimizer: str = "SGD",
9 device: str = "",
10 workers: int = 8,
11 seed: int = 0,
12 project: str = "runs/train",
13 name: str = "yolo9_exp",
14 exist_ok: bool = False,
15 resume: bool = False,
16 amp: bool = True,
17 patience: int = 50,
18 allow_download_scripts: bool = False,
19 callbacks = None,
20) -> dict

Returns the standard LibreYOLO training dict with final_loss, best_mAP50, best_mAP50_95, best_epoch, save_dir, best_checkpoint, and last_checkpoint.

model.train() (RF-DETR)

python
1model.train(
2 data: str, # path to data.yaml
3 epochs: int = 100,
4 batch_size: int = 4,
5 lr: float = 1e-4,
6 output_dir: str = "runs/train",
7 resume: str = None,
8 **kwargs, # additional RF-DETR training args
9) -> dict

Additional experimental trainers exist for YOLO-NAS, D-FINE, DEIM, DEIMv2, EC, PicoDet, RT-DETRv2/v4, and RTMDet, plus the new classification (MobileNetV4, ConvNeXt, EfficientNetV2, DINOv2), semantic-segmentation (DINOv2), and point (FOMO) families. They follow the same model.train(data="...yaml", ...) shape but their defaults and experimental gates are family-specific.

Runtime artifact loading

Load exported artifacts through LibreYOLO(), the same way you load PyTorch checkpoints. The factory chooses ONNX Runtime, TorchScript, TensorRT, OpenVINO, NCNN, or CoreML from the path:

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("model.onnx")
4model = LibreYOLO("model.torchscript")
5model = LibreYOLO("model.engine")
6model = LibreYOLO("model_openvino/")
7model = LibreYOLO("model_ncnn/")
8model = LibreYOLO("model.mlpackage", compute_units="all")

Advanced integrations can reach lower-level runtime modules, but normal application code should stay on the factory path.

ValidationConfig

python
1from libreyolo import ValidationConfig
2
3config = ValidationConfig(
4 data="coco128.yaml",
5 data_dir=None, # override dataset root directory
6 split="val", # "val", "test", or "train"
7 batch_size=16,
8 imgsz=640,
9 conf_thres=0.001,
10 iou_thres=0.6,
11 max_det=300,
12 iou_thresholds=( # mAP IoU sweep
13 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95,
14 ),
15 device="auto",
16 save_dir=None,
17 save_json=False,
18 verbose=True,
19 num_workers=4,
20 half=False,
21 augment=False, # test-time augmentation (TTA)
22 allow_download_scripts=False,
23 # Pose-only fields (PoseValidator)
24 keypoints_json=None,
25 images_dir=None,
26 oks_sigmas=None,
27)
28
29# Load/save YAML
30config = ValidationConfig.from_yaml("config.yaml")
31config.to_yaml("config.yaml")

Architecture Guide

This section is for contributors who want to understand the codebase internals.

Base class design

PyTorch model families inherit from BaseModel in libreyolo/models/base/model.py. Subclasses implement these abstract methods:

MethodPurpose
_init_model()Build and return the nn.Module
_get_available_layers()Return layer-name to module mapping
_get_preprocess_numpy()Return the NumPy preprocessor used for export / calibration
_preprocess()Image to tensor conversion
_forward()Model forward pass
_postprocess()Raw output to detection dicts

BaseModel provides the shared wrapper behavior: prediction, export, validation, size/name metadata, and training helpers. The actual single-image, batch, and tiled inference flow lives in libreyolo/models/base/inference.py, while deployment runtimes live under libreyolo/backends/.

Package structure

text
1libreyolo/
2 __init__.py # Public API exports + deprecated-alias resolver
3 tasks.py # Task types, suffix conventions, resolution rules
4 assets/parkour.jpg # SAMPLE_IMAGE
5 models/
6 __init__.py # LibreYOLO() factory + model registry bootstrap
7 base/
8 model.py # BaseModel - shared wrapper behaviour
9 inference.py # Shared prediction pipeline (image/dir/video/tiled)
10 yolox/ # LibreYOLOX (detect)
11 yolo9/ # LibreYOLO9 (detect)
12 yolo9_e2e/ # LibreYOLO9E2E (detect)
13 yolonas/ # LibreYOLONAS (detect, pose)
14 dfine/ # LibreDFINE (detect)
15 deim/ # LibreDEIM (detect)
16 deimv2/ # LibreDEIMv2 (detect)
17 rtdetr/ # LibreRTDETR (detect)
18 rtdetrv2/ # LibreRTDETRv2 (detect)
19 rtdetrv4/ # LibreRTDETRv4 (detect)
20 rfdetr/ # LibreRFDETR (detect, segment, pose, obb) - lazy-loaded
21 ec/ # LibreEC / EdgeCrafter (detect, pose, segment)
22 picodet/ # LibrePICODET (detect)
23 rtmdet/ # LibreRTMDet (detect)
24 dinov2/ # LibreDINOv2 (semantic, classify) - lazy-loaded
25 mobilenetv4/ # LibreMobileNetV4 (classify)
26 convnext/ # LibreConvNeXt (classify)
27 efficientnetv2/ # LibreEfficientNetV2 (classify)
28 depth_anything/ # LibreDepthAnythingV2 (depth)
29 fomo/ # LibreFOMO (point)
30 l2cs/ # LibreL2CS (gaze, inference-only)
31 backends/
32 base.py
33 onnx.py # ONNX Runtime loader
34 torchscript.py # TorchScript loader
35 tensorrt.py # TensorRT loader
36 openvino.py # OpenVINO loader
37 ncnn.py # NCNN loader
38 coreml.py # CoreML loader
39 export/
40 exporter.py # BaseExporter and format registry
41 onnx.py / torchscript.py / tensorrt.py / openvino.py / ncnn.py / coreml.py
42 config.py / calibration.py
43 training/
44 trainer.py # Shared trainer scaffolding
45 config.py # TrainConfig dataclass (single source of truth)
46 augment.py / callbacks.py / distributed.py / ema.py / scheduler.py
47 artifacts.py / train_config.yaml
48 # Per-family trainers live in models/<family>/trainer.py
49 validation/
50 config.py # ValidationConfig
51 base.py / preprocessors.py
52 detection_validator.py # DetectionValidator, SegmentationValidator
53 pose_validator.py # PoseValidator
54 coco_evaluator.py # COCOEvaluator
55 tracking/
56 tracker.py # ByteTracker
57 config.py # TrackConfig
58 kalman_filter.py / matching.py / strack.py
59 cli/
60 __init__.py # libreyolo entrypoint (Typer app)
61 commands/ # predict / train / val / export / special
62 aliases.py / config.py / parsing.py / output.py / errors.py
63 utils/
64 results.py # Results, Boxes, Masks, Keypoints, Probs, OBB, Gaze
65 image_loader.py # Unified image loading
66 video.py # VideoSource, VideoWriter, video inference loop
67 general.py # Path helpers, NMS, tiling utilities
68 download.py / drawing.py / logging.py / predict_args.py
69 serialization.py / box_ops.py
70 data/
71 dataset.py / pose_dataset.py / utils.py / yolo_coco_api.py
72 config/
73 datasets/ # Built-in dataset YAML configs (coco8, coco128, coco5000, coco, etc.)
74 export/ # TensorRT default YAML

Adding a new model family

  1. 1Create libreyolo/models/newmodel/model.py with a class inheriting BaseModel
  2. 2Set FAMILY, FILENAME_PREFIX, INPUT_SIZES, SUPPORTED_TASKS, and DEFAULT_TASK as needed
  3. 3Implement registry hooks such as can_load(), detect_size(), detect_nb_classes(), and detect_size_from_filename()
  4. 4Implement the model init, preprocess, forward, postprocess, train, and validation hooks that the family needs
  5. 5Create the supporting network and utilities under libreyolo/models/newmodel/
  6. 6Add the import to libreyolo/models/__init__.py; subclass registration happens when the import runs
  7. 7Export the class from libreyolo/__init__.py
  8. 8(Optional) Override val_preprocessor_class if validation preprocessing differs from the standard path

Export architecture

User code should export through model.export(...). Internally, BaseExporter in libreyolo/export/exporter.py owns the format registry, and concrete exporters register themselves through subclass registration.

python
1from libreyolo import LibreYOLO
2
3model = LibreYOLO("LibreYOLO9c.pt")
4model.export(format="onnx")

To add a new export format, implement a new BaseExporter subclass with a unique format_name and import it from libreyolo/export/exporter.py so the registry is populated.

Dataset Format

Every task loads through one data.yaml. Detection, instance segmentation, and OBB accept two interchangeable label formats — YOLO TXT or native COCO JSON — and the loader picks the right one from the config. Pose, semantic segmentation, depth, and classification each add a small format of their own. The table maps every task to its layout.

Formats by task

TaskData layoutLabels
Detectiondata.yaml + labels/*.txt, or COCO JSONOne box per line
Instance segmentationdata.yaml + polygon .txt, or COCO JSONPolygon per line (TXT) / polygons + RLE (COCO)
OBBdata.yaml + rotated-box .txt, or COCO JSONOne rotated box per line
Posedata.yaml + .txt + kpt_shape/flip_idxBox + keypoints per line
Semantic segmentationdata.yaml + masks_dir/ PNGsPer-pixel class ID (255 = ignore)
Depthdata.yaml + depths_dir/ mapsPer-pixel depth (0 = invalid)
ClassificationImageFolder (train/<class>/)Folder name = class

data.yaml structure

The shared contract for detection, segmentation, OBB, and pose. train/val/test may be a directory, a .txt file list (one image path per line), or a list of paths. nc is optional — when omitted it is inferred from names.

data.yaml
1path: /absolute/path/to/dataset # dataset root
2train: images/train # dir, .txt file list, or list of paths
3val: images/val
4test: images/test # optional
5
6nc: 80 # optional; inferred from names if absent
7names: ["person", "bicycle", "car", "..."]

Configs resolve from an explicit path, the working directory, then the built-ins under libreyolo/config/datasets/. Roots default under ~/datasets; override with LIBREYOLO_DATASETS_DIR.

YOLO TXT labels

The default layout: one .txt per image under labels/, mirroring the images/ tree with the same file stem. All coordinates are normalized to [0, 1].

text
1dataset/
2 images/train/img001.jpg
3 labels/train/img001.txt # same stem as the image
text
1# Detection one box per line
2<class_id> <cx> <cy> <w> <h>
3
4# Segmentation one polygon per line (box derived from the vertices)
5<class_id> <x1> <y1> <x2> <y2> ... <xn> <yn>
6
7# Pose box, then K keypoints (needs kpt_shape / flip_idx below)
8<class_id> <cx> <cy> <w> <h> <kx1> <ky1> <v1> ... <kxK> <kyK> <vK>
9
10# OBB four rotated-box corners
11<class_id> <x1> <y1> <x2> <y2> <x3> <y3> <x4> <y4>
data.yaml (pose)
1kpt_shape: [17, 3] # K keypoints, 3 values each: x, y, visibility
2flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]

Native COCO JSON

Detection, segmentation, and OBB also load COCO JSON directly — add an annotations: block mapping each split to its JSON file. train/val then point at image directories (not .txt lists). Requires pycocotools; class names come from the JSON categories, so nc/names are optional.

data.yaml (COCO)
1path: dataset
2train: images/train # image directory
3val: images/val
4annotations:
5 train: annotations/train.json # COCO instances JSON
6 val: annotations/val.json

The same switch feeds YOLO9, RF-DETR, DEIM, and D-FINE training and the detection, OBB, and pose validators. A COCO layout with annotations/instances_train2017.json on disk is also detected automatically, without the annotations: key.

Which segmentation format? A YOLO polygon row is a single ring per instance — it cannot express a hole or a split (multi-part) mask. COCO JSON keeps every polygon of an instance and decodes RLE masks, holes included. Use COCO JSON when instances have holes or disconnected parts; either format is fine for simple blobs. Crowd annotations (iscrowd: 1) are skipped.

Semantic segmentation masks

Pair each image with a single-channel mask whose pixel values are class IDs; 255 marks ignored pixels. masks_dir is substituted for images in each path (default masks), and masks must be lossless (PNG) with the same stem as their image. Optional label_mapping remaps source IDs to train IDs (unmapped values become ignore). Omit masks_dir to rasterize masks from YOLO polygon labels at load time, with a background class appended.

text
1dataset/
2 images/train/scene001.jpg
3 masks/train/scene001.png # single-channel class IDs, 255 = ignore
data.yaml (semantic)
1path: /path/to/dataset
2train: images/train
3val: images/val
4masks_dir: masks
5nc: 3
6names: ["road", "building", "vegetation"]

Depth maps

Pair each image with a single-channel depth map under depths_dir (default depths). 16-bit PNG/TIF is divided by depth_scale (default 256.0); .npy float files are used as-is. Zero, negative, and non-finite pixels are invalid. An optional depth_stem_suffix and a *_mask validity map are honored automatically. Depth is validation-only in v1.3.0.

data.yaml (depth)
1path: /path/to/dataset
2val: images/val
3depths_dir: depths
4depth_scale: 256.0 # 16-bit PNG encoding: value / 256 = depth

Classification

Classification uses an ImageNet-style ImageFolder tree instead of a data.yaml — see Classification for the layout. data= takes a dataset root, a .zip URL, or a known name.

Built-in datasets

Configs ship under libreyolo/config/datasets/. Download behavior differs per config: URL-backed sets fetch on first use, script-backed sets need allow_download_scripts=True, and a few must be placed locally.

ConfigTaskDownload
coco8Detection (8 images)Automatic
coco128Detection (128 images)Automatic
coco5000DetectionScript — allow_download_scripts=True
coco / coco-val-onlyDetection (full)Script — allow_download_scripts=True
coco8-pose / coco-posePoseScript — allow_download_scripts=True
cocostuffSemantic (182 classes)Manual — place locally
python
1results = model.val(data="coco8.yaml") # auto-downloads
2results = model.train(data="coco128.yaml", epochs=10) # auto-downloads
3model.train(data="coco8-pose.yaml", allow_download_scripts=True) # script config