CellSeg
CellSeg

Three months ago I started building an Android app to count cells. Today the first public build is up, and I’d like to introduce it properly.

Thank you for reading this post, don't forget to subscribe!

It’s called CellSeg, and it does one stubborn small thing: it lets a bench scientist take a picture of a microscopy sample with their phone and get a cell count out of it in a few seconds, on the device, with no laptop and no cloud round-trip in the way.

You can install it from cellseg.yaylali.uk. It’s an open-source sideload APK — not on the Play Store yet — under MIT licence, with no ads, no tracking, no in-app purchases, and no plans for any of those things. It runs on Android 8.0 and up. The whole thing weighs about 15 MB plus a one-time 14 MB model download.

If you’ve been following along from the build-in-public post a few weeks ago, this is the moment that one was pointing at. If you’re new here, here’s the rest of the story.

What it does, plainly

You open the app on a phone next to a microscope. You tag the sample — sample ID, magnification, channel, optional fields like passage and well — and either capture an image through the eyepiece with your phone camera, or import a TIFF the microscope already exported. You hit Run. A few seconds later you have an outlined image, a count, a confluence percentage, mean and median cell area, and a density estimate in cells per cm². Tap Export and the run is in a CSV.

Run history lives on the device. You can search it by sample ID, filter by mode, batch-process a folder of images with one set of parameters, and export everything together. The app will not lose your data. The app will not send your images anywhere unless you explicitly tell it to.

That’s basically the whole product. It’s not trying to replace ImageJ, CellProfiler, or a real Cellpose Python pipeline running on a workstation. It’s trying to fit into the rhythm of bench work — the part of the day where you have gloves on, an eyepiece in front of you, and you’d like a number now rather than after three context switches.

How it works, briefly

There are two segmentation modes and the user picks per run.

On-device is the default. The app downloads the Cellpose 3 cyto3 model once on first launch — about 14 MB in ONNX FP16 format — and runs it locally via ONNX Runtime, with hardware acceleration through the phone’s NNAPI. On a Pixel-7-class device, the network forward pass is well under a second; the slower step is the post-processing that turns Cellpose’s flow-field output into actual instance labels, which I had to port from the reference NumPy implementation into Kotlin and which takes 2–4 seconds depending on cell count and image size. End-to-end from tap-to-result is single-digit seconds for a typical 1024×1024 image.

Cloud is opt-in. It hands the work over to Cellpose-SAM running on Hugging Face Spaces — a much larger and more accurate transformer model that’s too big to run on a phone. Same UI, same parameters, same metrics, same export. The difference is accuracy on harder cases at the cost of needing a network round-trip and somebody else’s GPU. You choose where each run happens with a small chip near the Run button.

The two modes share everything downstream: the metrics calculation, the Room database for run history, the CSV export, the sample-tagging UI. Only the inference layer differs. That made the architecture reasonable to test, and it means the on-device path can be improved later without disturbing the cloud path or vice versa.

Why I went small first

A natural question is “why ship the smaller model first?” The honest answer is friction. The friction the app is trying to solve isn’t fundamentally about cellpose-vs-cellpose-SAM accuracy — it’s about the gap between “I have an image” and “I have a number in the lab notebook”. Most of that gap is context switches and bad WiFi in basement microscope rooms, not model performance. A workflow that requires a network round-trip per attempt is a workflow people abandon after the third try, regardless of how good the model is on paper. Local inference makes parameter sweeps free. It makes offline use real. It makes the app something a user can rely on without thinking.

Cloud-mode Cellpose-SAM is there for the cases where local cyto3 isn’t accurate enough — and there are real cases where that’s true, particularly on imaging modalities cyto3 wasn’t well-represented in. But it’s the optional fallback, not the default.

The licensing chapter, which is the part I’m proudest of

This is the part of the post I most want to write carefully, because it might be the most useful thing in here for other people building on Cellpose.

