Skip to content

Methodology

How we measure, and what we refuse to measure

Everything below is deterministic code you could re-run. A language model writes some of the sentences you see in the app. It never produces a number, never decides anything, and never touches this page.

Written for the person who reads the methods section first. If something here is wrong, we would rather hear it than not.

01

The hard part is repeatability, not seeing

The difficult question is not what a model can spot in a photo. It is whether one phone can take the same photo of one face twice, six weeks apart.

Between two casual sessions, the light temperature, the auto white balance decision, the exposure, the head angle, the distance, the time of day and the vendor smoothing all move. Together they move a colour index by one to two orders of magnitude more than the effect anyone is hoping to see.

The uncomfortable corollary, which applies to us too if we get lazy: a progress chart built on uncontrolled selfies is mostly a chart of the room. We are not allowed to ship that, so most of the engineering below is spent removing the room rather than analysing the face.

02

The model writes the sentence. It never makes the measurement.

The usual architecture sends a selfie to a vision-language model and renders whatever comes back, including its stated confidence. A confidence emitted by a language model is generated text, not a calibrated probability, and it will not be stable between runs.

So we inverted it. Deterministic code computes every number. A rules engine makes every decision. The model is handed numbers it did not produce and cannot change, and is asked to write plainly about them. Its output then passes a blocking language filter before anyone reads it.

No number that originates inside a language model is ever shown to you.
Safety rules run before the model sees any candidate ingredient, and again after it produces text. Both are blocking, and both are ordinary code with tests.
03

The pipeline, in order

One capture goes in. A versioned payload of numbers, each with its own uncertainty, comes out. Every stage is pinned by a commit hash stored alongside the result, so we can answer "we re-ran it and it moved" instead of shrugging.

  1. Stage 1

    Gate at the moment of capture

    Pose, sharpness, exposure and lighting evenness are checked on your device before anything uploads. A capture that fails is not a photo we analyse badly. It is a photo that never exists, and you are told the one specific thing to fix.

  2. Stage 2

    Control the light source

    The most useful accessory on a front camera is the screen next to it. A full white screen at arm’s length is a known, frontal, diffuse light that partly swamps whatever the room was doing. It ramps over 400 milliseconds rather than snapping, and it can be turned off — that choice is recorded and widens the uncertainty band rather than being ignored.

  3. Stage 3

    Decode to linear light

    The transfer function is removed before any arithmetic. Averaging gamma-encoded pixels is a real, common and silent error that biases every regional mean, and it is invisible once it has happened.

  4. Stage 4

    Landmarks

    A face mesh with iris refinement runs on device. The iris points matter more than the rest: they give the inter-pupillary distance.

  5. Stage 5

    Canonical alignment

    A rotate, scale and translate step puts the eye line horizontal and fixes the inter-pupillary distance at 256 pixels. A phone photo carries no metric scale, so we never claim millimetres — but that distance is close to constant for one adult over the timescales we care about, which makes every spatial measurement comparable across distance, resolution and device within one person.

  6. Stage 6

    Skin mask

    Eyes, brows, lips, nostrils, hair, facial hair, glasses, jewellery and clipped highlights are excluded, along with a margin around each. Excluding facial hair is not politeness: beard regions produce garbage colour and texture values that would quietly corrupt the chin and jaw numbers.

  7. Stage 7

    Combine the views

    When more than one pose was captured, the views are warped into one face space, oblique surfaces are masked out, and the shine is separated from the colour underneath it. That separation is the reason side poses exist at all.

  8. Stage 8

    Compute in log-linear space

    Under a diagonal illuminant model, each channel is the light’s gain multiplied by the surface’s reflectance. Take the difference of logs between two regions of the same frame and the gain cancels exactly, leaving pure reflectance contrast. The white balance decision, the exposure choice and the colour temperature all vanish in that subtraction. Doing the same subtraction in a perceptual colour space cancels only approximately, so we do not.

  9. Stage 9

    Sample the regions

    Regions are defined by landmark indices, so the same anatomy is sampled every session. Each one reports its own pixel count and how much of it was masked away. A region with too little valid skin left is reported as unavailable, never as a statistic computed from a handful of pixels.

  10. Stage 10

    Derive the indices

    Per-region primitives use trimmed means throughout, so one specular pixel or one dark lash cannot move a regional average. The user-facing indices are contrasts between regions, not absolute values. Absolutes are still stored, because aggregate work needs them, but they are not what any chart shows you.

  11. Stage 11

    Annotate quality and comparability

    Every reading carries flags describing how comparable it is to your others. Some of those flags widen the uncertainty band. Some remove the reading from the trend entirely and show it as an unconnected point, with the reason stated.

