Skip to main content
Jonathan Andrei
Back to all posts
Aug. 202611 min read

Assay: A Skincare Tracker with an Error Bar. Cropping the Same Photo Moves Texture by 5.81 Points, So a Verdict Only Fires When the Change Beats That Floor on Your Face.

The measurement exists: YouCam's Skin Analysis API scores sixteen skin outputs from a photograph, and it is a genuinely good instrument (byte-identical input gives byte-identical output). The problem is that a score reported without its error is a number you cannot make a decision with. On my own face with one variable changed at a time, brightness ±8% moves blemishes by 4.85 points and cropping the same photograph differently moves texture by 5.81. A realistic four-week treatment effect is about five. Assay measures its own error first, then calls a change real only when it beats that floor.

YouCamHackathonYouCam Skin Analysis APIPerfect CorpSEMMDC95n-of-1Next.jsTypeScript
I created this post and the Assay project for the YouCam API Skin AI & Apparel VTO Hackathon. #YouCamHackathon
The claim in one sentence: the average woman spends about $170 a year trying to find skincare that is right for her and is still holding on to four products that did not work, because a score reported without its error bar is not enough to decide anything. On the same face, cropping the photograph differently moves texture by 5.81 points; a realistic four-week treatment effect is about five. Assay measures how much the reading moves when your skin has not changed, then requires any claimed change to clear that bar before it says anything.
Assay landing page in warm off-white: 'Four of the products on your shelf are doing nothing. Assay tells you which.' Subtitle: 'Most skin trackers report your lighting as progress. Assay measures its own error first, then calls a change real only when it beats that margin on your face, on your device. It is the only skin tracker that tells you when it cannot tell.' Four stats below: $170 spent a year, 4 failed products held on to, 1 in 9 women who have cycled through ten or more failures, £1bn skincare abandoned annually in the UK alone.
The whole argument in one page. Numbers from a 2,000-person AmLactin/OnePoll survey (Feb 2022) and a 2,000-person Body Shop / Professional Beauty survey, both cited in the copy. Everything downstream is that claim, made honest.

The instrument is good. The number you are shown is not the number that was measured.

YouCam's Skin Analysis API is a genuinely good instrument. Assay verified it: three analyses of a byte-identical input return byte-identical output, standard deviation 0.000 on every attribute. Model noise is zero. That is what licenses everything else the app does: every point of spread between two frames comes from capture variation, not the model changing its mind. The problem is not the measurement. It is that Perfect Corp's documentation openly describes the displayed score as 'a psychological motivator', adjusted upward from the underlying measurement because 'consumers generally prefer positive evaluations regarding their skin health.' The largest gap I saw on my own face was on moisture, the concern a hydrating product is supposed to move. Assay computes everything on the measurement and never on the motivator.

Calibration table showing 'On skin that did not change, a normal tracker would have been wrong 10 times out of 12.' Column headers: concern, sessions, difference, a tracker says. Rows show redness -4.18 (changed), redness +17.04 (changed), pores -0.18 (no change), pores +1.68 (changed), texture +1.36 (changed), and so on. Same face, 15 minutes, nothing applied.
Same face, fifteen minutes apart, nothing applied between shots. A normal tracker would have called ten of twelve changes real. Assay's calibration measures exactly this so it can refuse to call any of them.

The maths, in two lines

Two standard quantities from clinical measurement science do the work. SEM is the pooled standard deviation across replicate captures. MDC95 = 1.96 × √2 × SEM is the minimum change you can distinguish from measurement noise at 95% confidence; the √2 is there because two measurements are being compared and each carries its own error. Below that threshold, the honest answer is not zero and it is not a small improvement. It is 'cannot tell yet', and Assay says so, with the number of further sessions required. Six verdicts fall out: Working (clears the floor and the trend agrees), Getting worse (clears the floor in the wrong direction, reported early because an adverse reaction shows up fast), Expected flare (worse but inside the window a retinoid or BHA is known to purge), Not working (flat, past the point where this ingredient should have done something, a null result not an early one), No evidence yet (flat but the study cannot yet resolve an effect this size), and Cannot measure (the concern is pinned against the end of the scale).

Assay verdict card for the shipped study. Texture: change -7.5, noise floor ±3.1, verdict 'Getting worse'. Bar chart shows the change is past the noise floor, in the wrong direction. Copy: 'Texture moved 7.5 points in the wrong direction, past the 3.1-point noise floor. That is outside the window where this product is expected to cause temporary irritation. Worth stopping and reconsidering.' Below: Blemishes card with change -6.9, floor ±6.4, verdict 'Getting worse'.
Every verdict card carries the change and the floor together. Two numbers, and the verdict follows from them. No adjective without a bound.

Where the noise floor is measured, and the limit I state up front

Frames taken seconds apart without touching the camera capture sensor and pose noise, and nothing else. They cannot see the error you add by setting the camera back up tomorrow, which the crop experiment above shows is the largest error there is. So calibration is several sessions separated in time rather than several frames separated in seconds; skin cannot change in twenty minutes, so the spread across those session means is pure measurement error rather than biology. One thing to be clear about, because it is the limit of the number: the three calibration sessions in the shipped study are sampled at 120s, 520s and 900s of a single continuous recording. That captures the pose, distance and expression drift that accumulates between sittings, but not the error of physically taking the camera down and setting it back up. The floor it yields is therefore a lower bound on the true between-session error, and the honest consequence runs against the project: an underestimated floor makes verdicts fire more readily than they should, not less. `src/data/study.json` records this on the calibration block itself, and the app takes whichever is larger, the between-session error or the frame-level error, never the smaller, which is what keeps this bound from collapsing further.

Live in-browser capture: aligned face with a MediaPipe face-mesh overlay for consistent framing, capture pipeline normalising every frame to the same dimensions and JPEG quality before it is sent, so at least those two sources of error are held constant across sessions.
Cropping moved texture by 5.81 and JPEG quality moved blemishes by 2.91, so the capture pipeline holds both constant before anything goes to the API. If you cannot control an error, at least do not add it.
Error budget by source: JPEG quality q80 to q96 moves blemishes 2.91, hydration 0.35, texture 0.12, pores 2.55. Brightness ±8% moves blemishes 4.85, hydration 3.87, texture 1.96, pores 1.52. Model (identical bytes) is 0.00 on every attribute. Score movement in points, by source of variation, larger is worse.
The error budget, pulled apart by cause. Because model noise is zero, every point of the remaining spread has a name: JPEG, brightness, or pose. Assay controls the first two and calibrates against the third.
Related project

Assay: A Skincare Tracker with an Error Bar. Cropping the Same Photo Moves the Texture Score by 5.81 Points, So a Verdict Only Fires When the Change Beats That Floor on Your Face.

View the project