Inspiration
Every skincare routine is judged by photos: your own selfies week to week, a clinic's before and after, a brand's ad. AI skin analysis promised to make that judgement objective. But a skin scan reads the photo, not the face — so before building anything, I measured how far YouCam's AI Skin Analysis moves when the skin does not change at all.
What I measured first
- The scanner is exact. The identical photo scanned three times gave identical scores.
- The light is not. On the same photo, changing only the colour temperature moved the pore score from 96 to 85. Exposure ±20% moved skin age by three years. Three faces, every frame the same skin.
- Matching removes most of it in a controlled test, and not on real footage. Across all 12 light changes (3 faces x 4 lights, skin unchanged), the total score gap falls from 84 points to 33 (61% less). Seven single readings got slightly worse after matching, all inside their noise band, and every case is listed on the site's Evidence page (same-light.onrender.com/evidence.html). An earlier headline of 40 to 13 came from the first four cases and is superseded.
- And it has limits. A before/after pair with a much larger light gap still left pores +6 after matching. So I calibrated the residual on 3 faces × 4 lights and only certify a change inside the range that was actually measured.
Every number is in the repository with the script that produced it.
What Same Light is, in one paragraph
Same Light is a caution more than a cure. It measures how far the light alone moves a YouCam skin score (up to 11 points on one concern, 3 years of skin age, on skin that did not change), matches the light to your baseline where that helps, and says borderline, can't certify or retake where it does not. Matching cut the total gap from 84 to 33 points on 12 software-applied light changes; on two real video clips it did not help, so the product promises a warning, not a fix.
What it does
Track a routine. Name what you're testing, take a baseline selfie (upload, or the YouCam JS Camera Kit in skincare mode, which waits for a steady, well-lit, frontal face). Each weekly check-in is compared with the baseline's light, matched to it, and only then scanned. Every concern — wrinkles, pores, texture, blemishes — gets a plain verdict: better beyond light noise, worse beyond light noise, within noise, can't certify (light gap larger than calibrated) or retake. One tap shows what a plain, unmatched scan of the same photo would have claimed. When a routine works, a proof card lists only the changes beyond the noise.
Check a before & after. Two photos from an ad, a clinic post or your camera roll. Same Light scans both, then scans the "after" again in the "before" photo's light, and shows for each concern how much of the claimed improvement the light alone explains.
Consumer and retail value
- Consumers stop paying for products on the strength of a warmer bathroom bulb, and see real progress when it is there — with a proof card they can share in a review.
- Retailers and brands get before/after evidence that survives a fair comparison: a claim-checker for their own ads before a customer or regulator runs one, and proof cards as user-generated evidence on product pages.
- Clinics get a like-for-like progress record instead of photos taken under different lights.
Evidence, and what it does not show
The Evidence page shows measured, assumed and not-validated side by side: the scanner is deterministic; light moves scores; matching cuts the total gap 84 to 33 over 12 cases; the noise bands were set from the largest matched gaps, so "no reading outside the band after matching" is true by construction and is not claimed as a result. It is three faces and a programmatic light change, not real cameras, makeup, shadows or poses, and Same Light says a change beats the light noise, not that skincare worked or that skin changed. Out of sample, the picture is weaker: fitting each noise band on two faces and scoring the third, 8 of 48 held-out readings fell outside (LEAVE_ONE_OUT.md), so with three faces the bands are a rough guide. On real camera footage the evidence is negative or inconclusive, and published as it is (real_camera/FOOTAGE.md): frames from 18 free stock clips, one person and one camera with the light changing, cut by a fixed rule; YouCam refused most (angle, face size, out of frame) and only two clips gave a comparison. On a face split by strong blue and orange light, matching made the total gap larger (24 to 39). On an evenly lit clip, chosen with an eligibility rule fixed before scanning, the total gap stayed the same (14 to 14), with one confident better after matching on unchanged skin, though expression and pose also changed. So matching is shown to help on three faces with software-applied light and not shown to help on real footage. The light is read from a fixed crop of the middle of the frame; if nothing in it looks like skin the photo is rejected as unreadable, and if under a third does the result carries a warning. Checking that guard on all ten Monk Skin Tone swatches (SKIN_GUARD_CHECK.md) found that it refused the darkest tone, because colour cannot tell very dark skin from dark hair; it is now not applied to very dark crops. Flat swatches are not faces, so that is a diagnostic, not a fairness validation.
For brands and clinics
An audit of a before and after claim: for each concern, the change as shown, the change in the same light, the share removed by light matching (an algorithmic comparison of two scans, not a causal finding), and a verdict, exported as a report (sample: same-light.onrender.com/audit-sample.html, a demonstration built from the recorded sample pair, not a real merchant). One click on the home page runs that sample with recorded real YouCam results and spends no credits.
How I built it
- YouCam AI Skin Analysis V2.1 (SD, four concerns): file API → upload to the signed URL →
task → poll → result zip with
score_info.jsonand per-concern mask overlays (enable_mask_overlay), which are shown on every result. - Task delete right after the scores are read, so the photo does not stay on the scanner; history lives only in the browser.
- JS Camera Kit (
faceDetectionMode: 'skincare') for guided capture; API errors (error_src_face_too_small,error_lighting_dark,error_no_face, …) become one line of capture advice. - Light fingerprint and matching in Python/Pillow: per-channel mean and spread of the face region, drift described in words ("12% darker and cooler than your baseline"), histogram-free moment matching before the scan; noise bands and calibrated range from the experiments.
- Small standard-library server holds the key, runs the three pair scans concurrently, caps scans per visitor and keeps a unit reserve. Vanilla HTML/CSS/JS front end, no build step. 20 tests, CI on Python 3.10 and 3.13.
Challenges
The hardest part was not trusting my own fix. The first version certified a +6 pore change on an unchanged face because the light gap in that pair was twice what the noise bands had been measured on. Rather than widen the band until the demo looked good, I measured the residual across larger gaps and made the product refuse to certify outside them.
Accomplishments
A skin-analysis app that can say "nothing changed" and "I can't tell" — and shows the measurements behind both.
What's next
Calibrate across more skin tones, cameras and real (not simulated) bulbs; per-user noise bands from two baseline shots; HD concerns; and a brand-side API that returns a certified/not-certified stamp for before/after pairs.
Built With
- css3
- html5
- javascript
- pillow
- python
- render
- youcam