These are the docs for v1.3.0, the previous release. The latest docs are v1.3.1, available from the version menu.
Two companion guides go deeper on specialized topics: the LibreVLM guide covers open-vocabulary detection that wraps vision-language models like Qwen3-VL and Florence-2, and the experimental tasks guide covers additional experimental workflows, including LoRA / DoRA fine-tuning. Classification, oriented boxes, and pose are also documented in their own sections below.
Introduction
v1.3.0 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.0 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.0. Use them if you have a specific reason.
1 from libreyolo import LibreYOLO, SAMPLE_IMAGE 2 3 # Default: YOLO9 detection 4 model = LibreYOLO("LibreYOLO9c.pt") 5 result = model(SAMPLE_IMAGE, conf=0.25, save=True) 6 7 print(f"Detected {len(result)} objects") 8 print(result.boxes.xyxy) 9 print(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
- Ultralytics-style
libreyolocommand-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:
LibreDAMOYOLOraisesAttributeError, and DAMO-YOLO checkpoints are rejected on load. - YOLO9 is detect-only. The
-seg,-pose,-cls,-obb, and-semYOLO9 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
LibreDINOv2family; depth moved to the newLibreDepthAnythingV2family. - TFLite export needs Python 3.12+ (onnx2tf wheel constraint). The onnx2tf floor was raised to
>=2.4.3and the old onnx2tf runtime patches were removed.
Compatibility
Use this matrix as the quick v1.3.0 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 family | v1.3.0 status | Inference | Training | Detect | Segment | Semantic | Classify | Pose | OBB | Depth | Point | Gaze | ONNX | TorchScript | TensorRT | OpenVINO | NCNN | CoreML | TFLite |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| YOLO9 | Validated detect, single GPU | ✓ | ✓ | ✓ | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | exp |
| RF-DETR | Validated detect + segment; pose / OBB preview | ✓ | ✓ | ✓ | ✓ | Not currently supported | Not currently supported | prev | prev | Not currently supported | Not currently supported | Not currently supported | ✓ | ✓ | ✓ | ✓ | Not currently supported | exp | exp |
| YOLOX | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | exp | exp | Not currently supported |
| YOLO9-E2E | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported |
| YOLO-NAS | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | exp | Not currently supported | Not currently supported |
| D-FINE | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | exp | Not currently supported | Not currently supported |
| DEIM | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | exp | Not currently supported | Not currently supported |
| DEIMv2 | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | exp | Not currently supported | Not currently supported |
| RT-DETR | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | exp | exp | exp | Not currently supported |
| RT-DETRv2 | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| RT-DETRv4 | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| PicoDet | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| RTMDet | Experimental | exp | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| EC | Experimental | exp | exp | exp | exp | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| DINOv2 | New, experimental (needs transformers) | exp | exp | Not currently supported | Not currently supported | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| MobileNetV4 | New, experimental classifier (Apache) | exp | exp | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| ConvNeXt | New, experimental classifier (Apache) | exp | exp | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| EfficientNetV2 | New, experimental classifier (Apache) | exp | exp | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| Depth Anything V2 | New, experimental; no export | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| FOMO | New, experimental; no auto-download | exp | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported |
| L2CS | Experimental, inference-only | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | exp | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not currently supported | Not 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
1 pip install libreyolo
These docs track the upcoming v1.3.0 release. Until v1.3.0 is published to PyPI, use a source install for the features documented on this page.
From source
1 git clone https://github.com/LibreYOLO/libreyolo.git 2 cd libreyolo 3 git checkout dev 4 pip install -e .
Optional dependencies
1 # ONNX export and inference 2 pip install libreyolo[onnx] 3 # or: pip install onnx onnxsim onnxruntime 4 5 # RT-DETR compatibility extra (currently no extra packages) 6 pip install libreyolo[rtdetr] 7 8 # RF-DETR support 9 pip install libreyolo[rfdetr] 10 # or: pip install transformers 11 12 # TensorRT export and inference (NVIDIA GPU) 13 pip 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) 18 pip install libreyolo[openvino] 19 # INT8 export also needs: pip install nncf 20 21 # NCNN export and inference 22 pip install libreyolo[ncnn] 23 # or: pip install pnnx ncnn 24 25 # ByteTrack API compatibility extra 26 pip install libreyolo[tracking] 27 # Tracking dependencies are part of the base install in v1.3.0. 28 29 # CoreML export and inference (macOS only for runtime) 30 pip install libreyolo[coreml] 31 # or: pip install coremltools 32 33 # L2CS gaze optional auto-download helper 34 pip install libreyolo[gaze] 35 # Optional parity with the upstream RetinaFace-based L2CS pipeline 36 pip install libreyolo[gaze-retinaface] 37 38 # Install every optional LibreYOLO extra 39 pip install libreyolo[all]
If using uv, the most reliable path is an isolated venv per extra:
1 # ONNX environment 2 uv venv .venv-onnx 3 uv pip install --python .venv-onnx/bin/python -e '.[onnx]' 4 5 # RT-DETR environment 6 uv venv .venv-rtdetr 7 uv 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
1 from libreyolo import LibreYOLO, SAMPLE_IMAGE 2 3 # Use the official checkpoint name and let the factory resolve the details 4 model = LibreYOLO("LibreYOLO9c.pt") 5 6 # Run on a single image (SAMPLE_IMAGE ships with the package) 7 result = model(SAMPLE_IMAGE) 8 9 print(f"Found {len(result)} objects") 10 print(result.boxes.xyxy) # bounding boxes (N, 4) 11 print(result.boxes.conf) # confidence scores (N,) 12 print(result.boxes.cls) # class IDs (N,)
RF-DETR - transformer flagship
1 from libreyolo import LibreYOLO, SAMPLE_IMAGE 2 3 # Same factory, same call shape - just point at an RF-DETR checkpoint 4 model = LibreYOLO("LibreRFDETRs.pt") 5 result = model(SAMPLE_IMAGE) 6 7 print(f"Found {len(result)} objects") 8 print(result.boxes.xyxy)
Save annotated output
1 result = model(SAMPLE_IMAGE, save=True) 2 print(result.saved_path) # e.g. runs/detect/predict/parkour.jpg
Process a directory
1 results = model("images/", save=True, batch=4) 2 for 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.0.
LibreYOLO v1.3.0 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| Size | Code | Input size | Use case | Detection checkpoint |
|---|---|---|---|---|
| Tiny | "t" | 640 | Fast inference | LibreYOLO9t.pt |
| Small | "s" | 640 | Balanced | LibreYOLO9s.pt |
| Medium | "m" | 640 | Higher accuracy | LibreYOLO9m.pt |
| Compact | "c" | 640 | Best accuracy | LibreYOLO9c.pt |
YOLO9 is detection-only in v1.3.0. The non-detect flagship variants (including the old -seg checkpoints) were removed; for segmentation use RF-DETR or EdgeCrafter below.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreYOLO9c.pt") # detection
RF-DETR - transformer flagship
Recommended| Size | Code | Input size | Use case | Detection checkpoint |
|---|---|---|---|---|
| Nano | "n" | 384 | Edge | LibreRFDETRn.pt |
| Small | "s" | 512 | Balanced | LibreRFDETRs.pt |
| Medium | "m" | 576 | Higher accuracy | LibreRFDETRm.pt |
| Large | "l" | 704 | Maximum accuracy | LibreRFDETRl.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.
1 from libreyolo import LibreYOLO 2 3 model = 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.0. 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.
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).
| Family | Status | Task | Checkpoints |
|---|---|---|---|
| MobileNetV4 | Experimental | classify | LibreMobileNetV4s-cls.pt, LibreMobileNetV4m-cls.pt, LibreMobileNetV4l-cls.pt |
| ConvNeXt | Experimental | classify | LibreConvNeXtt-cls.pt, LibreConvNeXts-cls.pt, LibreConvNeXtb-cls.pt |
| EfficientNetV2 | Experimental | classify | LibreEfficientNetV2b0-cls.pt, LibreEfficientNetV2b1-cls.pt, LibreEfficientNetV2b2-cls.pt, LibreEfficientNetV2b3-cls.pt |
| DINOv2 | Experimental | semantic, classify | LibreDINOv2n.pt, LibreDINOv2s.pt, LibreDINOv2m.pt, LibreDINOv2l.pt, LibreDINOv2n-cls.pt, LibreDINOv2s-cls.pt, LibreDINOv2m-cls.pt, LibreDINOv2l-cls.pt |
| Depth Anything V2 | Experimental | depth | LibreDepthAnythingV2s-depth.pt, LibreDepthAnythingV2b-depth.pt, LibreDepthAnythingV2l-depth.pt, LibreDepthAnythingV2g-depth.pt |
| FOMO | Experimental | point | LibreFOMOs-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
| Family | Status | Tasks | Checkpoints |
|---|---|---|---|
| L2CS | Experimental | gaze (inference-only) - see Gaze Estimation | LibreL2CSr50.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:
1 from libreyolo import LibreYOLO 2 3 # Default: YOLO9 detection 4 model = LibreYOLO("LibreYOLO9c.pt") 5 6 # Flagship transformer: RF-DETR 7 model = LibreYOLO("LibreRFDETRs.pt") 8 model = LibreYOLO("LibreRFDETRs-seg.pt") # validated segmentation 9 10 # New in v1.3.0 11 model = LibreYOLO("LibreMobileNetV4s-cls.pt") # classification (Apache, ImageNet-1k) 12 model = LibreYOLO("LibreDINOv2n.pt") # semantic segmentation 13 model = LibreYOLO("LibreDepthAnythingV2s-depth.pt") # monocular depth 14 model = LibreYOLO("LibreFOMOs-point.pt") # point localization (local weights) 15 16 # Exported deployment formats 17 model = LibreYOLO("model.onnx") # ONNX Runtime 18 model = LibreYOLO("model.engine") # TensorRT 19 model = LibreYOLO("model.mlpackage") # CoreML (macOS) 20 model = LibreYOLO("model_openvino/") # OpenVINO (directory) 21 model = 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.0.
Tasks & Filenames
LibreYOLO uses a uniform filename convention so the factory can detect family, size, and task from the checkpoint name alone:
1 Libre<FAMILY><size>[-<task>].pt
Task suffixes
| Task | Canonical name | Filename suffix | Owned by |
|---|---|---|---|
| Detection | "detect" | (none - implicit) | most families (default) |
| Instance segmentation | "segment" | -seg | RF-DETR, EdgeCrafter |
| Semantic segmentation | "semantic" | -sem | DINOv2 |
| Pose estimation | "pose" | -pose | YOLO-NAS, EdgeCrafter, RF-DETR (preview) |
| Oriented boxes | "obb" | -obb | RF-DETR (preview) |
| Classification | "classify" | -cls | MobileNetV4, ConvNeXt, EfficientNetV2, DINOv2 |
| Monocular depth | "depth" | -depth | Depth Anything V2 |
| Point localization | "point" | -point | FOMO |
| Gaze estimation | "gaze" | -gaze | L2CS |
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:
1 explicit task= → checkpoint["task"] → filename suffix → family default
1 from libreyolo import LibreYOLO 2 3 # 1. Filename suffix decides → segment 4 model = LibreYOLO("LibreRFDETRs-seg.pt") 5 6 # 2. Override regardless of filename 7 model = LibreYOLO("custom_weights.pt", task="segment") 8 9 # 3. Detection is implicit 10 model = LibreYOLO("LibreYOLO9c.pt") # task="detect"
Per-family task support
| Family | v1.3.0 status | Default | Supported tasks |
|---|---|---|---|
| YOLO9 | detect single-GPU heavily tested; multi-GPU experimental | detect | detect |
| RF-DETR | detect and segment single-GPU heavily tested; pose and OBB research preview | detect | detect, segment, pose, obb |
| YOLOX | experimental | detect | detect |
| YOLO9-E2E | experimental | detect | detect |
| YOLO-NAS | experimental | detect | detect, pose |
| D-FINE / DEIM / DEIMv2 | experimental | detect | detect |
| RT-DETR / RT-DETRv2 / RT-DETRv4 | experimental | detect | detect |
| PicoDet / RTMDet | experimental | detect | detect |
| EdgeCrafter (EC) | experimental | detect | detect, pose, segment |
| DINOv2 | new, experimental | semantic | semantic, classify |
| MobileNetV4 / ConvNeXt / EfficientNetV2 | new, experimental | classify | classify |
| Depth Anything V2 | new, experimental | depth | depth |
| FOMO | new, experimental | point | point |
| L2CS | experimental | gaze | gaze (inference-only) |
Examples
1 # Detection (implicit) 2 LibreYOLO9c.pt 3 LibreRFDETRs.pt 4 LibreRTDETRr50.pt 5 6 # Instance segmentation (-seg) 7 LibreRFDETRs-seg.pt 8 LibreECm-seg.pt 9 10 # Semantic segmentation (-sem) 11 LibreDINOv2n.pt # semantic is DINOv2's default; -sem optional 12 13 # Pose (-pose) 14 LibreYOLONASn-pose.pt 15 LibreECs-pose.pt 16 LibreRFDETRx-pose.pt # preview; size x only 17 18 # Oriented boxes (-obb) 19 LibreRFDETRn-obb.pt # preview 20 21 # Classification (-cls) 22 LibreMobileNetV4s-cls.pt 23 LibreConvNeXtt-cls.pt 24 LibreEfficientNetV2b0-cls.pt 25 LibreDINOv2n-cls.pt # DINOv2 linear probe 26 27 # Depth (-depth) 28 LibreDepthAnythingV2s-depth.pt 29 30 # Point (-point) 31 LibreFOMOs-point.pt 32 33 # Gaze (-gaze optional; only task for L2CS) 34 LibreL2CSr50.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.0.
Basic prediction
1 result = model("image.jpg")
All prediction parameters
1 result = 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:
1 # File path (string or pathlib.Path) 2 result = model("photo.jpg") 3 result = model(Path("photo.jpg")) 4 5 # URL 6 result = model("https://example.com/image.jpg") 7 result = model("s3://bucket/image.jpg") 8 result = model("gs://bucket/image.jpg") 9 10 # PIL Image 11 from PIL import Image 12 img = Image.open("photo.jpg") 13 result = model(img) 14 15 # NumPy array (HWC or CHW, RGB or BGR, uint8 or float32) 16 import numpy as np 17 arr = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8) 18 result = model(arr) 19 20 # OpenCV (BGR) - specify color_format 21 import cv2 22 frame = cv2.imread("photo.jpg") 23 result = model(frame, color_format="bgr") 24 25 # PyTorch tensor (CHW or NCHW) 26 import torch 27 tensor = torch.randn(3, 640, 640) 28 result = model(tensor) 29 30 # Raw bytes 31 with open("photo.jpg", "rb") as f: 32 result = model(f.read()) 33 34 # BytesIO 35 from io import BytesIO 36 result = model(BytesIO(open("photo.jpg", "rb").read())) 37 38 # Directory of images 39 results = model("images/", batch=4)
Working with results
Every prediction returns a Results object (or a list of them for directories):
1 result = model("image.jpg") 2 3 # Number of detections 4 len(result) # e.g., 5 5 6 # Bounding boxes in xyxy format (x1, y1, x2, y2) 7 result.boxes.xyxy # tensor of shape (N, 4) 8 9 # Bounding boxes in xywh format (center_x, center_y, width, height) 10 result.boxes.xywh # tensor of shape (N, 4) 11 12 # Confidence scores 13 result.boxes.conf # tensor of shape (N,) 14 15 # Class IDs 16 result.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. 20 result.boxes.data # shape (N, 6), or (N, 7) when tracked 21 22 # Metadata 23 result.orig_shape # (height, width) of original image 24 result.path # source file path (or None) 25 result.names # {0: "person", 1: "bicycle", ...} 26 27 # Move to CPU / convert to numpy 28 result_cpu = result.cpu() 29 boxes_np = result.boxes.numpy()
Class filtering
Filter detections to specific class IDs:
1 # Only detect people (class 0) and cars (class 2) 2 result = 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.
1 import numpy as np 2 from libreyolo import LibreYOLO 3 4 model = LibreYOLO("LibreYOLO9c.pt") 5 6 frames = [ 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 12 results = model(frames, batch=4) # list/tuple -> true batched inference 13 for 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.
1 meta = 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.0. It rejects segmentation masks, and it cannot be combined with augment=True.
1 result = 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 9 result.tiled # True 10 result.num_tiles # number of tiles used 11 result.saved_path # output directory when save=True 12 result.tiles_path # directory containing per-tile crops 13 result.grid_path # grid visualization image
When save=True with tiling, LibreYOLO saves:
final_image.jpg- full image with all merged detections drawngrid_visualization.jpg- image showing tile grid overlaytiles/- individual tile cropsmetadata.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
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreYOLO9c.pt") 4 results = 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.
1 for result in model("long_clip.mp4", stream=True): 2 print(f"frame {result.frame_idx}: {len(result)} detections")
Frame subsampling
1 # Process every 2nd frame (halves compute and saved fps) 2 results = model("clip.mp4", vid_stride=2, save=True)
Live preview
1 # Display annotated frames in an OpenCV window while processing 2 results = 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:
1 from libreyolo import LibreYOLO 2 from libreyolo.utils.video import VideoSource, VideoWriter 3 4 model = LibreYOLO("LibreYOLO9c.pt") 5 6 with 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.0.
Install
1 pip install libreyolo[tracking] # compatibility extra; tracking deps ship in base dev install
Video tracking helper
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreYOLO9c.pt") 4 5 for 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
1 from libreyolo import LibreYOLO, ByteTracker 2 from libreyolo.utils.video import VideoSource 3 4 model = LibreYOLO("LibreYOLO9c.pt") 5 tracker = ByteTracker() 6 7 with 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
1 from libreyolo import ByteTracker, TrackConfig 2 3 cfg = 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 ) 15 tracker = ByteTracker(config=cfg)
Reset between clips
1 tracker.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).
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreYOLO9c.pt") 4 5 for 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.
1 from libreyolo import LibreYOLO, OCSortConfig 2 3 cfg = 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 13 model = LibreYOLO("LibreYOLO9c.pt") 14 for result in model.track("clip.mp4", tracker_config=cfg, save=True): 15 print(result.frame_idx, result.track_id)
Segmentation
v1.3.0 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.0 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.0.
Run segmentation
1 from libreyolo import LibreYOLO 2 3 # RF-DETR segmentation, the heavily tested segmentation path 4 model = LibreYOLO("LibreRFDETRs-seg.pt") 5 result = model("photo.jpg") 6 7 # EdgeCrafter segmentation is also available but experimental 8 # model = LibreYOLO("LibreECs-seg.pt") 9 10 # Segmentation returns boxes + masks 11 print(result.boxes.xyxy) # bounding boxes (N, 4) 12 print(result.boxes.cls) # class IDs (N,) 13 print(result.masks.data.shape) # (N, H, W) tensor of binary masks
Mask representations
1 # Raw bitmasks 2 result.masks.data # tensor (N, H, W) - original image resolution 3 4 # Polygon contours (one ndarray of (M, 2) per instance) 5 result.masks.xy # absolute pixel coords 6 result.masks.xyn # normalized to [0, 1] 7 8 # Move / convert like Boxes 9 result.masks.cpu() 10 result.masks.numpy()
Save annotated output
save=True draws boxes and translucent mask overlays automatically.
1 model("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.
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
1 from libreyolo import LibreYOLO 2 3 # YOLO-NAS pose 4 model = LibreYOLO("LibreYOLONASs-pose.pt") 5 result = model("people.jpg") 6 7 # EdgeCrafter pose 8 # model = LibreYOLO("LibreECs-pose.pt") 9 10 # Per-person bbox + 17 keypoints 11 print(result.boxes.xyxy) # person boxes (N, 4) 12 print(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.0.
1 # RF-DETR pose preview (size x only) 2 model = LibreYOLO("LibreRFDETRx-pose.pt") 3 result = model("people.jpg") 4 print(result.keypoints.xy.shape) # (N, 17, 2)
Keypoint API
1 result.keypoints.xy # (N, K, 2) absolute pixel coords 2 result.keypoints.xyn # (N, K, 2) normalized to [0, 1] 3 result.keypoints.conf # (N, K) per-keypoint confidence (None if model doesn't emit it) 4 result.keypoints.has_visible # (N, K) bool - conf > 0 5 6 result.keypoints.cpu() 7 result.keypoints.numpy()
Save annotated output
1 model("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.0.
Install
1 pip 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
1 from libreyolo import LibreYOLO 2 from libreyolo.models.l2cs.face import resolve_face_detector 3 4 # Gaze head 5 gaze = LibreYOLO("LibreL2CSr50.pt") 6 7 # Wire any LibreYOLO detector trained on faces 8 face = LibreYOLO("path/to/face-detector.pt") 9 gaze.face_detector = resolve_face_detector(face) 10 11 result = gaze("portrait.jpg") 12 print(result.boxes.xyxy) # face boxes 13 print(result.gaze.data) # (N, 2) tensor - pitch, yaw in radians
Decode angles
1 import math 2 3 for 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.
| Family | Checkpoints | Input | Weights | Fine-tune | ONNX export |
|---|---|---|---|---|---|
| LibreMobileNetV4 | LibreMobileNetV4{s,m,l}-cls.pt | 224 / 224 / 256 | Apache-2.0 ImageNet-1k (production) | Cross-entropy | Yes |
| LibreDINOv2 (classify) | LibreDINOv2{n,s,m,l}-cls.pt | 224 | Imagenette demo-grade (10 classes) | Linear probe | Not supported |
LibreMobileNetV4 (production classifier)
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:
Load and predict. A single image returns one Results; read .probs directly off it (pass a list to get a list back).
1 from libreyolo import LibreYOLO 2 3 # MobileNetV4-conv-Small, Apache-2.0 ImageNet-1k weights (auto-downloaded if missing) 4 model = LibreYOLO("LibreMobileNetV4s-cls.pt") 5 result = model("cat.jpg") # single image -> one Results 6 7 probs = result.probs # whole-image class vector, length = num classes 8 print(probs.top1, probs.top1conf) # top-1 class id (int) and its confidence 9 print(probs.top5, probs.top5conf) # 5 class ids and 5 confidences 10 print(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.
1 from libreyolo import LibreMobileNetV4 2 3 model = LibreMobileNetV4(size="s") # ImageNet-pretrained backbone 4 model.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):
1 model = LibreYOLO("LibreMobileNetV4s-cls.pt") 2 metrics = model.val(data="imagenette160") 3 print(metrics["metrics/accuracy_top1"]) 4 print(metrics["metrics/accuracy_top5"])
Export to ONNX (verified bit-exact against eager). The ONNX graph emits a single logits tensor.
1 model = LibreYOLO("LibreMobileNetV4s-cls.pt") 2 path = 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)
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:
Load and predict (same Probs surface as MobileNetV4):
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreDINOv2s-cls.pt") # DINOv2-S backbone + linear probe (224) 4 result = model("springer.jpg") 5 print(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).
1 from libreyolo import LibreDINOv2 2 3 # Fresh DINOv2 backbone + random linear head, sized to the dataset 4 model = LibreDINOv2(size="s", task="classify", nb_classes=3) 5 model.train(data="path/to/imagefolder", epochs=5, lr=1e-4, batch=4) 6 7 # Validate the same way (top-1 / top-5) 8 metrics = model.val(data="path/to/imagefolder") 9 print(metrics["metrics/accuracy_top1"])
Export is not implemented for LibreDINOv2. If you need an exportable classifier, use LibreMobileNetV4.
1 model = LibreYOLO("LibreDINOv2s-cls.pt") 2 model.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.
1 dataset_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
1 probs = result.probs # Probs payload, 1-D vector of length = num classes 2 probs.data # raw tensor / ndarray of class probabilities 3 probs.top1 # int - argmax class id 4 probs.top5 # list - 5 class ids, highest first 5 probs.top1conf # float - confidence of the top-1 class 6 probs.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.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.
1 from libreyolo import LibreYOLO 2 3 # ViT-S encoder, Apache-2.0 weights (commercial use OK) 4 model = LibreYOLO("LibreDepthAnythingV2s-depth.pt") 5 result = model("street.jpg") 6 7 depth = result.depth_map # DepthMap payload, (H, W) float on the original canvas 8 print(depth.data.shape) # (H, W) 9 print(depth.min, depth.max, depth.mean) # relative inverse depth: higher = closer 10 norm = depth.normalized() # rescaled to [0, 1] over finite values
DepthMap API
1 depth = result.depth_map 2 depth.data # (H, W) float tensor / ndarray, relative inverse depth 3 depth.min # min over finite values 4 depth.max # max over finite values 5 depth.mean # mean over finite values 6 depth.normalized() # (H, W) rescaled to [0, 1]; non-finite pixels become 0 7 8 depth.cpu() 9 depth.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.
1 metrics = model.val(data="depth_dataset.yaml") 2 print(metrics["metrics/abs_rel"]) # absolute relative error (lower is better) 3 print(metrics["metrics/rmse"]) # root mean squared error 4 print(metrics["metrics/delta1"]) # fraction within a 1.25x ratio (higher is better)
Not supported
1 model.train(data="...") # raises NotImplementedError - DA V2 is inference + val only 2 model.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.
Point Localization
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).
1 from libreyolo import LibreYOLO 2 3 # LibreFOMO weights are not hosted by LibreYOLO - pass a local checkpoint 4 model = LibreYOLO("path/to/LibreFOMOm-point.pt") 5 result = model("scene.jpg") 6 7 points = result.points # Points payload, (N, 4) rows: x, y, class, confidence 8 print(points.xy) # (N, 2) absolute pixel coords 9 print(points.xyn) # (N, 2) normalized to [0, 1] 10 print(points.cls, points.conf)
Training
v1.3.0 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
1 from libreyolo import LibreYOLO 2 3 # Fine-tune from a pretrained checkpoint (recommended) 4 model = LibreYOLO("LibreYOLO9c.pt") 5 6 results = 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 38 print(f"Best mAP50-95: {results['best_mAP50_95']:.3f}") 39 print(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
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreRFDETRs.pt") 4 5 results = 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.
1 model = LibreYOLO("LibreRFDETRs.pt") 2 results = 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]).
1 from libreyolo import LibreYOLO 2 from libreyolo.training.loggers import MLflowLogger 3 4 model = LibreYOLO("LibreYOLO9c.pt") 5 6 # By name 7 model.train(data="coco128.yaml", loggers="tensorboard") 8 9 # Mix configured instances and names 10 model.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
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
1 # Load the checkpoint with the factory, then resume 2 model = LibreYOLO("runs/train/yolo9_exp/weights/last.pt") 3 results = model.train(data="coco128.yaml", resume=True)
Custom dataset YAML format
1 path: /path/to/dataset 2 train: images/train 3 val: images/val 4 test: images/test # optional 5 6 nc: 3 7 names: ["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.
1 model = LibreYOLO("LibreYOLO9c.pt") 2 results = 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.
1 # Effective batch 64 on a single GPU that only fits batch=8 2 model.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:
1 # 4-GPU node 2 torchrun --nproc_per_node=4 train_yolo9.py 3 4 # Multi-node - see PyTorch's torchrun docs for --nnodes / --rdzv_endpoint
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreYOLO9c.pt") 4 # Pass device="" (auto-detect) and let torchrun set the rank 5 model.train(data="coco128.yaml", epochs=300, batch=16)
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.
1 results = 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 13 print(f"mAP50: {results['metrics/mAP50']:.3f}") 14 print(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:
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
1 # ONNX (default) 2 model.export() 3 4 # TorchScript 5 model.export(format="torchscript") 6 7 # TensorRT (requires NVIDIA GPU + TensorRT) 8 model.export(format="tensorrt") 9 10 # OpenVINO (optimized for Intel hardware) 11 model.export(format="openvino") 12 13 # NCNN (via PNNX) 14 model.export(format="ncnn") 15 16 # CoreML (.mlpackage, macOS runtime) 17 model.export(format="coreml") 18 19 # TFLite (RF-DETR detect/seg/pose + YOLO9 detect; experimental, needs Python 3.12+) 20 model.export(format="tflite")
All export parameters
1 path = 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.
1 model = LibreYOLO("LibreYOLO9c.pt") 2 model.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 export
Experimental v1.3.0 adds a TFLite export path built on onnx2tf. 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).
1 pip install "libreyolo[tflite]" # Python 3.12+
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreRFDETRs-seg.pt") 4 model.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 a TF Lite runtime (ai-edge-litert / tflite-runtime) on your target device.
ONNX metadata
Exported ONNX files include embedded metadata:
| Key | Example 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.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model.torchscript") 4 5 result = model("image.jpg", conf=0.25, iou=0.45, save=True) 6 print(result.boxes.xyxy)
ONNX Inference
Run inference using ONNX Runtime instead of PyTorch. Useful for deployment environments without PyTorch.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model.onnx") 4 5 result = model("image.jpg", conf=0.25, iou=0.45, save=True) 6 print(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:
1 # Export with metadata 2 model.export(format="onnx", output_path="model.onnx") 3 4 # Load - names and nb_classes auto-populated 5 onnx_model = LibreYOLO("model.onnx") 6 print(onnx_model.names) # {0: "person", 1: "bicycle", ...} 7 print(onnx_model.nb_classes) # 80
For ONNX files without metadata (e.g., exported by other tools), specify nb_classes manually:
1 model = LibreYOLO("external_model.onnx", nb_classes=20)
Device selection
1 # Auto-detect (CUDA if available, else CPU) 2 model = LibreYOLO("model.onnx", device="auto") 3 4 # Force CPU 5 model = LibreYOLO("model.onnx", device="cpu") 6 7 # Force CUDA 8 model = LibreYOLO("model.onnx", device="cuda")
Prediction parameters
Runtime artifacts loaded through LibreYOLO() support the shared runtime prediction API:
1 result = 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.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model.engine") 4 5 result = model("image.jpg", conf=0.25, iou=0.45, save=True) 6 print(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.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model_openvino/") 4 5 result = model("image.jpg", conf=0.25, iou=0.45, save=True) 6 print(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.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model_ncnn/") 4 5 result = model("image.jpg", conf=0.25, iou=0.45, save=True) 6 print(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.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model.mlpackage", compute_units="all") 4 5 result = model("image.jpg", conf=0.25, iou=0.45, save=True) 6 print(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 follows Ultralytics-style key=value syntax.
Subcommands
| Command | Purpose |
|---|---|
predict | Run inference on images, directories, or videos |
train | Train a model on a dataset |
val | Evaluate a model on a dataset |
export | Export to ONNX / TorchScript / TensorRT / OpenVINO / NCNN / CoreML / TFLite |
ui | Launch a local drag-and-drop / paste browser inference UI |
doctor | Run pre-training dataset health checks (YOLO detection format) |
checks | Print Python, torch, CUDA, GPU, and optional-package info |
models | List registered model families and CLI shortcut names |
formats | List supported export formats |
cfg | Print the default training configuration YAML |
info | Load a model and print resolved family, size, task, device, and classes |
metadata | Inspect raw checkpoint metadata from a .pt file |
version | Print 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
| Command | Important options |
|---|---|
predict | conf, iou, imgsz, classes, max_det, half, batch, tiling, overlap_ratio, output_file_format, project, name, exist_ok, face_detector |
train | epochs, batch, imgsz, lr0, optimizer, scheduler, workers, seed, resume, amp, task, cache, lora, freeze, save_plots, allow_download_scripts, dry_run |
val | split, batch, imgsz, conf, iou, max_det, half, save_plots, data_dir, use_coco_eval, project, name, exist_ok, save_json, allow_download_scripts |
export | format, imgsz, batch, half, int8, dynamic, simplify, nms, conf, iou, max_det, opset, data, fraction, device, allow_download_scripts, verbose |
Predict
1 # Flagship: YOLO9 2 libreyolo predict model=yolo9-c source=image.jpg conf=0.25 save=true 3 4 # Flagship: RF-DETR 5 libreyolo predict model=rfdetr-s source=image.jpg save=true 6 7 # Video - saved under runs/detect/predict*/ 8 libreyolo predict model=yolo9-c source=clip.mp4 save=true 9 10 # Tiled inference for very large images 11 libreyolo predict model=yolo9-c source=aerial.jpg tiling=true save=true 12 13 # Gaze (requires a face detector) 14 libreyolo predict model=LibreL2CSr50.pt source=portrait.jpg \ 15 --face-detector path/to/face.pt save=true
Train
1 libreyolo train model=yolo9-c data=coco128.yaml epochs=300 batch=16 device=0 2 3 # Dry-run prints the resolved config without launching training 4 libreyolo train model=yolo9-c data=coco128.yaml --dry-run
Validate
1 libreyolo val model=runs/train/exp/weights/best.pt data=coco128.yaml split=val
Export
1 libreyolo export model=runs/train/exp/weights/best.pt format=onnx dynamic=true 2 libreyolo export model=best.pt format=tensorrt half=true 3 libreyolo export model=best.pt format=openvino int8=true data=coco128.yaml 4 libreyolo export model=best.pt format=coreml
Export with embedded NMS and rectangular size
1 # Embed NMS into an ONNX YOLO9 detection graph 2 libreyolo 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) 5 libreyolo export model=yolo9-c format=onnx imgsz=640,480 6 7 # TFLite (Python 3.12+, libreyolo[tflite]) 8 libreyolo 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.
1 libreyolo ui # opens http://127.0.0.1:8000 2 libreyolo 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.
1 libreyolo doctor coco8.yaml 2 libreyolo doctor --data coco8.yaml --strict --json 3 libreyolo 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.
1 libreyolo predict model=yolo9-c source=img.jpg --json | jq . 2 3 libreyolo train --help-json > train_schema.json
API Reference
LibreYOLO (factory)
1 LibreYOLO( 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)
1 model( 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)
1 backend( 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
1 result = 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 16 len(result) # number of detections 17 result.cpu() # copy with tensors on CPU 18 result.cuda() # copy with tensors on CUDA 19 result.numpy() # copy with numpy arrays 20 result.summary() # list[dict] with boxes, masks, gaze, and track_id when present 21 result.to_json() # JSON string from summary()
Boxes
1 boxes = Boxes(boxes, conf, cls) 2 3 boxes.xyxy # (N, 4) tensor - x1, y1, x2, y2 4 boxes.xywh # (N, 4) tensor - cx, cy, w, h 5 boxes.conf # (N,) tensor - confidence scores 6 boxes.cls # (N,) tensor - class IDs 7 boxes.id # (N,) track IDs when tracking, else None 8 boxes.is_track # True when track IDs are attached 9 boxes.data # (N, 6) [xyxy, conf, cls], or (N, 7) with track IDs 10 11 len(boxes) # number of boxes 12 boxes.cpu() # copy on CPU 13 boxes.numpy() # copy as numpy arrays
Task payloads
1 result.masks.data # segmentation masks, (N, H, W) 2 result.masks.xy # list of mask contours in pixel coordinates 3 result.masks.xyn # normalized mask contours 4 5 result.keypoints.xy # pose keypoint coordinates 6 result.keypoints.xyn # normalized keypoint coordinates 7 result.keypoints.conf # keypoint confidence when present 8 9 result.gaze.data # (N, 2): pitch, yaw in radians 10 result.gaze.pitch_deg # pitch in degrees 11 result.gaze.yaw_deg # yaw in degrees 12 result.gaze.direction_3d # approximate 3D direction vectors
model.export()
1 model.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()
1 model.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):
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)
1 model.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)
1 model.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:
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("model.onnx") 4 model = LibreYOLO("model.torchscript") 5 model = LibreYOLO("model.engine") 6 model = LibreYOLO("model_openvino/") 7 model = LibreYOLO("model_ncnn/") 8 model = 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
1 from libreyolo import ValidationConfig 2 3 config = 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 30 config = ValidationConfig.from_yaml("config.yaml") 31 config.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:
| Method | Purpose |
|---|---|
_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
1 libreyolo/ 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
- 1Create
libreyolo/models/newmodel/model.pywith a class inheritingBaseModel - 2Set
FAMILY,FILENAME_PREFIX,INPUT_SIZES,SUPPORTED_TASKS, andDEFAULT_TASKas needed - 3Implement registry hooks such as
can_load(),detect_size(),detect_nb_classes(), anddetect_size_from_filename() - 4Implement the model init, preprocess, forward, postprocess, train, and validation hooks that the family needs
- 5Create the supporting network and utilities under
libreyolo/models/newmodel/ - 6Add the import to
libreyolo/models/__init__.py; subclass registration happens when the import runs - 7Export the class from
libreyolo/__init__.py - 8(Optional) Override
val_preprocessor_classif 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.
1 from libreyolo import LibreYOLO 2 3 model = LibreYOLO("LibreYOLO9c.pt") 4 model.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
| Task | Data layout | Labels |
|---|---|---|
| Detection | data.yaml + labels/*.txt, or COCO JSON | One box per line |
| Instance segmentation | data.yaml + polygon .txt, or COCO JSON | Polygon per line (TXT) / polygons + RLE (COCO) |
| OBB | data.yaml + rotated-box .txt, or COCO JSON | One rotated box per line |
| Pose | data.yaml + .txt + kpt_shape/flip_idx | Box + keypoints per line |
| Semantic segmentation | data.yaml + masks_dir/ PNGs | Per-pixel class ID (255 = ignore) |
| Depth | data.yaml + depths_dir/ maps | Per-pixel depth (0 = invalid) |
| Classification | ImageFolder (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.
1 path: /absolute/path/to/dataset # dataset root 2 train: images/train # dir, .txt file list, or list of paths 3 val: images/val 4 test: images/test # optional 5 6 nc: 80 # optional; inferred from names if absent 7 names: ["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].
1 dataset/ 2 images/train/img001.jpg 3 labels/train/img001.txt # same stem as the image
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>
1 kpt_shape: [17, 3] # K keypoints, 3 values each: x, y, visibility 2 flip_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.
1 path: dataset 2 train: images/train # image directory 3 val: images/val 4 annotations: 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.
1 dataset/ 2 images/train/scene001.jpg 3 masks/train/scene001.png # single-channel class IDs, 255 = ignore
1 path: /path/to/dataset 2 train: images/train 3 val: images/val 4 masks_dir: masks 5 nc: 3 6 names: ["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.
1 path: /path/to/dataset 2 val: images/val 3 depths_dir: depths 4 depth_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.
| Config | Task | Download |
|---|---|---|
coco8 | Detection (8 images) | Automatic |
coco128 | Detection (128 images) | Automatic |
coco5000 | Detection | Script — allow_download_scripts=True |
coco / coco-val-only | Detection (full) | Script — allow_download_scripts=True |
coco8-pose / coco-pose | Pose | Script — allow_download_scripts=True |
cocostuff | Semantic (182 classes) | Manual — place locally |
1 results = model.val(data="coco8.yaml") # auto-downloads 2 results = model.train(data="coco128.yaml", epochs=10) # auto-downloads 3 model.train(data="coco8-pose.yaml", allow_download_scripts=True) # script config