The situation

The client is building a product for car dealerships: employees photograph vehicles on the forecourt with an ordinary phone, and the images come back looking as though the car had been shot in a professional studio. Dealers currently either pay for real studio photography, which does not scale to a forecourt turning over hundreds of vehicles, or list cars photographed against wheelie bins and other people's number plates, which measurably depresses click-through on the listing sites.

What they asked us for was the whole thing: web dashboard, iOS and Android capture apps, multi-tenant accounts, subscriptions and credits, an internal admin console, and eventual DMS integrations. What we quoted was one piece of it.

Why off-the-shelf didn't fit

The client had prototyped with a general-purpose image-to-image model and a prompt describing a studio, and the results were the reason they called us. At a glance the outputs were excellent. On inspection they were unusable, and specifically: a car with aftermarket black alloys came back with different alloys. A trim line moved. A dealer-fitted tow bar disappeared entirely. Most seriously, a scuffed bumper came back clean.

This is not a prompt problem or a model-quality problem and it does not get better with a larger model. A diffusion model asked to produce an image of a car produces a car. It resamples every detail from its own distribution, and the details it is least confident about are exactly the ones that make this specific vehicle that specific vehicle. The same property means it will not be consistent between angles: generate the front three-quarter and the rear three-quarter separately and you get two cars that resemble each other.

For a UK dealer the damage case is not merely a quality issue. An advertisement that materially misrepresents the condition of a vehicle is a consumer protection problem, and a pipeline whose failure mode is quietly removing a scratch is a pipeline that manufactures that problem at scale, unattended, across an entire inventory. We said so on the scope call, and it reframed the project for the client more than any technical argument did.

Scoping the real workflow

Two things came out of scoping, and the first was a refusal. We do not build multi-tenant SaaS platforms with billing and mobile apps. It is not what we are, and a team that ships one agent workflow at a time is the wrong team to hand a twelve-month product build. We said that in the first twenty minutes rather than at quote stage. What we offered instead was the imaging pipeline as a service their own platform and apps would call: images in, finished images out, with a documented API and webhooks. Their existing development team built everything around it. That split is in the scope document as an explicit boundary, including what we are not responsible for.

The technical reframe came second, and it is what made the project viable. The requirement is not "generate an image of the car in a showroom." It is "put this car in a showroom." Those sound alike and lead to opposite architectures. If the vehicle's own pixels are preserved and only its surroundings are replaced, identity preservation stops being a quality metric you fight for and becomes a property of the design. The car cannot change, because nothing generative ever touches it.

That decided everything downstream: segmentation and compositing as the core, environments pre-rendered rather than generated per request, and generative models confined to narrow, masked roles where they cannot reach the vehicle.

<8sec
Median time to a finished image
0
Generative passes over vehicle pixels
6 wks
Scope call to production API

What we built

The pipeline runs in stages. Instance segmentation locates the vehicle, followed by a matting pass that refines the boundary. The real difficulty sits here, because the useful edges of a car are wheel spokes, aerials, wing mirrors and the gap between a spoiler and the boot lid, and a mask that is merely good produces an image that reads as fake without the viewer being able to say why. The vehicle's pixels are then carried through the rest of the pipeline unmodified.

Environments are pre-rendered rather than generated. Each showroom is a set of rendered plates with known camera positions and known lighting, which buys three things at once: a given showroom looks identical on every vehicle a dealer processes, the output is deterministic, and there is no per-image generation cost for the background. Adding a showroom is an asset task, not a model task, which is what the client needed for the custom dealer-branded environments on their roadmap.

Realism comes from harmonisation, not generation. The vehicle is white-balanced against a reference and regraded to the target environment's lighting; a contact shadow and a soft cast shadow are synthesised from the estimated ground plane and the environment's key light; and a floor reflection is composited at a reflectance matched to the plate. This is compositing work of the sort that has existed for decades, and it is the right tool: physically grounded, fast, and incapable of hallucinating.

