Skip to content
← All writing

Plant Identifier: naming a plant with no signal

  • Computer Vision
  • Python
  • Flutter
  • Android

Source →

Where this came from

I was walking through a park, and there were flowers I didn’t recognise everywhere. I wanted to know what they were.

I had a phone in my hand with a good camera and several apps that would have answered instantly. I also had no signal.

That’s the part that stuck with me. It wasn’t that the technology didn’t exist — it was that all of it lived somewhere else. Every plant identification app I could find was a thin client over an API: photograph the thing, upload it, wait for a server to think about it. Which works beautifully in a café and not at all in the middle of a park, and a park is where the plants are.

The problem I actually wanted solved had a constraint attached to it, and the constraint was the whole problem: it has to work with the network off.

What that constraint costs

Deciding the model runs on the phone is one sentence and a great deal of consequence.

A server has as much memory as you’re willing to pay for, a GPU if you want one, and no particular reason to care whether your model is 40 MB or 400 MB. Move the same job onto a phone and every one of those goes away. The model ships inside the app, so its size is something a user notices at install time. Inference runs on whatever processor is in their hand. There’s no opportunity to quietly swap in a better model next Tuesday — whatever you shipped is what they have.

What you get in exchange is the only thing I cared about: it answers in a park.

That trade is the entire design. Accuracy that requires a round trip is worth less, to me, than slightly worse accuracy that works where the plants are.

Why end to end mattered

It would have been easier to stop at a notebook with good validation accuracy. Nearly every tutorial does, and I’d have learned the model-building half.

The half I’d have missed turned out to be the harder one. A model in a notebook runs on your machine, on images you curated, with as much time as it wants. A model in an app runs on a phone, on a photo someone took at a bad angle in poor light, and has to answer fast enough that the user doesn’t assume it’s broken. Export, quantisation, size, on-device inference, and what to show when the model genuinely isn’t sure — none of that appears in a training script, and all of it is what separates a model from a thing you can use.

Which is roughly why I built it. Not because plant identification is unsolved — it obviously isn’t — but because solving it under a constraint the existing apps had chosen not to accept meant I couldn’t copy any of them.