A newer version of the Gradio SDK is available: 6.20.0
title: Paint Match
emoji: 🎨
colorFrom: yellow
colorTo: red
sdk: gradio
sdk_version: 6.16.0
app_file: server.py
license: apache-2.0
short_description: Paint codes from kit photos — finetuned 1B VLM, no cloud
pinned: false
models:
- build-small-hackathon/paint-match-minicpm
tags:
- vision
- llama-cpp
- scale-modelling
- track:backyard
- sponsor:openbmb
- sponsor:modal
- achievement:offgrid
- achievement:welltuned
- achievement:offbrand
- achievement:llama
- achievement:fieldnotes
Paint Match
A finetuned 1-billion-parameter vision model running on a $50 ARM board identifies paint codes from scale model instruction sheets — no cloud API, no GPU.
Upload a photo of an instruction sheet or a shop screenshot. Paint Match extracts the paint codes, converts Humbrol references to Tamiya equivalents, and shows shop links. Paints you already own are flagged automatically.
Who it's for
I build plastic scale models. Every kit ships an instruction sheet listing paint codes in a manufacturer's own system (Humbrol, Tamiya, Meng), and matching those to what's actually on the shelf — and to what I already own — is tedious manual cross-referencing before every build. Paint Match is the tool I use on my own kits: photograph the sheet, get a Tamiya shopping list, with paints already in my Google Sheets inventory flagged so I don't re-buy them.
The UI is styled after Airfix Dogfighter — a 2000 PC game I played as a kid. The aesthetic felt right for a tool that's part of the same hobby.
How it works
- Photo is resized to 960px (A/B tested: 640px drops codes on small print; 1280px adds 30s with no recall gain)
- MiniCPM-V-4.6 finetuned on paint instruction data, runs via llama.cpp on a Radxa Dragon Q6A — 4 CPU cores, no GPU
- Fine-tuned on Modal.com H100 (16 min, ~391 training examples); training data scraped from Airfix instruction sheets and paper photos
- JSON schema constraint forces structured output; no regex fragility
- Humbrol→Tamiya conversion from a hand-curated CSV; inventory check via Google Sheets
- Inference: ~64s average (down from ~190s with the base InternVL model)
Benchmark (MiniCPM-V-4.6 finetuned, running on Radxa CPU)
| Metric | Score |
|---|---|
| F1 — benchmark (10 images) | 0.935 |
| F1 — shop holdout (53 images) | 0.927 |
| F1 — paper holdout (7 images) | 0.928 |
| Avg latency | ~64s |
Base model comparison (InternVL3.5-2B): F1=0.873, ~190s latency. Gemma 4B timed out on every instruction sheet image on this hardware.
Architecture
All inference is 100% local, on hardware I own. This HF Space is a thin proxy UI only — it holds no model and calls no hosted LLM API. Photos are forwarded over a Cloudflare Tunnel to a private Radxa SBC, where the finetuned 1B model runs on CPU via llama.cpp; the Space just renders the result. Off-grid where it counts: the AI never leaves the board.
Demo & social
- Demo video - https://youtu.be/mNMjyIMAUuo
- Social post - https://x.com/szwendacz/status/2064679708877291630
- Field notes - blog post