Files
settled-reach/tooling/garment-qa/README.md
T
jpmschweitzerandClaude Fable 5 74fa16260d feat(tooling): two-pass clip discriminator for garment QA (T-1089)
Second garment-only render pass per view at the identical paused animation
time; the analyzer intersects so body-key pixels split into exposed_skin
(no garment behind — informational: collars, sleeveless arms) vs
clip_through (garment behind — gating). Highlights differ: lime exposed,
red clip. Peasant re-run: 72 captures, 56 clip-through flags — real
collar micro-clips under crouch/walk plus suspected 1px boundary
artifacts; gate threshold + garment-mask dilation are the tuning knobs,
to be calibrated against the first real modern garments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 14:51:04 +02:00

39 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# garment-qa — chromakey garment-clipping QA (T-1089)
Automatically detects clothing clip-through with a **two-pass depth-proximity**
chromakey. Per view (clips × sampled frames × 4 camera yaws), the capture scene renders
the SAME frozen animation frame twice: **pass A** paints the body segments a garment
*claims to cover* (coverage.json `hides`) flat **unshaded magenta**, garment + head/hands
normal; **pass B** is identical except the garment is flat **cyan** and every garment
vertex is nudged `clip_epsilon_m` (default 3 cm) **toward the camera**. A body-key pixel
that is magenta in A but cyan in B means the ε-shifted cloth now covers it — the body sat
within ε *in front of* the cloth = poking through. This separates a true clip from a limb
merely crossing in front of the torso, an open collar, or a bare arm over background
(all of which stay magenta because the cloth behind them is > ε away).
**Run:** `tooling/garment-qa/run-garment-qa [config.json]` (defaults to
`configs/peasant.json`). It launches Godot (`~/bin/godot4`, `opengl3`, `xvfb-run` when
headless) on the capture scene, then runs the analyzer.
**Config** (path passed to the scene via `GARMENT_QA_CONFIG`): `garments`
(`{item_id,slot}` catalogue items, or `{glb,covers[]}` for a raw WIP garment),
`body_types`, `clips`, `frames_per_clip`, `yaws`, `head_id/hair_id/eyebrow_id/skin_tone`,
`out_dir`.
**Read the report:** `<out_dir>/report.json` — the same summary prints to stdout. Two
metrics per capture:
- **`clip_through_pixels`** / `largest_clip_component` — key pixels the ε-shifted cloth
covers (skin ≤ ε in front of cloth). **This is the real defect and it gates:** a capture
`fail`s when its largest connected clip blob ≥ `--min-pixels` (default 8, tolerating AA
edges). `clip_through_failures` + the `by_group` `clipfail`/`worstClip` columns roll it up.
- **`exposed_skin_pixels`** — key pixels the shift did NOT cover (skin well in front of any
cloth: collar/sleeve/ankle gaps, a limb crossing the torso). Informational; does not gate.
Tune sensitivity with `clip_epsilon_m` in the config (smaller = only tighter pokes count)
and `--min-pixels` on the analyzer. Failing/flagged frames are copied to
`<out_dir>/failures/*_HL.png` with **exposed_skin lime**, **clip_through filled red**, and
each clip blob boxed.
**Note:** the Godot scene lives at `client/tools/garment_qa/chromakey_scene.gd` (not here)
because Godot `res://` paths cannot leave the client project root.