mlboydaisuke commited on
Commit
b07559d
Β·
verified Β·
1 Parent(s): c908b55

SAM2.1 Hiera-Tiny LiteRT (CompiledModel GPU), corr 1.0

Browse files
Files changed (4) hide show
  1. README.md +91 -0
  2. sam2_decoder.tflite +3 -0
  3. sam2_encoder.tflite +3 -0
  4. sam2_prompt.bin +3 -0
README.md ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: litert
4
+ pipeline_tag: mask-generation
5
+ tags:
6
+ - litert
7
+ - sam2
8
+ - segment-anything
9
+ - image-segmentation
10
+ - on-device
11
+ - gpu
12
+ base_model: facebook/sam2.1-hiera-tiny
13
+ ---
14
+
15
+ # SAM 2.1 Hiera-Tiny β€” LiteRT (CompiledModel GPU)
16
+
17
+ [SAM 2.1](https://ai.meta.com/sam2/) (Segment Anything 2, Meta) Hiera-Tiny converted to
18
+ **LiteRT** and running fully on the **GPU** via the `CompiledModel` API (ML Drift). Tap a
19
+ point on an image and it returns a segmentation mask β€” the image encoder runs once per image,
20
+ the mask decoder runs per point.
21
+
22
+ Both graphs are **fully GPU-accelerated** on the Pixel 8a (Mali / ML Drift) and on Apple
23
+ silicon (Metal), and the output is **bit-exact (corr 1.0)** vs the original PyTorch SAM 2.1.
24
+
25
+ ## Files
26
+
27
+ | File | Size (fp16) | Input | Output | Runtime |
28
+ |---|---|---|---|---|
29
+ | `sam2_encoder.tflite` | 80 MB | `[1, 3, 1024, 1024]` NCHW | flat `[1, 4194304]` (`image_embed \| fpn0 \| fpn1`) | CompiledModel GPU |
30
+ | `sam2_decoder.tflite` | 17 MB | flat `[1, 4194816]` (`image_embed \| sparse \| fpn0 \| fpn1`) | masks `[1, 3, 256, 256]` | CompiledModel GPU |
31
+ | `sam2_prompt.bin` | 3 KB | β€” | prompt-encoder constants for the Kotlin point encoder | β€” |
32
+
33
+ Preprocessing: resize to 1024Γ—1024, ImageNet mean `[0.485, 0.456, 0.406]` / std
34
+ `[0.229, 0.224, 0.225]`, NCHW.
35
+
36
+ ## GPU compatibility
37
+
38
+ The Hiera image encoder is made GPU-clean with three numerically-identical rewrites (done at
39
+ conversion time; the SAM 2 mask decoder converts unchanged):
40
+
41
+ 1. **Bake the windowed positional embedding** (constant for a fixed 1024Β² input) β€” removes the
42
+ bicubic `interpolate` (GATHER_ND) and the tiled window embed (BROADCAST_TO).
43
+ 2. **4-D window partition / unpartition** β€” the 6-D `view`+`permute` becomes split-H β†’ transpose
44
+ β†’ split-W (ML Drift rejects > 4-D tensors).
45
+ 3. **4-D multi-scale attention** β€” the 5-D fused `qkv` reshape becomes a channel-wise q/k/v slice.
46
+
47
+ ## Usage (Kotlin, LiteRT CompiledModel)
48
+
49
+ ```kotlin
50
+ import com.google.ai.edge.litert.Accelerator
51
+ import com.google.ai.edge.litert.CompiledModel
52
+
53
+ val encoder = CompiledModel.create(
54
+ context.assets, "sam2_encoder.tflite", CompiledModel.Options(Accelerator.GPU), null)
55
+ val decoder = CompiledModel.create(
56
+ context.assets, "sam2_decoder.tflite", CompiledModel.Options(Accelerator.GPU), null)
57
+
58
+ // Encode once per image (input = normalized NCHW floats).
59
+ val encIn = encoder.createInputBuffers()
60
+ encIn[0].writeFloat(inputFloats) // 3 * 1024 * 1024
61
+ val flat = encoder.run(encIn)[0].readFloat() // [image_embed | fpn0 | fpn1]
62
+
63
+ // Build the flat decoder input [image_embed | sparse | fpn0 | fpn1] (sparse = point encoding
64
+ // from sam2_prompt.bin), then run the decoder per tap.
65
+ val decIn = decoder.createInputBuffers()
66
+ decIn[0].writeFloat(flatDecoderInput)
67
+ val masks = decoder.run(decIn)[0].readFloat() // (3, 256, 256) logits; mask > 0 = foreground
68
+ ```
69
+
70
+ ## Usage (Python, verify the graph)
71
+
72
+ ```python
73
+ from ai_edge_litert.interpreter import Interpreter
74
+ import numpy as np
75
+
76
+ enc = Interpreter(model_path="sam2_encoder.tflite"); enc.allocate_tensors()
77
+ enc.set_tensor(enc.get_input_details()[0]["index"], pixels_nchw.astype(np.float32)) # [1,3,1024,1024]
78
+ enc.invoke()
79
+ flat = enc.get_tensor(enc.get_output_details()[0]["index"]).flatten() # image_embed | fpn0 | fpn1
80
+ ```
81
+
82
+ ## Conversion
83
+
84
+ Converted with `litert-torch` from the Hugging Face `transformers` SAM 2 model. The full
85
+ conversion script (and Android sample app) is in
86
+ [LiteRT-Models](https://github.com/john-rocky/LiteRT-Models) β†’ `sam2/`.
87
+
88
+ ## License & credits
89
+
90
+ Apache-2.0, following the original [SAM 2](https://github.com/facebookresearch/sam2) (Meta,
91
+ Apache-2.0). Conversion by [@john-rocky](https://github.com/john-rocky).
sam2_decoder.tflite ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f00e15545c887e20a2886cb88f6afab92ceb8e35a81e9fbf67629cf1de56902d
3
+ size 16866608
sam2_encoder.tflite ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:433d488bbf13116bf45f51e98efdfd2c047c48aa2693366079a1fdf73b101b1d
3
+ size 79847760
sam2_prompt.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c1ac798f0cc0bd5e4b0dc94efe26f2f9dfe4d1d4cec141ab0350580ce7a48588
3
+ size 3072