One color for every complexion
Four to eight women, often spanning Fitzpatrick I–VI, must wear the same colorway. The shade that flatters the bride's own skin can drain every other complexion in the photos — the photos that last forever.
Built for the YouCam API Hackathon · Topic C — Skin AI × Apparel VTO
Bridesmaid dresses are one color for the whole party — and usually final-sale. OneDress measures every bridesmaid's real skin hex and Fitzpatrick depth, solves for the single color that harms the group least, and renders it photorealistically on each of them.
Engine proven live against 5 YouCam (Perfect Corp) endpoints · product UI in build
The problem
The bridal party is the one wardrobe decision made for a group — and it's made with less measurement than buying a pair of shoes.
Four to eight women, often spanning Fitzpatrick I–VI, must wear the same colorway. The shade that flatters the bride's own skin can drain every other complexion in the photos — the photos that last forever.
Bridesmaid dresses are ordered months ahead and are frequently non-refundable. Once the color is chosen, it's effectively irreversible — there is no "return it if it washes someone out."
Today the color is picked from one retailer model who matches nobody in the party, then debated over group-chat screenshots. Mailed swatch kits and the "mismatched dresses" trend exist precisely because one-color-for-all keeps failing across skin tones.
The inversion
Every personal-color tool answers a one-person question. OneDress inverts the primitive.
One selfie → one verdict. Run it for five bridesmaids and you get five different answers — which chooses zero dresses. Single-user verdicts don't compose into a group constraint.
A fixed garment constraint, N measured complexions, one answer. This is a constrained group-optimization problem — no amount of personal-color analysis composes into it.
It's a max-of-minimum — Rawlsian — fairness problem: optimize the least-flattered person, not the average. The winner is never any individual's top pick, and by construction the deepest-skin bridesmaid — the one the industry has historically served worst — is the protected one, not the sacrificed one.
How it works
Four moves, five live YouCam endpoints — the measured skin values drive the render; they aren't decoration beside it.
Two phone photos per bridesmaid — a face selfie and a full-length. Three live analyses return her measured skin hex, her Fitzpatrick depth (I–VI), and her face shape. Real values, printed on the card: #bb9982 · ITA° 43 · hue° 61.
Every curated colorway is scored against every measured profile with a published formula — undertone harmony, value contrast, saturation. It's pure math on cached measurements: re-scoring all 24 costs zero API units. The winner is the max-of-minimum pick.
The winning colorway is rendered photorealistically on each bridesmaid's own full-length photo with AI Clothes Try-On — measured render fidelity ΔE00 ≈ 7.7 against the intended swatch. Seeing all six in the same color is the proof no swatch kit can give.
Face shape picks each woman's silhouette — stud, hoop, or drop — and her undertone picks the metal: gold for warm, silver for cool. It's a second, smaller color-harmony decision rendered onto the try-on, chained from the dress render.
The palette
Warm × cool × neutral, each at light / medium / deep, muted / saturated — so every skin tone I–VI has at least one strong candidate. The maximin winner is chosen from real options, never a floor of desperation. All names are original; no trademarked colors.
The math
The whole engine is disclosed: fixed color physics (sRGB → CIELAB, ITA°, hue angle, ΔE2000) plus three calibratable weights. Toggle the objective below and watch who pays for the "prettier average."
// each (bridesmaid p, colorway c) flatter(p,c) = 0.50·U + 0.30·C + 0.20·S U undertone harmony — dress warmth vs skin warmth (CIELAB hue°) C value contrast — |ΔL*| inside a flattering band S saturation harmony — enough chroma to read as its own color // group objective — Rawlsian maximin groupScore(c) = minₚ flatter(p,c) winner = argmax_c groupScore(c) // the counterfactual — today's way by-eye = argmax_c mean flatter
Why maximin? Averages hide victims. Maximizing the mean happily sacrifices one bridesmaid to make the group photo "mostly nice." Maximizing the minimum makes the least-flattered person the whole objective — nobody can be quietly thrown under the bus.
Full derivation and constants live in lib/colorway/engine.ts — unit-tested against CIELAB reference anchors.
Illustrative scores, shown to explain the mechanism. In the engine's real measured demo run, the maximin winner lands in the dusty sage / mauve family with nobody scoring below ≈57 — while the mean-maximizing pick drops the most-hurt bridesmaid far lower.
Verified live
Every load-bearing endpoint has been run end-to-end against the live YouCam (Perfect Corp) API — not mocked, not planned. One command reproduces it.
| Endpoint | Role in the flow | Verified live result |
|---|---|---|
| skin-tone-analysis | measured skin hex — the scoring input | #bb9982 → ITA° 43 · hue° 61 |
| fitzpatrick-scale-analyzer | Type I–VI depth cross-check | Type II returned on the test face |
| face-attr-analysis | face shape → earring silhouette | "Heart" returned on the test face |
| cloth-v3 | renders the winning color on each bridesmaid | photoreal render · fidelity ΔE00 ≈ 7.7 |
| 2d-vto/earring | chained finishing touch (undertone → metal) | gold hoop landed on the dress render |
Status, honestly: the typed API client, the live five-endpoint integration, and the published scoring engine (31 passing tests) are done and reproducible — run npm run spike. The interactive product UI is in build. Nothing on this page is a screenshot of an app that doesn't exist yet.
Sponsor track
Three Skin AI endpoints feed the math; two VTO endpoints make its answer visible. The categories aren't stacked side by side — one drives the other.
Remove any one endpoint and the flow visibly breaks — that is what "the API is the engine" means.
Status
npm run spikeDevpost submission deadline Aug 17, 2026
The full story — problem, inversion, math, and the live-API receipts — in ten slides.