Generative models appear in exactly one place: inpainting the small background region left behind when foreground clutter is removed, always masked strictly away from the vehicle. That mask is enforced in code rather than by prompt.

Consistency across the eight angles is not a feature we implemented. It falls out of the architecture, because the same captured car appears in every shot and no shot regenerates it.

Where it got hard

Glass was the first real problem and the one that took longest. A car's windows are semi-transparent, so a naive mask carries the original forecourt through them: the finished image shows a car sitting in a pristine studio with a Renault Clio and half a wheelie bin visible through its rear window. Viewers cannot say why the image looks wrong, and do not trust it. Glazing is now detected and handled as a separate layer, with the new environment composited through it at a measured transmission while the original specular reflections on the glass are retained, because glass with no reflections reads as an empty hole.

Colour cast was invisible to us until we looked at a large sample. A car photographed outdoors on an overcast British afternoon carries a cool, flat cast across its whole body; the same car photographed in low sun carries a strong warm one. Dropped unmodified into a neutral studio plate, both look subtly wrong, because the vehicle does not belong to the light in the scene. The normalisation step that fixes it has to be careful in one specific way: it must not correct the vehicle's actual colour. A genuinely white car and a warm-cast silver car are not easy to tell apart, and getting that wrong means changing the car, which is the one thing the whole architecture exists to prevent. We constrained correction to the estimated illuminant rather than the body colour, and validated it against a set of vehicles the client confirmed the paint codes for.

The last problem was not technical. The client wanted a regenerate button, so that a user who dislikes an image gets another one. With a deterministic pipeline there is nothing to regenerate; the same inputs give the same output, forever. We pushed back and asked what a user actually wants when they press it. The answer was a different environment, a different angle, or a different grade. So "regenerate" became recompositing with changed parameters, which is instant, free, and predictable, rather than a fresh GPU job that rolls dice. The client's initial reaction was that this was a reduction in capability. It is the opposite, and the cost model made the argument for us.

Rollout & results

The API went to the client's team in week six and their platform launched on it some weeks later, on their own schedule. Median time from upload to finished image is under eight seconds, against a target of ten to twenty, almost entirely because the expensive generative step everyone assumes is necessary is not in the pipeline.

Cost per vehicle mattered most to the client, since their business model is per-vehicle subscription pricing and the margin lives here. A segmentation and compositing pass on eight angles runs at a small fraction of what eight diffusion generations would cost, and it scales linearly and predictably rather than tracking the price of whichever image model is current.

The identity guarantee has held because it is structural. Across the vehicles processed to date, no wheel, badge, trim detail or item of damage has changed between the captured image and the finished one, and it cannot, because nothing in the pipeline is capable of altering them.

"We came in wanting the AI to make the picture. What we needed was the AI to make everything except the car." Founder, client engagement

What we'd do differently

We would have taken a much stronger position on the capture guidance earlier. The client's mobile app walks the photographer through a sequence of angles, and we treated that as their side of the boundary. Every constraint imposed at capture time removes an entire class of problem downstream. Consistent standing distance and phone height narrows the perspective mismatch between the photograph and the showroom plate; asking the photographer to avoid shooting into low sun removes the worst colour casts before they exist. We eventually sent them a short list of capture constraints and each one made the pipeline better than any amount of work at our end would have. That list should have been our first deliverable, in week one, not an afterthought in week four.

We would also have asked for a sample of genuinely difficult vehicles at scope time rather than a representative one. The set we were given was a fair cross-section of the client's inventory, which meant it under-represented the hard cases: convertibles with the roof down, vehicles with roof boxes, anything with a complex aftermarket body kit. Those are a small share of any forecourt and a large share of the engineering.

Have an AI core inside a much bigger product?

We're not the team to build your platform. If there's one hard AI problem sitting in the middle of it, that's the part we quote. Tell us which part it is.

Request Your Agent