Skip to content

Evidence

What we measured, including what failed.

246 YouCam tasks are in the ledger below, and 235 succeeded: 177 made the demo people and boutique stock, 41 ran on real photographs, and 28 were early research. Times are wall-clock from creating the task to having the result, polled every few seconds.

Tasks by API

The studio calls 11 YouCam APIs, and each one has at least one successful run here. Every row is counted from an output file we kept (2026-10-21, scripts/export-runs.mjs), so tasks whose output we didn’t keep, such as early exploration and one-unit end-to-end checks, are not in it. Face and hair length are split because they behave differently on generated and real photos.

APIRunsSucceededReal photosMedianErrors seen
AI Hair Type Detection55—25.5 sNone
AI Hair Frizziness Detection65—17.2 serror_face_angle_invalid
AI Hair Length Detectiongenerated people55—11.1 sNone
AI Hair Length Detectionreal photos52—33.9 serror_face_angle_invalid
AI Face Attribute & Ratio Analyzergenerated people, default strictness55—15.6 sNone
AI Face Attribute & Ratio Analyzerreal photos, default strictness50——error_face_angle_downward, error_face_angle_left_tilt, error_face_not_forward_facing
AI Face Attribute & Ratio Analyzerreal photos, flexible strictness55—16.2 sNone
AI Hairstyle Virtual Try-On959518/1816.5 sNone
AI Hair Color Virtual Try-On1212—24.7 sNone
AI Image Generator (image to image)45454/414.9 sNone
AI Makeup Virtual Try-On994/420.6 sNone
AI Hair Volume Virtual Try-On99—137.3 sNone
AI Hair Extension Virtual Try-On88—143.3 sNone
AI Skin Analysis33—17.1 sNone

Used to build the demo, or tried and left out

APIRunsSucceededWhy it isn’t in the studio
AI Image Generator (text to image)2323Made the demo people and the boutique’s wigs. The studio never calls it.
AI Hair Density Detection20Rejected a front photo and two head-down photos with error_face_angle_invalid. It needs the guided camera in hairdensity mode. Errors: error_face_angle_invalid.
AI Hat Virtual Try-On22Restyles the whole person and, on a bald head, added hair under a beanie. Headwear uses image-to-image instead.
AI Facial Color Tones Analyzer11Returned the same hair-colour label as Face Attribute, at 20 units a run against 10.
AI Scarf Virtual Try-On11Draws a neck scarf, not a head scarf.

Real photographs

The demo people are generated, so we ran the same YouCam calls on nine real portraits from Unsplash. Four are shaved heads. These are Unsplash-licensed stock photos of models, credited to each photographer on its card, and the people are not patients. We publish the results, not the pictures.

18/18wig try-ons succeeded on real photos
8/8of them on shaved heads
0/5 → 5/5face readings at default strictness, then “flexible”
2/5length readings on everyday, slightly turned portraits
  • Hair colour label. YouCam returned a label for 3 of 5 hair photos, and it fit the hair by eye on 2 of 3: Grey/White for dark brown, Black for black, Black for very dark brown. No label came back for the other 2. We have no reference swatch yet, so this is a judgement by eye.
  • Brows. All four shaved-head photos still have brows, so the rebuilt brows barely change them. The brow rebuild is untested on a face that has lost its brows.
  • Why there are no pictures here. The people in these photos agreed to Unsplash’s licence, not to appearing with wigs and turbans in a hair-loss product, so we show the results and keep the edited images out of the site and the repository.
  • Easy photos. These are lit, sharp, uncovered heads. None is a hard case such as glasses, dim phone light or patchy loss.

Long straight brown hair, sunset backlight

  • Face, default strictness: error_face_not_forward_facing
  • Face, flexible: Square, flagged as turned
  • Length: error_face_angle_invalid
  • Colour: shade 1B, off black (YouCam returned no label) Brown to the eye, so the measured off black is a miss in strong backlight.

Tested on a photo by Štefan Štefančík on Unsplash; 2 try-on images kept privately.

Long curly hair

  • Face, default strictness: error_face_not_forward_facing
  • Face, flexible: Oval, flagged as turned
  • Length: error_face_angle_invalid
  • Colour: shade 1B, off black (YouCam label: Grey/White)

Tested on a photo by Jude Infantini on Unsplash; 2 try-on images kept privately.

