# RF-DETR
A detection transformer that predicts a fixed set of objects instead of a dense grid, so it needs no NMS at inference. LibreYOLO supports it for four tasks.
Tasks: Detection, Instance segmentation, Pose, Oriented boxes. Install: pip install "libreyolo[rfdetr]".
Verified against LibreYOLO v1.6.0.

## Install

RF-DETR needs its own extra, which pulls in `transformers` for the backbone.

```bash
pip install "libreyolo[rfdetr]"
```

## Predict

Weights download from Hugging Face on first use and are cached locally.

**Python**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

model = LibreYOLO("LibreRFDETRs.pt")
result = model(SAMPLE_IMAGE, save=True)

for box in result.boxes:
    print(box.cls, box.conf, box.xyxy)
```

**CLI**

```bash
libreyolo predict model=LibreRFDETRs.pt source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg save=True
```

**Video**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreRFDETRs.pt")

# Any source the library accepts: file, folder, URL, webcam index,
# RTSP stream, or a .streams list
for 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 the query
selection; there is no NMS step to tune. See
[prediction](/docs/predict) for sources, streaming and result handling.

Detection, segmentation and oriented-box paths use floating-point OpenCV bilinear resizing without antialiasing; pose keeps its antialiased resize. Rectangular `imgsz=(height, width)` must satisfy the task patch/window grid. The checkpoint inventory includes the UI detector. [Event histograms](/docs/train/event-histograms) use the recorded input profile.

## Variants

Four detection sizes, `n` to `l`, and four tasks that share one architecture:
segmentation, pose and oriented boxes reuse the detection decoder with a
different head, so they take the same arguments. Segmentation adds `x` and
`xx`, and pose comes only in `x`. The sizes carry similar parameter counts and differ mainly
in input resolution.

| Checkpoint | Input (px) | mAP 50-95 | Params (M) |
| --- | --- | --- | --- |
| `LibreRFDETRn` | 384 | 51.4 | 30.47 |
| `LibreRFDETRs` | 512 | 55.2 | 32.11 |
| `LibreRFDETRm` | 576 | 57.4 | 33.69 |
| `LibreRFDETRl` | 704 | 58.6 | 33.93 |

COCO val2017, 500 images. Published on https://www.visionanalysis.org/

Interactive chart: https://www.visionanalysis.org/embed/scatter?highlight=rfdetr-n%2Crfdetr-s%2Crfdetr-m%2Crfdetr-l%2Crfdetr-seg-n&title=RF-DETR%20on%20COCO&subtitle=Accuracy%20against%20latency%2C%20every%20benchmarked%20model

## Train

Training starts from a published checkpoint, for all four tasks.
`pretrained=False` instead reinitializes the whole network, backbone included,
and trains from scratch.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreRFDETRs.pt")
model.train(data="my-dataset.yaml", epochs=50, imgsz=512, batch=8, lr0=1e-4)
```

**CLI**

```bash
libreyolo train model=LibreRFDETRs.pt data=my-dataset.yaml \
  epochs=50 imgsz=512 batch=8 lr0=1e-4
```

**LoRA**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreRFDETRs.pt")
model.train(data="my-dataset.yaml", epochs=50, lora=True)
```

**Multi-GPU**

```bash
libreyolo train model=LibreRFDETRs.pt data=my-dataset.yaml \
  epochs=50 device=0,1 batch=-1
```

Two arguments matter more here than on a CNN detector. Keep `lr0` at or below
`1e-4`, since transformer detectors diverge at learning rates a YOLO model
tolerates. Leave `imgsz` at the checkpoint's native resolution unless you have a
reason to change it. The input must divide evenly by the backbone patch size
times the window count; LibreYOLO checks this before the run starts and names
the nearest valid sizes.

See [training](/docs/train) for datasets, augmentation, multi-GPU and loggers.

Fresh runs default to `output_dir=None`, resolving to an incremented `runs/train/rfdetr_exp` with `exist_ok=False`. A resumed run keeps writing into its checkpoint's run directory. Multi-class pose datasets use `kpt_names` keyed by class index or name; an empty list marks a box-only class. Predictions pad keypoints to `kpt_shape`; keypoint-mAP fitness does not score box-only classes.

## Validate

`val()` returns a dictionary of `metrics/` keys covering mAP 50, mAP 50-95,
mAP 75 and COCO average recall, measured against any dataset in the format you trained on.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreRFDETRs.pt")

# val() returns a plain dict, not an object
metrics = model.val(data="my-dataset.yaml", imgsz=512)

print(metrics["metrics/mAP50-95"])
print(metrics["metrics/mAP50"])
print(metrics["metrics/mAP75"], metrics["metrics/AR100"])
```

**CLI**

```bash
libreyolo val model=LibreRFDETRs.pt data=my-dataset.yaml imgsz=512
```

**Against COCO**

```bash
# The bundled COCO yaml carries an embedded download script, so it
# needs explicit permission unless the dataset is already local.
libreyolo val model=LibreRFDETRn.pt data=coco.yaml imgsz=384 \
  allow_download_scripts=True
```

## Export