04

Every number we compute

Six families. Each one below states what it is and, more usefully, what it is not. The primary endpoint for redness work is EC_cheek.

Erythema contrast

ECPrimary endpoint
What it is
How much redder a region is than your own least-red skin in the same frame, computed on the green-versus-red axis in log-linear light. Your own face is the reference, which is what makes it survive a change of room.
What it is not
Not a clinical redness grade and not equivalent to any instrument used in a clinic. We have not validated it against one, so we do not claim it matches one.
Beneficial direction
Lower is the direction people usually want.
Reported for
Both cheeks togetherLeft cheekRight cheekChinAround the mouthThe difference between the two sides

Tone uniformity

TU
What it is
The spread of lightness within a region — a measure of how evenly the region reflects light. Reported only as a difference from your own baseline.
What it is not
Not an evenness score, not comparable between people, and never shown as a rank or a grade.
Beneficial direction
Lower is the direction people usually want.
Reported for
ForeheadBetween the browsLeft cheekRight cheekNose bridgeAround the mouthChinLeft jawRight jawLeft under-eyeRight under-eyeBoth cheeks together

Pigment depth

ITA
What it is
A standard photometric angle derived from lightness and the yellow-blue axis. We use it for two things: auditing whether the pipeline behaves differently across skin tones, and tracking regional pigment change against your own baseline.
What it is not
Not an identity, not an ethnicity, and never rendered to you as a category name. It is an angle computed from reflected light, and it is used as a recommendation input only through questions you answered yourself.
Beneficial direction
Neither direction is good or bad. This one is an observation, not a verdict.
Reported for
ForeheadBetween the browsLeft cheekRight cheekNose bridgeAround the mouthChinLeft jawRight jawLeft under-eyeRight under-eyeThe whole face

Surface gloss

GL
What it is
The fraction of a region reflecting light specularly. With one pose it is a weak, region-relative proxy compared within a single session. With three poses the shine can actually be separated from the colour underneath, which makes it a real measurement.
What it is not
Not oiliness and not sebum output. Those need contact instruments. Even the three-pose version is confounded by moisturiser, sunscreen, sweat and time since washing, so it is always labelled surface gloss and never anything else.
Beneficial direction
Neither direction is good or bad. This one is an observation, not a verdict.
Reported for
ForeheadBetween the browsLeft cheekRight cheekNose bridgeAround the mouthChinLeft jawRight jawLeft under-eyeRight under-eyeBoth cheeks together
The one-pose and three-pose versions are not comparable to each other. Changing capture method breaks the series, and we flag it and break the line rather than joining two things that do not join.

Texture

TX
What it is
Band-passed high-frequency energy at a scale normalised by inter-pupillary distance, computed on the shine-free component where we have one.
What it is not
Not smoothness, not pore size in physical units, and not available at all from a soft or upscaled image. Blur removes high-frequency energy, which would read as smoother skin — the exact failure mode that manufactures fake progress — so the threshold here is stricter than the general gate and the metric goes unavailable instead.
Beneficial direction
Lower is the direction people usually want.
Reported for
ForeheadBetween the browsLeft cheekRight cheekNose bridgeAround the mouthChinLeft jawRight jawLeft under-eyeRight under-eyeBoth cheeks together

Inflamed spot count

SC
What it is
A deterministic blob count: difference-of-Gaussians on a red-contrast map at inter-pupillary-normalised scales, thresholded on contrast and size. Versioned and unit-tested against a fixed image set.
What it is not
Not a clinical lesion count and not a severity grade. It cannot tell one kind of spot from another and it will catch some moles and freckles. It is always shown with its band attached, and it is labelled an estimate.
Beneficial direction
Lower is the direction people usually want.
Reported for
ForeheadBetween the browsLeft cheekRight cheekNose bridgeAround the mouthChinLeft jawRight jawLeft under-eyeRight under-eyeBoth cheeks together
Defined here, not computed in this version. It appears on a reading as unavailable with that reason attached, rather than as a blank.
05

Where we sample

Defined by landmark indices, so the same anatomy is measured every session. Each region reports its own pixel count and masked fraction.

Forehead
Forehead, above the brows and below the hairline
Between the brows
Between the brows
Left cheek
Left cheek — a primary region for redness and pigment
Right cheek
Right cheek — a primary region for redness and pigment
Nose bridge
Bridge of the nose
Around the mouth
Around the mouth, lips excluded
Chin
Chin
Left jaw
Left jaw
Right jaw
Right jaw
Left under-eye
Left under-eye — posture and lighting sensitive, low trust
Right under-eye
Right under-eye — posture and lighting sensitive, low trust
06

