| --- |
| 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. |
|
|