Earlier this year I emailed Marius Pachitariu at HHMI Janelia explaining what I wanted to build, that the app would be free and open-source under MIT, that it would attribute Cellpose prominently, and asking specifically about both the cloud client and the cyto3 ONNX redistribution. Cellpose-SAM was trained on data licensed CC-BY-NC, and a pessimistic read of that licence had been the single biggest unknown in the project for me — pessimistic enough that I’d been planning the whole architecture around the assumption that the app could only ever be free.

Marius replied within a couple of hours: yes, with attribution and licence propagation, both are fine. Then his colleague Mike Perham — Janelia’s Director of Innovations & Open Science — sent a follow-up clarifying that the upstream chain (back through Cellpose-SAM to Meta’s original SAM weights) is under fully permissive licences that allow commercial applications, and that the CC-BY-NC notice in the upstream README applies to the training data used to retrain SAM into Cellpose-SAM, not to the resulting model weights themselves.

So the actual situation, for anyone else building on Cellpose: the codebase is BSD-3, the cyto3 weights are redistributable with attribution and licence propagation under permission directly from the maintainers, and the SAM-derived weights chain is permissive enough for commercial work if you ever wanted to go that direction. CellSeg’s choice to stay free and ad-free is now a product choice on my end, not a licence-imposed constraint. That distinction matters because I want it to be clear to anyone reading this that the option exists for someone else to build a different product on top of these models — and that the path through the maintainers is much more straightforward than a pessimistic reading of the upstream README would suggest.

The full attribution and propagation block is on the Hugging Face model card and on the About page. I’d encourage anyone redistributing Cellpose-derived models to use similar wording — Marius and Mike’s generosity here is exactly the kind of thing that gets eroded if downstream projects don’t honour it visibly.

What v0.1.0 isn’t, yet

This is an early build. Things I haven’t done yet, in rough order of how soon I’ll get to them:

It’s sideload-only, not on the Play Store. Closed testing has to happen first; that’s a 14-day Google requirement before production submission. I’ll be recruiting testers in the next couple of weeks.

Multi-page TIFFs (Z-stacks) aren’t supported yet — the app currently rejects them with a clear message rather than silently flattening. 3D segmentation is a separate problem and I’d rather not fake it.

Calibration values for cells/cm² density are entered manually per magnification right now. Auto-calibration via stage micrometer image is planned for v0.2.

The cloud mode requires you to either use the public Cellpose-SAM Space (free but rate-limited) or duplicate it into your own Hugging Face account for higher quotas. I don’t proxy this through any backend of mine, partly for cost reasons and partly because I’d rather not be in the data path between users and Hugging Face.

There are no screenshots on the website yet. I know. They’ll appear this week.

How to install, in 30 seconds

Go to cellseg.yaylali.uk/download. On your Android phone, allow your browser to install unknown apps (Settings → Apps → Special app access → Install unknown apps). Tap the Download APK button on the page. Open the file, tap Install. Launch the app, accept the Cellpose attribution acknowledgement, and tap “Download model” when prompted. Wi-Fi is recommended for the model download.

Or, if you trust me less than you trust the source, the GitHub repo has the source, the build instructions, and the SHA-256 hashes for the release artefacts so you can verify the APK before installing.

What I’d love feedback on

If you install it and use it on real samples, the things I most want to hear about: cell types where cyto3 disagrees with you, error states that aren’t clear enough, and missing fields in the sample-tagging UI that would make the app usable in your workflow when it currently isn’t. Open an issue on GitHub, or email me at [email protected] if a public issue isn’t appropriate.

I’ll keep writing about this as it develops — the on-device pipeline in detail, the Play Store submission process, what real bench testing turns up. None of it is “this problem is solved” — it’s all “this is what I’m working on and what I’ve learned this week.”

Thanks for reading. And thank you, especially, to Marius Pachitariu and Mike Perham for the kindness of their reply. There’s a version of this project that doesn’t exist because the email never got answered, and I don’t take for granted that the version that does exist, does.

— Kemal

By Kemal

A bioprocess engineer, modeler, machine learning dreamer.