What we refuse to measure

Written down here so it cannot quietly be forgotten in a design review. None of these are hard for us in the sense of being unsolved. They are impossible from an uncalibrated front camera, and every app that reports them is guessing.

Hydration, water loss through the skin
Needs contact instruments held against the skin. Nothing in a reflected photo carries this.
Sebum output rate
Needs a contact measurement too. Surface gloss is a weak and confounded proxy, and we label it as gloss for exactly that reason.
Pore size in physical units
There is no metric scale reference in the frame. Only comparison against your own face is defensible.
Collagen density
Not observable in reflected visible light. Nothing in the image carries it.
Skin age
Not a physical quantity. It is a number invented to make a chart move, and it also evaluates the person rather than describing a surface.
Anything below the surface
Needs cross-polarised or ultraviolet imaging that a phone front camera does not have.
Any named condition, and any severity grade
That is a clinical act, and it is over the line we hold. There is no code path that does it — not a filtered one, an absent one.
Where a proxy is genuinely useful we name it as a proxy in the interface. We never ship a proxy while implying a direct measurement.
07

Reliability is not accuracy, and we only have one of them

These two get conflated constantly, usually on purpose. Reliability is whether the same instrument gives the same answer on the same unchanged subject. Accuracy is whether the answer matches a reference instrument that is regarded as ground truth.

What we validate is reliability: how much our own number moves when nothing about you has moved. That is measurable with volunteers and a stopwatch, and it is what makes a comparison over six weeks mean anything.

What we have not validated is accuracy. That needs a study against reference instruments, on a sample deliberately spanning skin tones, and it does not exist yet. Until it does, describing our numbers as accurate would be a lie, so we do not, anywhere.

Our indices are internally consistent. They are not calibrated against any clinical reference, and we make no claim that they match one.
The practical consequence for you: our numbers are meaningful compared with your own earlier numbers, and meaningless compared with anybody else’s. So the product never ranks you against another person, and there is no score.
08

The noise floor, and the rule built on it

At enrolment you take two captures about 20 seconds apart. Nothing biological has changed in that gap, so every difference between them is our own measurement wobbling. Repeating that opportunistically keeps the estimate current.

That gives a standard error of measurement per person, per metric, and from it a minimal detectable change: the smallest difference we are entitled to call a difference.

How it is computed

  • The standard error of measurement is the spread between your repeat captures, divided by the square root of two.
  • The minimal detectable change uses the two-sided Student’s t value for that estimate’s own degrees of freedom, multiplied by the square root of two.

This is the standard test–retest formulation. Small studies use a wider band than the normal approximation; a missing degrees of freedom means no band is published.

If a difference is smaller than the minimal detectable change, the interface says there was no detectable change. It does not draw a trend, it does not say slight, and the number does not appear.
This is the single rule that separates us from the category, and it is also the rule that gets argued about internally every time somebody wants a nicer-looking chart. It does not move.

Where the estimate comes from, worst to best

A population prior
Used before you give us anything personal. It says nothing about you specifically, and it is flagged as such.
Your enrolment repeat
Two captures in one sitting. The lighting and the setup never changed between them, so it is a lower bound on real-world noise, and it is flagged as a lower bound.
Your trial baseline
Captures on separate days before any intervention starts, when you are by definition changing nothing. This is the honest number, and it is free — which is why a trial insists on a baseline instead of starting immediately.
A within-session estimate is never presented as if it bounded between-session noise. That would understate our uncertainty in precisely the direction that flatters us.

We have not measured this yet, so there is no number here

The real figure comes from a repeatability run: volunteers, several captures each within a couple of minutes, no intervention, gate on. Until that has been run and the data published, this section stays empty on purpose.

A plausible-looking placeholder would be the exact failure this whole page argues against, and inventing one would be worse than an empty box. Milestone zero does not ship until this box has a measured number in it.

The run can also fail. If our minimal detectable change turns out to be larger than the effects people are trying to detect, the quantitative approach does not work as designed, and we will say so here and change the product rather than round the number down.

09

Flags that change how a reading is used

Every reading carries these. They decide whether it may join a trend, and you can see them on the reading itself. Where a flag widens the uncertainty band, the amount it widens by is a deliberately cautious estimate, not a measurement: we have not yet run the study that would tell us the real number, so we chose factors that make us under-claim rather than over-claim.

