Not a filter. A verdict.
Every virtual try-on I have ever used answers the wrong question. They show you what a garment looks like on you. They never tell you whether it works on you. You are left doing the hardest part yourself — squinting at a mirror, asking a friend, guessing.
EventReady AI answers the question you actually had: should I wear this?
Upload one photo. It measures your skin, hair and eye colour, places you in a 12-season colour palette, and then grades any garment you point it at — yes or no, with a confidence score and the actual colour-distance number that decided it.
What it does
1. It measures you — it doesn't guess. One photo goes to Perfect Corp's Skin Tone Analysis and Skin Analysis APIs. We pull skin colour, hair colour and eye colour, convert everything into CIELAB, and treat those as instrument readings rather than vibes.
2. It classifies your season. Three axes — warm/cool, light/deep, muted/bright — resolve to one of the twelve seasonal palettes. Every axis is shown as a meter with its measured value, so you can see why you landed where you did rather than being handed a label.
3. It grades garments by ΔE. Every garment colour is compared to your palette using CIEDE2000 — the perceptual colour-difference standard, validated here against the Sharma et al. (2005) reference pairs. A ΔE below the threshold is a match. Above it is not. The number is always shown.
4. It shows you the proof. Perfect Corp's Cloth Virtual Try-On renders the same face wearing a best-match garment and a deliberately off-palette one, side by side. The verdict is not something you have to take on faith — you can see the difference. Image-to-Video then brings the winning look to life.
5. It grades garments we've never seen. Paste any product photo. We extract the true garment colour out of the retailer's photography and run it through the same scoring engine.
How we built it
- Frontend — React + TypeScript + Vite, Tailwind, Framer Motion, Radix primitives.
- Backend — Express + TypeScript, with an OpenAPI contract as the single source of truth. Zod schemas and the typed React client are both generated from it, so a backend shape change becomes a frontend type error rather than a runtime surprise.
- Perfect Corp / YouCam APIs — Skin Analysis, Skin Tone Analysis, Cloth Virtual Try-On, Image-to-Video, and the S2S file-upload pipeline, all async task-and-poll.
- Colour engine — hand-written CIELAB conversion, CIEDE2000, a 12-season palette model, and a k-means garment-colour extractor. No colour library; we needed to know exactly what every number meant.
Challenges we ran into
The scores were upside down. YouCam Skin Analysis returns healthy-direction scores — higher is better. We read them as concern-direction, so every early verdict was inverted. The fix is one inversion at the API boundary; the lesson is to never let a convention mismatch propagate past the edge of your system.
HTTP 431, disguised as a hang. We built a stateless signed session token and embedded the uploaded image in it, then echoed it back as a request header. Past a certain photo size the browser silently refused the request and the processing screen just froze forever. Nothing in the logs said "header too large" — it presented as a hang, not an error.
Hair segmentation lied to us, confidently. Some responses returned a "hair" swatch that was actually skin or backdrop — around 40 L* too light, with no error and no low confidence flag. We now cross-check the hair reading against the eyebrows and reject it when it reads implausibly light.
Our classifier had a warm bias — and it was an inclusivity bug. Three separate traps compounded: the skin hue neutral has to be lightness-corrected, hair warmth is carried by chroma rather than hue angle, and every brown eye measures positive on b* so the neutral point must sit inside the brown range. Uncorrected, the classifier mislabelled deep skin tones systematically. That is not a rounding error, it is the app failing the people it should serve best.
Retailer photography is not measurably reliable. Centre-crop averaging quietly blends the backdrop into the garment colour. We ended up on border flood fill with adaptive tolerance plus k-means largest-cluster — and a fallback to the retailer's own colour word when the photo simply isn't measurable.
Accomplishments we're proud of
It works on everyone. The colour engine was calibrated across a deliberate spread of skin tones rather than the handful that happened to be convenient. Fixing the warm skew was the single highest-value thing we did.
It works on non-Western clothing. Saree, lehenga, anarkali, qipao and abaya all render correctly — pallu drape, dupatta, mandarin collar. The garment gallery leads with that on purpose. Colour analysis has a long history of assuming a Western wardrobe, and it does not have to.
Every number is on screen. Axis meters, ΔE values, confidence scores, and a plain-English reason for every verdict — including when we couldn't measure something and said so. No silent fallbacks.
What we learned
Measurement and interpretation are different products, and users can tell. The moment we stopped rendering a generated summary next to curated copy — and started showing the axis meters with their real values — the whole app got more trustworthy, not less.
We also learned that a graceful fallback without a recorded reason is just a bug with good manners. Every fallback path in the engine now carries a reason code, so "we couldn't measure your hair" never gets quietly reported as "your hair is neutral."
What's next
Full wardrobe scanning — grade everything you already own in one pass. Retailer integration so ΔE sits on the product page next to the price. And extending the same measure-then-verdict approach beyond colour, to fit and proportion.
Built With
- ciede2000
- cielab
- color-science
- computer-vision
- express.js
- framer-motion
- jimp
- k-means
- node.js
- openapi
- orval
- perfect-corp
- pnpm
- radix-ui
- react
- tailwindcss
- tanstack-query
- typescript
- virtual-try-on
- vite
- vitest
- wouter
- youcam
- zod
Log in or sign up for Devpost to join the conversation.