Groundwork

Open source · AGPL-3.0 · self-hosted — your photos, your models, your machines. No cloud, no account, no telemetry.

Teach a computer to count
anything you can photograph.

Label by clicking. Train on your own GPUs — one machine or a fleet. Every run is judged on a frozen holdout. Serve it on the web, over the API, or from a chat bot that gathers tomorrow's training data while it works.

View on GitHub Run it tonight

The editor over a real production photo: 286 tablets, a dot on every one

How it works

The dot editor over a real production photo: 69 capsules on a tray, one dot each

Click once per object.

That's labeling — here, a real production photo: 69 capsules, 69 dots. The count in the corner is the label; switch to boxes when extent matters. An optional auto-labeler drafts the dots so you correct instead of starting from zero.

The Train tab mid-run: model, machine and card chosen, live progress below

Model × machine × card.

Training is one control across every GPU you own, and refusals carry reasons: a card the build can't drive is greyed with why; a card that's too small warns before it spills. Live progress, honest ETAs, and a wedge detector that reads CPU ticks — not vibes.

Results: runs ranked by count error on the frozen holdout

One frozen exam for every run.

Models are ranked by count error on a holdout that is never trained on — with tied operating points and grid edges reported, so "best" is never a quiet tie-break. Apache-2.0 challenger families sit the same exam as the champion: pick by evidence, and ship a permissively licensed model the day it proves out.

Serving: upload a photo, get the count and overlay back

Serve it everywhere.

Count in the browser, over the REST API, or through a Telegram bot — which works from day zero: before your first model exists it collects photos straight into the labeling queue, and the moment a run finishes it starts answering with counts. Full API reference →

Try a model in your browser

This is the washers model from the screenshots above — trained on fully synthetic images, exported to ONNX, running entirely in your browser. Your photo never leaves this page.

Drop a photo, or tap to shoot one

This one only knows round hardware — washers, coins, buttons. Want hammers? Screws? Seedlings? That's the whole product: photograph a few dozen, click-label them, and train your counter on any GPU you've got.

  • solid, contrasting background
  • spread things out — minimal overlap
  • shoot top-down, fill the frame

The model (~25 MB) loads on first use. Trained only on synthetic renders — flat, scattered scenes like these samples. Real-world piles want real training photos; that's the product.

No washers handy? Try one:

Proven behind a real counter

Groundwork's first production model counts pills in a working pharmacy — photos arrive by chat, a person verifies every count, and corrections flow back into training. The same trained weights run on-device (an iOS app counts 121 in 33 ms) and live on a Raspberry Pi 5 bench camera, and recent runs count exactly on 95–100% of a frozen 69-photo holdout.

count error / photo0.000.050.10first perfect score →run 25run 36run 68
Count error per photo across 44 consecutive runs of the same frozen exam — zero by the twelfth run. The chart is real ledger data; the case study tells the whole story, including what to do when a model outgrows its exam.
Live at the edge — the same trained weights counting in real time on a Raspberry Pi 5 bench camera.

Not a medical device — every count is checked by a person; the tooling exists to make that verification effortless.

See the full build log — day-zero collection, the frozen-holdout exam, and the phone + Pi deploys →

Run it tonight

shell
git clone https://github.com/gammahazard/groundwork
cd groundwork/docker
docker compose up

One compose up.

Linux, or Windows via WSL2 / Docker Desktop. A GPU is only needed to train — projects, labeling and review all work without one. The first-run wizard takes it from there: admin account, first project, optional extras.

on the GPU box
curl -fsSL http://your-hq:8000/join.sh \
  | bash -s -- http://your-hq:8000 gwj_…

A fleet in one paste.

Mint a join command on your HQ, run it on any GPU machine: it installs itself from your HQ, exchanges keys, gets its cards probed, and appears in the Train matrix — verified. Datasets sync before every remote run; finished runs are adopted home into one ledger.