FlagWhat it does
Captured on a different device than the trial baselineExcluded from the trend, shown as an unconnected point
Screen light was off or unavailableWidens the uncertainty band (provisional factor)
The estimated light source sits far outside your own usual rangeWidens the uncertainty band (provisional factor)
Uploaded rather than captured through the guided flowExcluded from the trend, shown as an unconnected point
Image resolution below canonicalAffected regions reported as unavailable
Heavy masking from hair, facial hair or occlusionAffected regions reported as unavailable
A different number of poses than the trial baseline usedExcluded from the trend, shown as an unconnected point
Fewer poses captured than the full setRecorded on the reading; the numbers come from the views that were captured
A region was only ever seen at too steep an angleAffected regions reported as unavailable
Texture and tone both dropped sharply against your own baselineWidens the uncertainty band (provisional factor)
10

Known limitations

Things that are true today and that we would rather you learn here than discover yourself.

No physical units, ever
Fixing the inter-pupillary distance gives consistency within one person. It does not give absolute size, and it does not make two people comparable, because that distance varies between people.
Most noise estimates are optimistic at first
Until you run a trial baseline, your uncertainty band comes from captures taken minutes apart, which understates real-world variation. The band is flagged while that is true.
Single-pose gloss is a weak proxy
With one pose we cannot separate shine from the colour beneath it, so gloss is comparable only within one session and only between regions of your own face.
Some readings cannot join a trend
A different device, an upload that did not come through the guided capture, or a different number of poses will show as an unconnected point with the reason attached. We would rather break the line than draw a comparison that is not one.
Under-eye regions are low trust
They move with posture, sleep and the angle of the light far more than with anything about your skin. We measure them, and we weight them accordingly.
The ingredient knowledge base is not signed off
Every source in it is a research brief written by us describing evidence we still need to read, not a citation. Nothing is suggested to anybody until a person has read and recorded the real source. The ingredient pages say so individually.
English only
German is the next locale and the launch market speaks it. The copy needs a legal read rather than a translation, so it is not shipped half-done.
11

Metric version changelog

Any change that alters a computed value increments the metric version. Stored readings keep the version they were computed with, and a chart never mixes versions without recomputing. Recomputation is only possible where you chose to keep your images — for everyone else a version bump freezes the old points and labels them.

Current: metric version 1.2.0, capture version 2.0.0-gemini

Metric version changelog

One version so far, so there is nothing to compare it against yet. Every subsequent version will be listed here with what changed and whether stored readings were recomputed.

12

How to prove us wrong

The claim on this page is testable and cheap to test, so here are the tests, including the ones that would sink it. Results land in the repository with the raw data.

  1. Test T1

    The noise floor

    Volunteers, several captures each within a couple of minutes, no intervention, gate on. Compute the spread, and from it the minimal detectable change.

    If the minimal detectable change for the primary redness contrast is larger than the effect anyone would need to see, the quantitative approach fails as designed.

  2. Test T2

    Illuminant robustness

    One face, one session, four lighting conditions. Compare the contrast indices against the absolute ones.

    The contrast indices must vary substantially less than the absolutes, or the central argument of this page is wrong.

  3. Test T3

    What the gate is worth

    Repeat the lighting run with the capture gate switched off.

    Gated variance must be materially lower. This is the number that justifies the cost of rejecting your photos, so it gets measured rather than asserted.

  4. Test T4

    Whether detection boxes are stable at all

    The same image, several identical calls, then again with tiny crops. Measure how much the returned boxes agree with each other.

    This decides whether model-drawn boxes are a feature in this product. Right now we do not draw any.

  5. Test T5

    The null run

    One or two people, six weeks, doing nothing different. The pipeline should report no detectable change throughout.

    This is the most important test we run. If the pipeline finds progress in somebody doing nothing, it manufactures signal and everything built on top of it is invalid.

  6. Test T6

    Capture geometry

    Single frontal capture against a held three-pose set against a continuous sweep. Measure repeat variance, blur, how well shine is suppressed, how much of the sides we can see — and how many people give up partway.

    Abandonment counts as a result. A capture protocol nobody completes measures nothing.

If the noise-floor run or the null run fails, we do not paper over it. The product becomes qualitative tracking and we say so publicly, which would still be more honest than the category standard.
13

The line we hold

We measure optical properties of skin and compare them against your own earlier measurements. That is a cosmetic activity, and staying on that side of the line is a deliberate constraint on the product rather than a disclaimer bolted to the bottom of it.

  • We never name a condition as a conclusion. Not in the app, not in narration, not here.
  • We never assess an individual spot or mole, and we never say one is fine. That capability is absent rather than filtered, because the two possible errors are not symmetric.
  • Nothing Skinstreak produces is a diagnosis, and telling you that somebody should look at something in person is a statement about our limits rather than about you.
What we can and cannot do