extract_pbr_evidence: interior crops can be masked away entirely, and confidence does not drop
Version: 2.0.0 (6e60b5e)
Summary
On an interior material crop — a crop that is 100% material, with no background in it — build_foreground_mask can discard nearly all of the material, and the reported confidence does not fall. In my case it rose, and the run reported "verdict": "pass" with 0.854 confidence while the extracted albedo map was almost entirely black.
Mechanism
forge/stage1_intake/extract_pbr_evidence.py:243-280. For an opaque image the mask is:
alpha > 16 and (distance_from_corner_background > threshold
or (saturation > 0.16 and luma < 0.94))That test assumes a subject sitting on a background. On an interior crop the corner is the material, so distance is ~0 for every pixel of it. A bright, unsaturated material then also fails the second clause.
My crop was cream leather at saturation 0.066, comfortably under the 0.16 threshold, so essentially the whole crop failed both clauses. What survived was the shadowed folds and a sliver of adjacent navy.
The coverage < 0.035 rescue at :265-268 did not fire, because that surviving residue exceeded the floor.
Measured
94x146 crop of cream leather from a garment photograph:
| crop mean RGB | extracted albedo mean RGB | reported confidence | |
|---|---|---|---|
| plain opaque crop | (149.7, 145.6, 136.8) | (5.0, 6.7, 16.6) | 0.854 "pass" |
| same crop, transparent border | (149.7, 145.6, 136.8) | (147.9, 143.7, 135.3) | 0.860 "pass" |
Extracted palette went from #030510, #010106, #36322C, ... to #F4EFDF, #918C85, #56514D — i.e. from near-black to the actual cream. A rib-knit crop lost its white and grey stripes the same way; those returned as #6D6C6A after the fix.
The confidence score is the part that worries me most. It scores the internal consistency of whatever survived the mask, not whether the mask kept the right pixels — so a near-total masking failure reads as slightly better evidence than a correct extraction.
Workaround
Pad the crop with a transparent border so transparentPixelFraction > 0.03. That selects the alpha > 24 branch at :255-257, which is the correct mask for a crop of pure material.
Suggested fix
Either an explicit --interior-crop flag that skips the corner-background test, or a warning when the sampled backgroundColor lands within threshold of the crop's own mean — that coincidence is the signature of the corner test being applied to an image with no background in it.
Source: img2threejs/img2threejs