Case study
Livery Design AI
Vision-LLM pipeline that turns photographs of physical decals into vector assets and composes AI-planned liveries onto product templates.
- Role
- Owner — AI pipelines and all prompt engineering
- Domain
- Generative AI & LLMs · Backend & APIs · Cloud & Production
- Stack
- Python · FastAPI · Anthropic Claude · OpenAI gpt-image · OpenCV
- Result
- ~75s livery composition pipeline
Overview
Two AI pipelines behind one design tool. One turns a photograph of a decal into a clean vector asset; the other has a vision model plan a colour scheme and layout that a deterministic renderer composites onto a product template. In UAT with a small group of users.
The model proposes. Deterministic code disposes.
The problem
Custom artwork meant tracing each decal and laying out every design by hand — and the layout rules were rewritten for every new template, so the work never compounded. A vision model can do the creative part, but its output cannot be sent to print as-is.
Two pipelines
Independent arms behind one API. Extraction produces assets; composition consumes them. Separate, so a failed extraction never corrupts a layout and either can be rerun alone.
Extraction
A photograph in, a clean vector asset out.
- Vision classifier gates what runs next
- Decal reproduced in isolation on a clean field
- Automatic review of the reproduction
- Background removal, then raster to SVG
Composition
Assets in, a finished design on the template out.
- Vision model returns a JSON plan — theme, colours, placements, paint
- Guard passes correct the plan
- Regions derived from the template's geometry
- Composited back to front with protection masks
Every failure became a guard
Prompting reduces how often a model gets something wrong; it never reaches never. Each recurring failure was turned into a named, testable correction instead of a longer prompt.
- What the model producedDark detail on a dark body — trim that vanished on the product.
- The guard that corrects itDetail-visibility lift: contrast between detail and body is checked and raised.
- What the model producedBody colours too extreme to carry detail at all.
- The guard that corrects itMid-tone clamp: the body is held in a range where anything placed on it reads.
- What the model producedTwo elements planned into the same region.
- The guard that corrects itZone-collision correction: placements are validated against template regions and moved.
- What the model producedGradients strong enough to flatten the form.
- The guard that corrects itGradient softening: ramps are limited before rendering.
My Role
Role
Owner — AI pipelines and all prompt engineering
Contribution
- Built the extraction arm: vision classification, AI image reproduction of an isolated decal, automated review, background removal, and raster-to-vector conversion
- Built the composition arm: a vision-LLM planner that reads the assets and returns a structured JSON design plan — theme, colour scheme, placements and parametric paint primitives
- Built a data-driven SVG engine that composites the plan onto templates with window-protection masks and explicit Z-ordering
- Wrote deterministic guard passes that correct model output — mid-tone body clamp, detail-visibility lift, zone-collision correction
- Added a composition-fallback layer that generalises rendering rules to new templates with no per-template code
- Instrumented per-call token and cost tracking across every API call
Team Context
Owned the AI pipelines and prompt work within a wider product backend.
Decisions
Ask for a plan, not a picture.
The output is print-bound, so geometry must be exact and editable. A generated image looks right and cannot be measured, corrected or re-exported. A plan can be validated and re-rendered without another API call.
- Instead of
- Image model renders the finished design
- Freeform text the renderer parses
Derive placement regions from template geometry.
Per-template rules were the original complaint. Regions are computed as proportions of the template, so an unseen one renders with no new code — with a kill-switch for templates that genuinely are special.
- Instead of
- Hand-authored regions per template
- One fixed layout
Seed variety through rotating design archetypes.
The models in use reject a temperature parameter, so the usual lever is gone. Rotating an archetype through the prompt varies designs along an axis a designer can name, which sampling does not.
- Instead of
- Temperature sampling
- Accept repetitive output
Engineering around the model
- Credit-free iteration
- Saved plans re-render through the real pipeline with no model call, so renderer changes cost nothing to test.
- Honest failure codes
- Provider errors classified into billing, auth, rate limit and outage — a caller can retry the retryable and stop on the rest.
- Per-call accounting
- Tokens, cost and stage logged on every call, so an expensive run traces to the step that caused it.
- Real-world inputs
- Phone-camera formats normalised on upload, with retries and streamed progress for long image operations.
Results
~75s
livery composition pipeline
~200s
asset extraction pipeline
How it is measured
- Measured
- Wall-clock latency per pipeline, instrumented per call alongside tokens and cost.
- Method
- Per-call instrumentation across real runs, not a controlled benchmark.
- Quality
- Assessed by UAT users reviewing rendered output. There is no labelled set and no ground truth for a good design.
What I Learned
- Wrapping a creative model in deterministic correction beats prompting it into submission. A guard is a named, testable rule; a longer prompt is neither.
- Ask for a plan, not an artefact, when output must be exact. A plan can be corrected; an image can only be regenerated.
- Make iteration cheap early. The credit-free harness paid for itself in days and changed how much I was willing to try.
Limits
The honest weak point: no fidelity metric for extraction and no scored evaluation of design quality — both need a labelled set and a rubric, and neither exists. Latency is instrumented, not benchmarked under load. The system is in UAT with a handful of users, so none of this is production-scale evidence.
What I'd Improve
- Build a labelled evaluation set and score extraction fidelity. Quality is asserted, not measured. First fix.
- Add a golden-render regression test, so a change that silently degrades output fails the build.
- Benchmark both pipelines under controlled conditions rather than averaging live runs.
- Cache planner output across similar inputs — many runs re-plan nearly identical work.