Spaces:
Sleeping
Sleeping
File size: 6,262 Bytes
6a75a66 c4458f9 6a75a66 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | """R3-3 β rug-replace certification (CI-safe, no models).
Two contracts:
1. Class routing: 'rug' is a REPLACEABLE class (RUG_CLASSES), not an
occluder β the benchmark behaviour. Verified against the real class sets
from app.py.
2. Shade neutrality: with the rug replaced, the heuristic shade map must
NOT carry the rug's albedo (a dark persian rug would otherwise transfer
as a giant stain onto the new floor). Inside the rug the shade flattens
to neutral; outside the feather band the shading is untouched.
"""
import cv2
import numpy as np
# --- real implementations / class sets from app.py ---------------------------
src = open("app.py").read()
ns = {"np": np, "cv2": cv2}
sets_start = src.index("PRIMARY_FLOOR_CLASSES")
sets_end = src.index("\n\n", src.index("OCCLUDER_CLASSES"))
exec(compile(src[sets_start:sets_end], "app.py", "exec"), ns)
for fn in [
"_adaptive_shade_range",
"_encode_shade",
"_dominant_period",
"_suppress_periodic_shading",
"build_shade_map",
]:
start = src.index(f"def {fn}")
end = src.index("\ndef ", start + 10)
exec(compile(src[start:end], "app.py", "exec"), ns)
build_shade_map = ns["build_shade_map"]
H, W = 480, 640
def scene():
"""Bright floor (lower half) with a gentle vertical light gradient and a
DARK rug rectangle; the mask covers floor incl. rug (R3-3 union)."""
yy = np.mgrid[0:H, 0:W][0].astype(np.float64)
lum = 150.0 + 40.0 * (yy - H / 2) / (H / 2)
img = np.clip(lum, 0, 255)
mask = np.zeros((H, W), np.uint8)
mask[H // 2 :, :] = 1
rug = np.zeros((H, W), np.uint8)
rug[int(H * 0.65) : int(H * 0.85), int(W * 0.3) : int(W * 0.7)] = 1
img = np.where(rug > 0, 60.0, img)
img3 = np.stack([img] * 3, axis=2).astype(np.uint8)
return img3, mask, rug
def decode(enc, rng):
lo, hi = rng
return lo + enc.astype(np.float64) / 255.0 * (hi - lo)
def main():
ok = True
# 1 β class routing
rug_ok = (
"rug" in ns["RUG_CLASSES"]
and "rug" not in ns["OCCLUDER_CLASSES"]
and "rug" not in ns["FLOOR_SURFACE_CLASSES"]
)
print(f" [{'PASS' if rug_ok else 'FAIL'}] class routing: rug replaceable "
f"(RUG_CLASSES), not occluder, not silently merged into floor classes")
ok &= rug_ok
img, mask, rug = scene()
enc_with, rng_with = build_shade_map(img, mask, rug)
enc_wo, rng_wo = build_shade_map(img, mask, None)
rel_with = decode(enc_with.reshape(H, W), rng_with)
rel_wo = decode(enc_wo.reshape(H, W), rng_wo)
rug_interior = cv2.erode(rug, np.ones((31, 31), np.uint8)) > 0
# 2 β without neutralisation the rug albedo IS a stain (documents the bug)
stain = float(rel_wo[rug_interior].mean())
good = stain < 0.85
print(f" [{'PASS' if good else 'FAIL'}] un-neutralised rug reads as stain: "
f"mean shade {stain:.3f} < 0.85")
ok &= good
# 3 β with the rug mask the region flattens to neutral
flat = float(np.abs(rel_with[rug_interior] - 1.0).mean())
good = flat < 0.05
print(f" [{'PASS' if good else 'FAIL'}] neutralised: mean |shade-1| inside rug "
f"{flat:.3f} < 0.05")
ok &= good
# --- R3-3 v2 β rug-region refinement (refine_rug_mask) -------------------
SOFT_ID = 7
rns = {
"np": np,
"cv2": cv2,
"class_ids": lambda names: [SOFT_ID],
"SOFT_FURNISHING_CLASSES": {"cushion"},
}
start = src.index("def refine_rug_mask")
end = src.index("\n# ---", start)
exec(compile(src[start:end], "app.py", "exec"), rns)
refine_rug_mask = rns["refine_rug_mask"]
def striped(shape):
yy, xx = np.indices(shape)
return (90 + 60 * ((xx + yy // 4) % 2)).astype(np.uint8)
img2 = np.full((H, W, 3), 170, np.uint8)
seg2 = np.zeros((H, W), np.int64)
rug2 = np.zeros((H, W), np.uint8)
# main rug: striped pattern, 120x160
rug2[300:420, 200:360] = 1
img2[300:420, 200:360] = striped((120, 160))[..., None]
# stray island: 12x12 far away (mislabelled accent tile)
rug2[100:112, 500:512] = 1
# object on the rug: black 24x24 blob (slippers)
img2[340:364, 260:284] = 15
# look-alike soft fragment adjacent to the rug (same stripes)
seg2[300:420, 362:410] = SOFT_ID
img2[300:420, 362:410] = striped((120, 48))[..., None]
# genuine plain cushion adjacent on the other side (uniform, L matches
# the stripe median -> only the texture-contrast gate can save it)
seg2[300:420, 150:198] = SOFT_ID
img2[300:420, 150:198] = 120
refined, protect = refine_rug_mask(rug2, seg2, img2)
# 5 β stray island dropped, main rug kept
good = refined[100:112, 500:512].sum() == 0 and refined[305:315, 205:215].all()
print(f" [{'PASS' if good else 'FAIL'}] v2: stray island dropped, rug kept")
ok &= good
# 6 β object on the rug carved out and protected
blob = np.zeros((H, W), bool)
blob[342:362, 262:282] = True
good = (protect[blob].mean() > 0.9) and (refined[blob].sum() == 0)
print(f" [{'PASS' if good else 'FAIL'}] v2: object on rug carved out + protected "
f"(protected {protect[blob].mean():.2f} of blob)")
ok &= good
# 7 β look-alike fragment absorbed into the rug
good = refined[310:410, 370:400].mean() > 0.9
print(f" [{'PASS' if good else 'FAIL'}] v2: look-alike fragment absorbed "
f"({refined[310:410, 370:400].mean():.2f} of fragment)")
ok &= good
# 8 β plain cushion NOT absorbed (texture-contrast gate abstains)
good = refined[310:410, 160:190].sum() == 0
print(f" [{'PASS' if good else 'FAIL'}] v2: plain cushion stays an occluder")
ok &= good
# 9 β shading outside the feather band is untouched
feather_zone = cv2.dilate(rug, np.ones((81, 81), np.uint8)) > 0
outside = (mask > 0) & ~feather_zone
drift = float(np.abs(rel_with[outside] - rel_wo[outside]).mean())
good = drift < 0.02
print(f" [{'PASS' if good else 'FAIL'}] outside feather band untouched: "
f"mean drift {drift:.4f} < 0.02")
ok &= good
print("\n" + ("ALL R3-3 SIM CHECKS PASSED" if ok else "R3-3 SIM CHECKS FAILED"))
return 0 if ok else 1
if __name__ == "__main__":
raise SystemExit(main())
|