Image Segmentation
LiteRT
LiteRT
android
ios
on-device
open-vocabulary
object-detection
instance-segmentation
segment-anything
Instructions to use mlboydaisuke/SAM3-LiteRT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use mlboydaisuke/SAM3-LiteRT with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
File size: 6,407 Bytes
82ad263 c2635a8 82ad263 c2635a8 82ad263 | 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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | ---
license: other
license_name: sam-license
license_link: LICENSE
base_model: facebook/sam3
tags:
- litert
- tflite
- android
- ios
- on-device
- open-vocabulary
- object-detection
- instance-segmentation
- segment-anything
pipeline_tag: image-segmentation
---
# SAM 3 — LiteRT (on-device, GPU)

**SAM 3** (Meta, [`facebook/sam3`](https://github.com/facebookresearch/sam3)) running fully
on-device with the LiteRT **CompiledModel** API: open-vocabulary, text-prompted detection +
instance segmentation. Type *"wheel"*, *"paper bag"*, *"person"* — any phrase — and get every
match's box, score, and 288×288 instance mask. No server, no cloud.
- **ViT-L/14 trunk @1008²** + tri-neck → **CLIP-L text encoder** → **text-conditioned DETR
head** (200 queries, presence token) — ~830 M params.
- Verified on a **Pixel 8a** (vision GPU 9.2 s / text CPU 0.5 s / head GPU 1.4 s; re-prompt
1.9 s; kept-set equal to PyTorch fp32, mask IoU ≥ 0.98) and on an **iPhone 17 Pro**
(first prompt ≈ 5.7 s; **re-prompt on the same photo ≈ 1.3 s** — vision features are
cached per image, so changing the phrase is nearly instant).
- Every graph re-authoring is **exact** (corr 1.0 vs PyTorch) — no approximations.

## Files
| File | Size | Role | Accelerator |
| ---- | ---- | ---- | ----------- |
| `sam3_vision.tflite` | 930 MB (fp16) | image `[1,3,1008,1008]` → `fpn288 \| fpn144 \| fpn72` | GPU |
| `sam3_text.tflite` | 607 MB (fp16) | token embeddings `[1,32,1024]` → text memory `[32·256]` | **CPU** (see note) |
| `sam3_head.tflite` | 68 MB (fp16) | `[fpn×3 \| text_mem \| pad]` → 200 logits + boxes cxcywh + presence + 200×288² mask logits | GPU |
| `sam3_token_embed.bin` | 101 MB | fp16 `[49408×1024]` token-embedding table (host lookup) | host |
| `tokenizer/vocab.json`, `tokenizer/merges.txt` | 2 MB | CLIP byte-level BPE (ctx 32, BOS 49406, EOT 49407, zero-pad) | host |
| `tracker/*.tflite` | 1.0 GB | video tracker graphs (shared trunk + memory attention + decoders), see below | GPU |
**Requires LiteRT ≥ 2.2.0** (2.1.5 mis-executes the head graph on Android GPU).
**Why text runs on CPU:** the CLIP-L residual stream reaches |x|≈1.2e3; fp16 GPU execution
corrupts some prompt embeddings. CPU is exact and takes ~0.5 s (on Apple Metal you can use
`enforce_f32` instead).
## Usage (Kotlin, CompiledModel)
```kotlin
val vision = CompiledModel.create(visionPath, CompiledModel.Options(Accelerator.GPU), null)
val text = CompiledModel.create(textPath, CompiledModel.Options(Accelerator.CPU), null)
val head = CompiledModel.create(headPath, CompiledModel.Options(Accelerator.GPU), null)
// image -> features (once per image; cache to re-prompt instantly)
visIn[0].writeFloat(preprocess(bitmap)) // 1008x1008, (x/255-0.5)/0.5, NCHW
vision.run(visIn, visOut)
val feats = visOut[0].readFloat()
// prompt -> text memory (host BPE + fp16 table lookup, then the text graph)
val ids = bpe.encode("wheel") // [BOS, ..., EOT, 0-pad] x32
textIn[0].writeFloat(lookupEmbeddings(ids)) // [1,32,1024]
text.run(textIn, textOut)
// features + text -> detections
headIn[0].writeFloat(feats + textOut[0].readFloat() + padMask(ids))
head.run(headIn, headOut)
val y = headOut[0].readFloat()
val presence = sigmoid(y[1000])
// query q kept if sigmoid(y[q]) * presence > 0.5; box y[200+4q..], mask y[1001+q*288*288..]
```
## Usage (Python, CompiledModel)
```python
import numpy as np
from ai_edge_litert.compiled_model import CompiledModel
from ai_edge_litert.hardware_accelerator import HardwareAccelerator
vision = CompiledModel.from_file("sam3_vision.tflite", HardwareAccelerator.GPU)
text = CompiledModel.from_file("sam3_text.tflite", HardwareAccelerator.CPU)
head = CompiledModel.from_file("sam3_head.tflite", HardwareAccelerator.GPU)
def run(model, x, n_out):
ib, ob = model.create_input_buffers(0), model.create_output_buffers(0)
ib[0].write(np.ascontiguousarray(x, np.float32).ravel())
model.run_by_index(0, ib, ob)
return np.array(ob[0].read(n_out, np.float32))
feats = run(vision, image_1008, 256 * (288**2 + 144**2 + 72**2)) # (x/255-0.5)/0.5, NCHW
table = np.fromfile("sam3_token_embed.bin", np.float16).reshape(-1, 1024)
emb = table[token_ids].astype(np.float32) # CLIP BPE, ctx 32, 0-pad
mem = run(text, emb[None], 32 * 256)
pad = (np.array(token_ids) == 0).astype(np.float32)
y = run(head, np.concatenate([feats, mem, pad]), 1001 + 200 * 288 * 288)
prob = 1 / (1 + np.exp(-y[:200])) / (1 + np.exp(-y[1000]))
keep = np.where(prob > 0.5)[0] # boxes y[200:1000], masks y[1001:]
```
## Video tracker (stage 2)
`tracker/` holds the Object-Multiplex tracker graphs sharing one trunk pass:
`sam3_vision_tri.tflite` (trunk + detector/interactive/propagation necks),
`trk_memattn_n7.tflite` (memory attention, 7 spatial slots + 16 pointer frames),
`trk_maskdec.tflite` (16-object multiplex decoder), `trk_memenc.tflite`,
`trk_initdec.tflite`. The host state machine (detection↔track association, hotstart,
recondition, memory bank + temporal pos-enc) is ported and verified against the official
model (ids identical, mask IoU ≥ 0.992) — the executable spec and the Kotlin/Swift ports
live in the **LiteRT-Models** zoo sample (`sam3/`), together with all conversion scripts.
A 48-frame clip tracks end-to-end on an iPhone 17 Pro at ≈16.6 s/frame (vision 7.3 s,
memory attention 6.4 s, head 2.7 s on CPU, decoders <0.2 s) and at ≈2 s/frame on an
M4 Max — offline processing rather than real time.
## Conversion notes
Converted with **litert-torch**; every GPU-compatibility re-authoring is exact: the >4-D
ViT attention (silently mis-lowered otherwise) is rebuilt in ≤4-D with the interleaved RoPE
baked into the qkv weights; SafeLayerNorm handles the |x|≈300 residual stream; the DETR
decoder is batch-first rank-4 end-to-end (rank-3 `[1,N,C]` fan-outs mis-execute on mobile
GPUs); masked softmax uses the delegate-safe form; ConvTranspose necks are zero-stuff +
Conv2d. Details and the on-device debugging record ship with the sample app.
## License
SAM Materials, © Meta Platforms — redistributed under the **SAM License** (see `LICENSE`,
provided with these materials as the license requires). Built with SAM.
|