File size: 2,990 Bytes
e22cfb6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | ---
license: apache-2.0
base_model: xinyu1205/recognize-anything-plus-model
tags:
- onnx
- image-classification
- tagging
library_name: onnx
pipeline_tag: image-classification
---
# RAM++ (Recognize Anything Plus) — ONNX export
ONNX export of [xinyu1205/recognize-anything-plus-model](https://huggingface.co/xinyu1205/recognize-anything-plus-model)
(`ram_plus_swin_large_14m.pth`, revision `84d4aee3a0265c4e0df1f714f0572011d1bf2ec3`), for CPU
inference in [Mendako](https://github.com/benjaminjonard/mendako)'s tagging sidecar.
All credit for the model belongs to its authors. This repository adds no training and no weights
of its own — it is the same network, exported.
## Files
| File | Description |
|------|-------------|
| `model.onnx` | fp32 graph. Input `image` `[1, 3, 384, 384]` float32 → output `logits` `[1, 4585]` float32 |
| `tags.txt` | 4585 tag names, one per line, in output order |
| `thresholds.txt` | RAM++'s own per-tag decision threshold, one float per line, same order |
## Usage
Preprocess exactly as upstream's `get_transform` does — resize to 384×384 **squashed** (no
aspect-ratio padding, bilinear), then normalize with the ImageNet statistics:
```python
import numpy as np, onnxruntime as ort
from PIL import Image
MEAN = (0.485, 0.456, 0.406)
STD = (0.229, 0.224, 0.225)
image = Image.open("photo.jpg").convert("RGB").resize((384, 384), Image.BILINEAR)
x = np.asarray(image, dtype=np.float32) / 255.0
x = (x - np.asarray(MEAN, dtype=np.float32)) / np.asarray(STD, dtype=np.float32)
x = np.ascontiguousarray(x.transpose(2, 0, 1)[np.newaxis, ...])
session = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
logits = np.asarray(session.run(None, {"image": x})[0]).reshape(-1)
tags = [line.strip() for line in open("tags.txt", encoding="utf-8")]
thresholds = [float(line) for line in open("thresholds.txt", encoding="utf-8")]
scores = 1.0 / (1.0 + np.exp(-np.clip(logits.astype(np.float64), -30.0, 30.0)))
fired = [tag for tag, score, t in zip(tags, scores, thresholds) if score > t]
```
Each tag is scored independently — this is multi-label classification, not a softmax over classes.
Compare with **strict** `>`: a few tags ship a threshold of `1.0`, which is how RAM++ disables them,
and a saturated logit rounded in float32 would otherwise revive them.
## Verification
The export script refuses to write anything unless the result reproduces upstream's own tagging
decision. On upstream's `images/demo/demo1.jpg`:
- max `|eager − onnx|` logit drift: **1.5×10⁻⁵**
- tags produced: **identical set of 19**, compared against `ram.inference_ram()`
## Reproducing
See [`ml/tools/export_ram_plus.py`](https://github.com/benjaminjonard/mendako/blob/main/ml/tools/export_ram_plus.py)
in the Mendako repository.
## License
Apache-2.0, inherited from the upstream model (© OPPO). See the
[Recognize Anything](https://github.com/xinyu1205/recognize-anything) repository for the paper and
original code.
|