| Task | ONNX | TorchScript | ExecuTorch | TensorRT | OpenVINO | Paddle | MNN | RKNN | ncnn | TFLite | CoreML | Core AI |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Detection | yes | yes | yes | yes | yes |  | yes |  |  |  | yes | yes |
| Instance segmentation | yes | yes | yes | yes | yes |  |  |  |  |  |  |  |
| Pose | yes | yes | yes | yes | yes |  |  |  |  |  |  |  |
| Oriented boxes | yes | yes | yes | yes | yes |  |  |  |  |  |  |  |

A "yes" means the export is supported. An empty cell means the exporter refuses that combination.

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`. Running the graph in a bare runtime, with no LibreYOLO installed, is
also supported, but then preprocessing and postprocessing are yours to write.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibreRFDETRs.pt")
model.export(format="onnx", imgsz=512)
model.export(format="tensorrt", imgsz=512, half=True)

# Arguments accepted for every format:
#
#   format    "onnx" | "torchscript" | "executorch" | "tensorrt"
#             | "openvino" | "paddle" | "mnn" | "rknn" | "ncnn"
#             | "tflite" | "coreml" | "coreai".
#             "engine" is an alias for tensorrt, "litert" for tflite.
#   imgsz     int, or (height, width). Defaults to the checkpoint's
#             native resolution.
#   batch     int, default 1.
#   half      bool, export in FP16. Default False.
#   int8      bool, export in INT8. Default False. Needs `data`.
#   data      path to a dataset YAML, used to calibrate int8.
#   fraction  float, share of that calibration set to use. Default 1.0.
#   dynamic   bool, dynamic axes. Default True.
#   simplify  bool, run ONNX graph simplification. Default True.
#   opset     int, ONNX opset. Chosen per family when not given.
#   device    str, device to trace on. Defaults to the model's device.
#   output_path  str, defaults to a name derived from the checkpoint.
#   verbose   bool, default False.
#   allow_download_scripts  bool, default False. Permits embedded
#             Python in a dataset YAML that has to be downloaded.
#
# A few formats take extra arguments of their own, such as an RKNN
# target platform. Those are documented on each format's page.
```

**CLI**

```bash
libreyolo export model=LibreRFDETRs.pt format=onnx imgsz=512
libreyolo export model=LibreRFDETRs.pt format=tensorrt imgsz=512 half=True
```

**Use the exported file**

```python
from 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("LibreRFDETRs.onnx")
result = model(SAMPLE_IMAGE)

print(result.boxes.xyxy)
```

**Without LibreYOLO**

```python
import numpy as np
import onnxruntime as ort

# Running the graph directly means doing your own preprocessing and
# postprocessing. Inspect the signature before wiring anything up.
session = ort.InferenceSession("weights/LibreRFDETRs.onnx")
name = session.get_inputs()[0].name
outputs = session.run(None, {name: np.zeros((1, 3, 512, 512), dtype=np.float32)})

for meta, array in zip(session.get_outputs(), outputs):
    print(meta.name, array.shape)
```

## Checkpoints

Every published weight file for this family.

| File | Input (px) | Task | Weights license |
| --- | --- | --- | --- |
| `LibreRFDETRl.pt` | 704 | Detection | apache-2.0 |
| `LibreRFDETRm.pt` | 576 | Detection | apache-2.0 |
| `LibreRFDETRn.pt` | 384 | Detection | apache-2.0 |
| `LibreRFDETRs.pt` | 512 | Detection | apache-2.0 |
| `LibreRFDETRn-seg.pt` | 312 | Instance segmentation | apache-2.0 |
| `LibreRFDETRs-seg.pt` | 384 | Instance segmentation | apache-2.0 |
| `LibreRFDETRm-seg.pt` | 432 | Instance segmentation | apache-2.0 |
| `LibreRFDETRl-seg.pt` | 504 | Instance segmentation | apache-2.0 |
| `LibreRFDETRx-seg.pt` | 624 | Instance segmentation | apache-2.0 |
| `LibreRFDETRxx-seg.pt` | 768 | Instance segmentation | apache-2.0 |
| `LibreRFDETRn-obb.pt` | 384 | Oriented boxes | cc-by-4.0 |
| `LibreRFDETRs-obb.pt` | 512 | Oriented boxes | cc-by-4.0 |
| `LibreRFDETRm-obb.pt` | 576 | Oriented boxes | cc-by-4.0 |
| `LibreRFDETRl-obb.pt` | 704 | Oriented boxes | cc-by-4.0 |
| `LibreRFDETRx-pose.pt` | 576 | Pose | apache-2.0 |
| `LibreRFDETRm-ui.pt` |  | Detection | mit |

## Licensing

Check the license on the Hugging Face repository of the specific weights you download. That repository is authoritative and licenses are not always uniform across a family. This is a description of the licenses involved, not legal advice.

- Original work: RF-DETR, Roboflow
- Upstream license: Apache-2.0
- Upstream source: https://github.com/roboflow/rf-detr
- LibreYOLO code: MIT
- Weights: Apache-2.0, republished at https://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.

## Citation

```bibtex
@inproceedings{robinson2026rfdetr,
  title     = {RF-DETR: Real-Time Detection Transformer},
  author    = {Robinson, Isaac and Robicheaux, Peter and Popov, Matvei and Ramanan, Deva and Peri, Neehar},
  booktitle = {International Conference on Learning Representations (ICLR)},
  year      = {2026},
  url       = {https://arxiv.org/abs/2511.09554}
}
```

Copied from https://github.com/roboflow/rf-detr#citation
