ML / Vision · 2025
Portrait Batch Analyser
A desktop GUI app for portrait shoots. Drop in a folder of frames and it does the boring shoot-day work: straightens each frame on the subject's face, crops everything to a reference you mark once, sorts by person, and flags the closed-eye shots.
What it is
When you shoot portraits, you come back with hundreds of nearly-identical frames per person. Sorting them is the slowest part of the day — every frame has to be levelled, cropped the same way as the others, grouped by who's in it, and the blink shots set aside. Most of that is mechanical.
This app is a desktop GUI you run on the laptop next to the camera. Drop in a folder, click a reference crop on one frame, and it applies the same workflow across every other frame. No upload, no internet, photos never leave the machine.
How it works
Built in Flutter as a desktop app, with the ML pipeline running locally. Four passes per batch:
- Straighten. ML Kit returns eye and nose landmarks for each face; an affine transform maps them onto a canonical axis and rotates the frame to match.
- Reference crop. You crop one frame by hand. The crop box, anchored to the same landmarks, is replayed across every other frame in the batch.
- Sort by person. A TF Lite face-embedding model produces a vector per face; cosine similarity plus a threshold buckets the frames into per-person folders.
- Closed-eye filter. ML Kit's per-eye openness probability flags frames below threshold. Flagged, not deleted — the photographer reviews.
Why a desktop GUI instead of a web app: the workflow runs on a laptop next to the camera mid-shoot, and the photographer wants their files staying local. Flutter on desktop with ML Kit and TF Lite bindings keeps it single-binary, no server, no upload step.
Where it's at
Early prototype. Real-world test on my own shoots; not packaged for general release. The face embedding is a general checkpoint, not fine-tuned, so the per-person threshold needs adjustment for tricky lighting. Closed-eye detection uses ML Kit's built-in classifier and misses half-blinks. The pair is the look-match half — the Lightroom Preset Extractor.