# PicoDet
PicoDet is a single-stage detector built for mobile and edge CPUs: an ESNet backbone, a CSP-PAN neck and a shared Generalized Focal Loss head. LibreYOLO supports it for detection.
Tasks: Detection. Install: pip install libreyolo.
Verified against LibreYOLO v1.5.0.

## Install

PicoDet needs no extra beyond the base package.

```bash
pip install libreyolo
```

## Predict

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

**Python**

```python
from libreyolo import LibreYOLO, SAMPLE_IMAGE

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

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

**CLI**

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

The returned `Results` object is the one every family returns, so swapping in a
different detector is a one line change. `conf` sets the confidence threshold
and `iou` the NMS threshold. See [prediction](/docs/predict) for sources,
streaming and result handling.

## Variants

Three sizes, each at its own fixed input resolution: `s` the smallest and
`l` the largest. Resolution grows with the size, so larger checkpoints are
also more expensive to run per image, on top of carrying more parameters.

| Checkpoint | Input (px) | mAP 50-95 | Params (M) |
| --- | --- | --- | --- |
| `LibrePICODETs` | 320 | 29.5 | 0.99 |
| `LibrePICODETm` | 416 | 37.6 | 2.15 |
| `LibrePICODETl` | 640 | 44.2 | 3.31 |

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

Interactive chart: https://www.visionanalysis.org/embed/scatter?highlight=picodet-s%2Cpicodet-m%2Cpicodet-l&title=PicoDet%20on%20COCO&subtitle=Accuracy%20against%20latency%2C%20every%20benchmarked%20model

## Train

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibrePICODETs.pt")
model.train(
    data="my-dataset.yaml",
    epochs=300, batch=16, lr0=0.01,
)
```

**CLI**

```bash
# imgsz is worth setting: the CLI defaults it to 640, while the s
# checkpoint is native at 320.
libreyolo train model=LibrePICODETs.pt data=my-dataset.yaml imgsz=320 epochs=300 batch=16 lr0=0.01
```

The loss components and the assigner follow the upstream recipe: VFL, DFL,
GIoU and SimOTA, with classification-quality weighting and dynamic-IoU VFL
targets. Inference is bit-equivalent to upstream on the same checkpoint.

What has not been checked, per `train()`'s own docstring: full-dataset
convergence, multi-GPU behavior, and any augmentation beyond horizontal flip.
The `s` checkpoint at its native 320 has also not reliably cleared LibreYOLO's
accuracy floor on the 30-image, two-class fixture the library tests small
fine-tunes with. That size is a better fit at full-COCO scale.

`train()` also accepts a `pretrained` argument, but the value is never read
inside the method: training always continues from whatever weights the model
was constructed with, so `pretrained=False` does not reinitialize the
network. Leave `imgsz` unset in Python and it takes the loaded checkpoint's
native resolution, 320 for `s`, 416 for `m` and 640 for `l`. The CLI always
sends an `imgsz`, defaulting to 640, so set it there to match the checkpoint.

Left alone otherwise, the trainer runs 300 epochs with SGD at `lr0=0.01`,
momentum 0.9, weight decay 4e-5 and a 1-epoch warmup on a cosine schedule.
Horizontal flip is the only augmentation applied.

See [training](/docs/train) 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.

**Python**

```python
from libreyolo import LibreYOLO

model = LibreYOLO("LibrePICODETs.pt")
metrics = model.val(data="my-dataset.yaml")

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

**CLI**

```bash
libreyolo val model=LibrePICODETs.pt data=my-dataset.yaml
```

## Export

| Task | ONNX | TorchScript | ExecuTorch | TensorRT | OpenVINO | Paddle | MNN | RKNN | ncnn | TFLite | CoreML | Core AI |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Detection | yes | yes | yes | 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("LibrePICODETs.pt")
model.export(format="onnx", imgsz=320)
model.export(format="tensorrt", imgsz=320, half=True)
```

**CLI**

```bash
libreyolo export model=LibrePICODETs.pt format=onnx imgsz=320
libreyolo export model=LibrePICODETs.pt format=tensorrt imgsz=320 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("LibrePICODETs.onnx")
result = model(SAMPLE_IMAGE)

print(result.boxes.xyxy)
```

## Checkpoints

Every published weight file for this family.

| File | Input (px) | Task | Weights license |
| --- | --- | --- | --- |
| `LibrePICODETs.pt` | 320 | Detection | apache-2.0 |
| `LibrePICODETm.pt` | 416 | Detection | apache-2.0 |
| `LibrePICODETl.pt` | 640 | Detection | apache-2.0 |

## 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: PP-PicoDet, PaddlePaddle (Baidu)
- Upstream license: Apache-2.0
- Upstream source: https://github.com/PaddlePaddle/PaddleDetection
- LibreYOLO code: Apache-2.0
- 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. LibreYOLO's port follows Bo396543018/Picodet_Pytorch, a PyTorch re-implementation of PaddleDetection's original PP-PicoDet, and both carry the same Apache-2.0 terms as the paper's authors.

LibreYOLO's port follows Bo396543018/Picodet_Pytorch, a PyTorch
re-implementation of PaddleDetection's original PP-PicoDet, with mmcv
stripped out and every activation matched exactly so PaddlePaddle checkpoints
converted through Bo's pipeline load with no numerical drift. Both sources
carry the same Apache-2.0 terms as the paper's authors.

## Citation

```bibtex
@misc{yu2021pppicodet,
      title={PP-PicoDet: A Better Real-Time Object Detector on Mobile Devices},
      author={Guanghua Yu and Qinyao Chang and Wenyu Lv and Chang Xu and Cheng Cui and Wei Ji and Qingqing Dang and Kaipeng Deng and Guanzhong Wang and Yuning Du and Baohua Lai and Qiwen Liu and Xiaoguang Hu and Dianhai Yu and Yanjun Ma},
      year={2021},
      eprint={2111.00902},
      archivePrefix={arXiv},
      primaryClass={cs.CV}
}
```

Copied from https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.8/configs/picodet/README_en.md#cite-pp-picodet


## PicoDet architecture

- PicoDet S: [SVG](/diagrams/models/picodet/s.svg), [interactive diagram](/diagrams/models/picodet/s.html)
- PicoDet M: [SVG](/diagrams/models/picodet/m.svg), [interactive diagram](/diagrams/models/picodet/m.html)
- PicoDet L: [SVG](/diagrams/models/picodet/l.svg), [interactive diagram](/diagrams/models/picodet/l.html)
- PicoDet family: [SVG](/diagrams/models/picodet/family.svg), [interactive diagram](/diagrams/models/picodet/family.html)
