Downloads · 30 days
0
jax-image-tools/cellpose-sam-onnx
cellpose-sam-onnx is a image segmentation model from jax-image-tools. Use it for the image segmentation task on the model card, and read the license before you ship it in a product. It is set up for onnx. The card lists the license as bsd-3-clause.
Single-file FP16 ONNX export of Cellpose-SAM (CPSAM), the ViT-L–based cellular segmentation model from Stringer et al., 2025. Intended for in-browser inference via WebGPU through cellpose-js, but usable from any
Downloads · 30 days
0
Access
Public
Updated Aug 26, 2026
Repo size
617 MB
Likes
0
Public
Click a slice to open those files.
.onnx617 MB · 100%
From the Hugging Face model README
Single-file FP16 ONNX export of Cellpose-SAM (CPSAM), the ViT-L–based cellular
segmentation model from Stringer et al., 2025.
Intended for in-browser inference via WebGPU through
cellpose-js, but usable from any
ONNX Runtime backend that supports opset 18 and FP16 graph IO.
flow_y, flow_x, cellprob).mouseland/cellpose-sam
(1.23 GB PyTorch checkpoint, 304.6 M params).cpsam_fp16.onnx — 588 MB, self-contained (weights merged into
the graph, no external .data sidecar).float16.image: tensor(float16), shape (1, 3, 256, 256), RGB,
per-channel percentile-normalized to ~[0, 1].flows_cellprob: tensor(float16), shape (1, 3, 256, 256) —
channels are (flow_y, flow_x, cellprob).This is the same model as mouseland/cellpose-sam, just re-packaged as a
588 MB FP16 ONNX file that browsers can load and run on WebGPU. No retraining,
no pruning, no architecture changes. Numerical parity vs the PyTorch source is
1.24e-05 worst max-abs-error across 10 random tiles (gate 1e-3).
If you want a smaller model, this is not it — that's Phase 2 (SlimCPSAM), which has not been built yet.
gradient_tracking_3D routine is not part of the
export and is not represented in this graph.cellpose-js (recommended)import { Cellpose, configureOrt } from 'cellpose-js';
configureOrt({ wasmPaths: '/ort/' }); // serve ORT WASM sidecars same-origin
const cp = await Cellpose.fromPretrained(
'https://huggingface.co/jax-image-tools/cellpose-sam-onnx/resolve/main/cpsam_fp16.onnx',
{ preload: true },
);
const result = await cp.segment(
{ data: imageData.data, width, height, channels: 4 },
{ diameter: 30, cellprob_threshold: 0, chan: 0, chan2: 0 },
);
// result.masks: Uint32Array — instance label map at source resolution
The first call fetches 588 MB from the Hub; subsequent calls hit IndexedDB and cold-start in under ~2 s.
See the cellpose-js README for the full API, parameter reference, and Python parity notes.
import numpy as np
import onnxruntime as ort
sess = ort.InferenceSession("cpsam_fp16.onnx", providers=["CPUExecutionProvider"])
tile = np.random.rand(1, 3, 256, 256).astype(np.float16)
out = sess.run(None, {"image": tile})[0] # (1, 3, 256, 256) float16
flow_y, flow_x, cellprob = out[0, 0], out[0, 1], out[0, 2]
For flow-dynamics postprocessing (Euler integration → convergence clustering → connected components → size/flow filtering), use either:
cellpose-js/src/dynamics, orcellpose.dynamics — input/output
contracts match.Because the graph IO is FP16, ORT-web needs the native Float16Array
typed-array, not a Uint16Array bit-pattern. That requires:
'gpu' in navigator). No WASM fallback in v1 of the
consumer (cellpose-js) — see "Why not FP32?" below.Older browsers fail fast with a clear error in cellpose-js. For direct ORT
use, ORT will throw on session create or input binding.
Measured end-to-end through cellpose-js:
| Step | Time |
|---|---|
| Cold model fetch (588 MB, CDN) | ~5 s |
| Warm fetch (IndexedDB) | < 100 ms |
ort.InferenceSession.create | ~1.3 s |
| Cold shader compile (first forward) | ~2.3 s |
| Steady-state per-tile inference (256×256) | ~277 ms |
| Per-tile preprocess (normalize + tile copy) | ~14 ms amortized |
| Full-image flow dynamics (400×400) | ~74 ms |
ORT-web 1.26 is ~2.3× faster than 1.20 on the WebGPU kernels — the steady-state 277 ms number is on 1.26. Stage 0 originally measured 628 ms/tile on 1.20.
The export path is documented in
docs/STAGE0-RESULTS.md
and docs/PLAN.md §1.5, §2.
The short version:
mouseland/cellpose-sam (PyTorch, 1.23 GB, 304.6 M params).cellpose.vit_sam.Transformer (this is not a HuggingFace
Transformers class — optimum-cli does not apply here).Transformer(dtype=torch.float16) then
load the FP32 checkpoint and cast. Post-export FP16 conversion via
onnxconverter-common or onnxruntime.transformers.float16 produced
broken graphs on the dynamo-exported topology (dangling FP16→FP32 type
mismatches and duplicate node names respectively) — re-exporting from a
natively-FP16 nn.Module is the only path that worked.torch.onnx.export(..., dynamo=True, strict=True) at
opset 17 (auto-upgraded to 18 by the dynamo exporter). Requires onnxscript
as an extra dependency. strict=False failed; strict=True succeeded.dynamic_axes: batch only. H/W are hardcoded to 256 by the dynamo
exporter — acceptable because CPSAM is always tiled at 256×256.onnx.save_model(..., save_as_external_data=False). The 588 MB result fits
comfortably under the 2 GB protobuf limit, so the browser fetches one file
instead of .onnx + .onnx.data.(1, 3, 256, 256) FP32, seed 0): worst max abs error 1.24e-05, mean
8.96e-06. Gate was 1e-3.The PyTorch and exporter versions used: torch 2.12.0, cellpose 4.1.1,
onnx 1.21.0, onnxruntime 1.26.0, onnxscript (latest at export time).
mouseland/cellpose-samIt is the same network, same weights, same outputs — only the serialization format differs. Specifically:
| Aspect | mouseland/cellpose-sam (PyTorch) | This repo (ONNX FP16) |
|---|---|---|
| Format | PyTorch .pt checkpoint | ONNX, single file |
| Size | 1.23 GB | 588 MB |
| Precision | FP32 | FP16 |
| Runtime targets | PyTorch (Python only) | ORT WebGPU/CUDA/CPU/CoreML/DirectML |
| Input dtype | float32 | float16 (native Float16Array) |
| Input shape | Variable; CPSAM tiles internally | Fixed (1, 3, 256, 256) |
| Postprocessing | Bundled in cellpose.dynamics | Not included — caller's job |
| 3D segmentation | Yes (gradient_tracking_3D) | No — 2D only |
| Promptable | No (CPSAM is dense regression) | No (unchanged) |
Numerical: worst observed max abs error vs the FP32 PyTorch reference on the same input is 1.24e-05 — the FP16 export is numerically indistinguishable from the original at the granularity that matters for downstream flow dynamics.
What's not here:
cellpose-js
(TypeScript port, ~500 LOC) and cellpose itself (Python). Output of this
ONNX graph is raw (flow_y, flow_x, cellprob) — you still need to turn that
into instance masks.cellpose-js does this transparently with 32-px overlap.Float16Array
is non-negotiable for FP16 graph IO under ORT-web 1.20+.If you use this model, please cite the original Cellpose-SAM paper:
Stringer, C., Pachitariu, M. et al.
Cellpose-SAM: superhuman generalization for cellular segmentation.
bioRxiv 2025.04.28.651001 (2025).
https://www.biorxiv.org/content/10.1101/2025.04.28.651001v1
mouseland/cellpose-sam on Hugging Face Hub.52fd6881…) are recorded in
docs/STAGE0-RESULTS.md.tests/fixtures/ in the cellpose-js repo.cellpose-js consumer library: MIT (compatible).cellpose-js, and this card: @belkassaby
(HF: ballon999) — same person, different
username on each platform.TheJacksonLaboratory/cellpose-js — TypeScript inference + dynamics port.cellpose-js.MouseLand/cellpose and mouseland/cellpose-sam.