DEIM
A detection transformer trained with dense one-to-one matching, which converges in far fewer epochs than the DETR recipes it builds on. LibreYOLO carries two versions of it, told apart by the checkpoint you load.
- Tasks
- detection
- Sizes
- deim: n, s, m, l, x at 640 px
- Install
pip install libreyolo- Support tier
- Core, since v1.2.0. Core trainable detectors: features follow the flagships in the same release wave.
- Upstream
- DEIM and DEIMv2 by Intellindust AI Lab, Apache-2.0; the DEIMv2 DINOv3 backbone adds Meta's DINOv3 License. Paper, source
- Licenses
- Code Apache-2.0, weights Apache-2.0; the DEIMv2 DINOv3 backbone adds Meta's DINOv3 License. Commercial use
Install
Neither version needs an optional extra. Everything they import is in the base install.
pip install libreyoloAdapter fine-tuning with lora=True is the exception, and needs the lora
extra.
pip install "libreyolo[lora]"Predict
Weights download from Hugging Face on first use and are cached locally.
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreDEIMn.pt")result = model(SAMPLE_IMAGE, save=True) for box in result.boxes: print(box.cls, box.conf, box.xyxy)libreyolo predict model=LibreDEIMn.pt save=True \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgfrom libreyolo import LibreYOLO # The version is part of the file name, and the factory routes on the# checkpoint, so both load the same way.model = LibreYOLO("LibreDEIMv2pico.pt") # Any source the library accepts: file, folder, URL, webcam index,# RTSP stream, or a .streams listfor result in model.predict("clip.mp4", stream=True, save=True): print(len(result.boxes))The returned Results object is the one every family returns, so swapping in a
different detector is a one line change. conf and max_det filter a top-k
decode over queries and classes; there is no NMS step to tune, and iou is
accepted but unused. See prediction for sources, streaming and
result handling.
Variants
Version 1 ships five sizes, all at the same input size. Version 2 keeps those
five names and adds three smaller ones, atto, femto and pico, the first
two of which are native at a lower input size than the rest. Five size codes
therefore exist in both versions and name different models; the version is
written into the checkpoint file name.
| Checkpoint | Input (px) | mAP 50-95 | Params (M) |
|---|---|---|---|
| LibreDEIMl | 640 | 57.8 | 31.24 |
| LibreDEIMm | 640 | 55.4 | 19.59 |
| LibreDEIMn | 640 | 46.8 | 3.78 |
| LibreDEIMs | 640 | 52.1 | 10.32 |
| LibreDEIMx | 640 | 59.6 | 62.62 |
| LibreDEIMv2atto | 320 | 27.5 | 0.51 |
| LibreDEIMv2femto | 416 | 34.5 | 0.98 |
| LibreDEIMv2l | 640 | 58.6 | 32.55 |
| LibreDEIMv2m | 640 | 56.0 | 18.36 |
| LibreDEIMv2n | 640 | 46.7 | 3.6 |
| LibreDEIMv2pico | 640 | 42.2 | 1.54 |
| LibreDEIMv2s | 640 | 53.0 | 9.78 |
| LibreDEIMv2x | 640 | 61.3 | 51.21 |
COCO val2017, 500 images. Measured by the LibreYOLO benchmark harness and published on Vision Analysis, where latency across hardware and runtimes is compared and the full run records live.
Version 1 keeps D-FINE's architecture and swaps its classification objective
for the matchability-aware loss from the dense one-to-one recipe, so the two
families share almost every state dict key and are told apart by the metadata
in the checkpoint. Version 2 keeps that training contract and mixes backbones:
HGNetv2 below s, and a DINOv3 vision transformer with a spatial tuning
adapter at s and above. That backbone is what puts a second license on those
four checkpoints, so read licensing before you ship one.
Train
Training starts from a published checkpoint. pretrained never reaches the
trainer: version 1 warns that the key is unknown and ignores it, version 2
removes it. Neither gives you a randomly initialized model.
from libreyolo import LibreYOLO model = LibreYOLO("LibreDEIMn.pt") # coco128.yaml downloads a 128-image sample on first use. Point `data`# at your own dataset YAML for a real run.model.train(data="coco128.yaml", epochs=50, batch=8, lr0=1e-4)libreyolo train model=LibreDEIMn.pt data=coco128.yaml \ epochs=50 batch=8 lr0=1e-4from libreyolo import LibreYOLO # Left unset, epochs, batch, imgsz and lr0 come from the released# recipe for the size that was loaded.model = LibreYOLO("LibreDEIMv2pico.pt")model.train(data="coco128.yaml", epochs=50)# Needs the lora extra: pip install "libreyolo[lora]"from libreyolo import LibreYOLO model = LibreYOLO("LibreDEIMn.pt")model.train(data="coco128.yaml", epochs=50, lora=True)libreyolo train model=LibreDEIMn.pt data=coco128.yaml \ epochs=50 device=0,1Pass lr0 yourself on version 1. Its Python train() signature defaults to
4e-4, the rate from the published COCO recipe, while the family's training
config carries 1e-4 as its fine-tune default, and that lower value is what
the CLI resolves when the argument is absent. The config records the
measurement behind it: at the batch sizes a fine-tune actually uses, on small
datasets, the COCO rate measurably degraded transfer.
Version 2 resolves those defaults itself. Leaving epochs, batch, imgsz
and lr0 unset makes it read each one from the released recipe for the size
that was loaded, so the small sizes train at their own input resolution without
being told, and a value you pass overrides the recipe. imgsz is the argument
it constrains: it has to be a positive multiple of 32, and version 2 raises
before the run starts otherwise.
See training for datasets, augmentation, multi-GPU and loggers.
Validate
val() returns a dictionary of metrics/ keys covering precision, recall,
mAP 50 and mAP 50-95, measured against any dataset in the format you trained on.
from libreyolo import LibreYOLO model = LibreYOLO("LibreDEIMn.pt") # val() returns a plain dict, not an objectmetrics = model.val(data="coco128.yaml") print(metrics["metrics/mAP50-95"])print(metrics["metrics/mAP50"])print(metrics["metrics/precision"], metrics["metrics/recall"])libreyolo val model=LibreDEIMn.pt data=coco128.yaml# coco-val-only.yaml fetches the 5000 val2017 images and skips the# training set. It carries an embedded download script, so it needs# explicit permission unless the dataset is already local.libreyolo val model=LibreDEIMn.pt data=coco-val-only.yaml \ allow_download_scripts=TrueThe rows in the benchmark table above come from the LibreYOLO benchmark harness; the note under that table records which dataset produced them and links the run records.
Export
| Task | ONNX | TorchScript | ExecuTorch | TensorRT | OpenVINO | Paddle | MNN | RKNN | ncnn | TFLite | CoreML | Core AI |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Detection | Detection to ONNX: supported. | Detection to TorchScript: supported. | Detection to ExecuTorch: not supported | Detection to TensorRT: supported. | Detection to OpenVINO: supported. | Detection to Paddle: supported. | Detection to MNN: supported. | Detection to RKNN: not supported | Detection to ncnn: not supported | Detection to TFLite: not supported | Detection to CoreML: not supported | Detection to Core AI: supported. |
The matrix covers both versions as one page: where they disagree about a format, the cell shows the weaker of the two, so nothing here is oversold for whichever version you load.
An exported artifact loads back through LibreYOLO() on its file suffix, so a
.onnx or .engine file behaves like a checkpoint and returns the same
Results.
# Needs the onnx extra: pip install "libreyolo[onnx]"from libreyolo import LibreYOLO model = LibreYOLO("LibreDEIMn.pt")path = model.export(format="onnx")print(path)libreyolo export model=LibreDEIMn.pt format=onnxfrom libreyolo import LibreYOLO, SAMPLE_IMAGE # The factory routes on the file suffix, so an exported artifact loads# like any checkpoint and returns the same Results object.model = LibreYOLO("LibreDEIMn.onnx")result = model(SAMPLE_IMAGE) print(result.boxes.xyxy)Checkpoints
Every published weight file for this family.
| File | Input (px) | Weights license |
|---|---|---|
| Detection | ||
| LibreDEIMn.pt | 640 | apache-2.0 |
| LibreDEIMs.pt | 640 | apache-2.0 |
| LibreDEIMm.pt | 640 | apache-2.0 |
| LibreDEIMl.pt | 640 | apache-2.0 |
| LibreDEIMx.pt | 640 | apache-2.0 |
| LibreDEIMv2n.pt | 640 | apache-2.0 |
| LibreDEIMv2s.pt | 640 | other |
| LibreDEIMv2m.pt | 640 | other |
| LibreDEIMv2l.pt | 640 | other |
| LibreDEIMv2x.pt | 640 | other |
| LibreDEIMv2atto.pt | apache-2.0 | |
| LibreDEIMv2femto.pt | apache-2.0 | |
| LibreDEIMv2pico.pt | apache-2.0 | |
Every file above exists in the LibreYOLO org today and downloads on first use.
Licensing
Check the license on the Hugging Face repository of the specific weights you download. Every checkpoint in the LibreYOLO org carries one, and they are not always the same across a family. That repository is the authoritative source; the summary below describes what applied when this page was last verified.
This is a description of the licenses involved, not legal advice. If the answer matters commercially, read the licenses yourself and take your own counsel.
- Original work
- DEIM and DEIMv2, Intellindust AI Lab
- Upstream license
- Apache-2.0; the DEIMv2 DINOv3 backbone adds Meta's DINOv3 License
- Upstream source
- github.com/Intellindust-AI-Lab/DEIM
- LibreYOLO code
- MIT
- Weights
- Apache-2.0; the DEIMv2 DINOv3 backbone adds Meta's DINOv3 License, republished at huggingface.co/LibreYOLO
- Interpretation
- Apache-2.0 is a permissive license, so these weights can be used in commercial and closed-source products. It asks you to keep its license text and attribution notices with any copy of the weights you redistribute, and it grants a patent license. It places no obligation on your own application code, and weights you train yourself on your own data are yours. DEIM is Apache-2.0 throughout, and so are the DEIMv2 sizes below S, which use an HGNetv2 backbone. The DEIMv2 S, M, L and X sizes take their backbone from DINOv3, so both their weights and the backbone source vendored in LibreYOLO are additionally governed by Meta's DINOv3 License Agreement, which is not an OSI license: redistribution has to carry the agreement with it, and it forbids use for military or warfare purposes, weapons development, espionage, nuclear industries and anything subject to ITAR. Their Hugging Face repositories declare both licenses, and DEIMv2 is also cited separately (arXiv 2509.20787).
Citation
@misc{huang2024deim,
title={DEIM: DETR with Improved Matching for Fast Convergence},
author={Shihua, Huang and Zhichao, Lu and Xiaodong, Cun and Yongjun, Yu and Xiao, Zhou and Xi, Shen},
booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},
year={2025},
}Copied from the authors' citation block at github.com/Intellindust-AI-Lab/DEIM#5-citation.
DEIMv2 is a separate paper and has its own citation block at github.com/Intellindust-AI-Lab/DEIMv2; cite that one if you used a version 2 checkpoint.