Long grey hair, smiling

  • Face, default strictness: error_face_angle_left_tilt
  • Face, flexible: Heart
  • Length: above chest or longer
  • Colour: shade 44, salt and pepper (YouCam returned no label)

Tested on a photo by Soroush Sedghi on Unsplash; 2 try-on images kept privately.

Short dark hair

  • Face, default strictness: error_face_angle_downward
  • Face, flexible: Square
  • Length: ear length
  • Colour: shade 1, jet black (YouCam label: Black)

Tested on a photo by Jurica Koletić on Unsplash; 2 try-on images kept privately.

Curly bob, warm light

  • Face, default strictness: error_face_not_forward_facing
  • Face, flexible: Diamond, flagged as turned
  • Length: error_face_angle_invalid
  • Colour: shade 2, darkest brown (YouCam label: Black)

Tested on a photo by Filipp Romanovski on Unsplash; 2 try-on images kept privately.

Shaved head, beard

    Tested on a photo by Zoran Borojevic on Unsplash; 4 try-on images kept privately.

    Shaved head, smiling

      Tested on a photo by Ben Masora on Unsplash; 4 try-on images kept privately.

      Shaved head, black and white

        Tested on a photo by Lisa Marie Theck on Unsplash; 4 try-on images kept privately.

        Shaved head, full beard, outdoors

          Tested on a photo by Tekeyah Whit on Unsplash; 4 try-on images kept privately.

          Hair colour: YouCam’s label and the measured shade

          On the real photographs above, YouCam’s label fit the hair on 2 of the 3 photos where it returned one, and Hairloom’s measured shade gives a code a fitter can order. Both are judged by eye, because we have no reference swatch yet, and the measured shade missed once, on backlit brown hair.

          For each generated demo person, the colour label YouCam’s Face Attribute Analyzer returned for the kept photo, and the shade Hairloom measured from the hair pixels of the same photo. The label was “Blonde” for all 3 generated people that got one, whether their hair was dark brown, blonde or jet black. That looks like an artefact of generated images, so where it agrees with the measurement below, that is chance, and we report it rather than rely on it.

          Anjali

          YouCam label
          Blonde
          Measured
          Shade 4, dark brown

          They disagree, so the passport uses the measured shade.

          Nia

          YouCam label
          Not returned
          Measured
          Shade 1, jet black

          Nothing to compare.

          Margaret

          YouCam label
          Blonde
          Measured
          Shade 16, neutral blonde

          They agree, by chance.

          Ravi

          YouCam label
          Blonde
          Measured
          Shade 1, jet black

          They disagree, so the passport uses the measured shade.

          Wig photos: the listed shade and the measured one

          Each demo wig was generated with a shade code in its description. Measured from the product photo, 5 of 16 come back as that code; the rest read darker and less red, by 4.0 points of lightness on average, because shadowed strands pull the median down. So the studio and the fitter desk show the listed code as the stock shade, and use the measurement only to rank wigs against each other. A client’s measured shade carries the same bias, which is why the passport and the brief ask the fitter to confirm against real swatches.

          WigListedMeasuredΔE00
          Asha21B (miss)5.2
          Meera1B1 (miss)7.6
          Nora64 (miss)7.6
          Ivy306 (miss)17.5
          Zuri1B1 (miss)8.8
          Amara115.1
          June3810 (miss)8.6
          Silver5651 (miss)6.0
          Rosa336 (miss)9.4
          Lena44444.5
          Tara443.5
          Wren38384.5
          Kai41B (miss)7.9
          Dev44448.9
          Arjun1B1 (miss)11.1
          Sam41B (miss)9.9

          Not proven yet

          • No real person with hair loss has used Hairloom from start to finish. The real-photo tests use stock portraits, and shaved heads are smoother and better lit than chemotherapy hair loss. A pilot with consenting clients and a wig fitter is the next step.
          • YouCam’s guided camera (Camera Kit) is built in but has not been tested on a real phone, so we can’t yet say how well its face and light checks work. Uploading photos works without it.
          • Everything was tested on generated wig photos from our demo boutique and on stock portraits, not on a real retailer’s product photos.
          • Salt-and-pepper hair, such as Ravi’s, is measured as its dominant dark shade, so the suggestions lean jet black. A fitter should judge a grey blend such as 44 or 56 by eye.
          • The measured hair shade has no reference swatch to check against, and it missed once on the real photos.
          • The closeness ranking weighs length, texture and colour by hand. It hasn’t been checked against what fitters and clients actually choose.
          • Shade codes vary by brand, and our hex values approximate typical swatches without white balance, so a fitter still checks against real swatches.

          What we learned about the YouCam API, and what we’d ask for

          Each note is something that cost us a run, what Hairloom does about it, and the one change we’d ask the Perfect Corp team for.

          Hair type and frizz need three same-size photos, in one order

          Front, then the face turned towards the right of the picture, then towards the left. Any other order, or different sizes, returns error_face_angle_invalid or error_mismatch_image_size. The studio crops all three to the front photo's size and orders the side photos itself from face landmarks, so a swapped upload still reads.

          We’d ask: Say which photo failed, or accept any order and size.

          Hair colour comes back as a named category

          Face Attribute Analyzer and Facial Color Tones Analyzer return one of a few named swatches. That suits a beauty quiz, but a wig fitter needs a shade code, so Hairloom measures colour from the hair pixels and keeps YouCam's label beside it. Where they disagree is listed below.

          We’d ask: Return a measured hair colour with a confidence, as eyebrow_color already is.

          Hairstyle try-on works on a bald head

          The docs list error_hair_too_short, so we expected failures after hair loss. All 64 try-ons on bald demo photos succeeded, and so did all 8 on real photos of shaved heads. Those are smooth scalps in good light, not patchy loss, so patchy and stubbled heads are still untested.

          We’d ask: Document that bald and shaved sources work.

          Face reading is strict about angle by default

          At the default strictness, Face Attribute Analyzer rejected all five of our real, everyday portraits (error_face_not_forward_facing, error_face_angle_left_tilt, error_face_angle_downward). At face_angle_strictness_level “flexible” all five read, and face_quality still flags a turned face, which the passport passes on. Hair length has no such setting and failed on three slightly turned portraits, which is why the studio leads with YouCam's guided camera.

          We’d ask: Name face_angle_strictness_level in the error, and give hair length the same setting.

          Hairstyle try-on can change more than hair

          On one real photo of a man with a full beard, both wig try-ons removed the beard, and on a black-and-white portrait the try-ons came back in colour. Hairloom's mirror lets you drag back to the original to spot this, and a fitter should always see the real person.

          We’d ask: A hair-only mode that leaves beard, skin tone and background alone.

          Hat try-on restyles the whole person

          Hat and scarf try-on generate a new outfit and background, and on a bald head the beanie came back with long hair under it. For headwear Hairloom uses image-to-image with an instruction to keep the face, clothes and background, at 1 unit.

          We’d ask: A keep-identity option on hat try-on, and a head-scarf style.

          Readings can differ between runs

          The same front photo read the left brow tail as “Average” on one run and “Sparse” on another. The passport keeps the reading with the photo it came from rather than presenting one run as fact.

          We’d ask: A confidence value on shape and thickness readings.

          Density detection is strict about angle

          Front-facing and generated head-down photos were rejected with error_face_angle_invalid. It needs YouCam's camera guide in hairdensity mode, so it is left out of the upload flow. For hair loss this is the reading we missed most, because the passport can say how long hair is but not how much of the scalp it covers.

          We’d ask: A scalp-coverage readout that works on an ordinary front photo, for alopecia and thinning.

          Volume and length templates are for women, and fill out rather than cover

          Every hair-volume and hair-extension template in YouCam's template list is in the “Female” category, so Hairloom doesn't offer them on men's photos. On a generated photo of thinning hair with a widening parting, all four volume templates filled out the sides and added length, but none covered the parting or a thin crown, which is what a topper is for. The three length templates changed length only.

          We’d ask: Men's templates, and a crown or parting topper template.

          Skin analysis needs a close-up

          The face must fill most of the frame. The journal finds the face on the device and crops to it before sending, which turns a normal selfie into an accepted one.

          We’d ask: Accept a normal selfie and crop to the face on YouCam's side.

          task/delete really deletes

          Tested on Oct 21: after task/delete the result URL returns 404, and starting a new task with the same input file fails with a 403. Hairloom deletes each task as soon as the browser has the result. If the tab closes first, the page sends the delete as it closes, and a daily sweep deletes anything left over.

          We’d ask: Delete on completion as an option, so no task depends on the browser to clean up.