Spaces:
Sleeping
Sleeping
| """N2 β fill_enclosed_islands must absorb accent-tile islands even when | |
| segmentation noise bridges them to a large protected hole or sprinkles a few | |
| protected pixels over them (the room-4 blue accent tile escaped both ways). | |
| Cases: | |
| 1. plain enclosed island -> filled (regression) | |
| 2. island bridged (1px chain) to big mat hole -> filled (N2 fix) | |
| 3. island 30% covered by protect (chair leg) -> kept (guard) | |
| 4. island with 2 stray protected pixels (~1%) -> filled (N2 fix) | |
| 5. hole touching the image border -> kept (guard) | |
| 6. large hole (over max_area) -> kept (guard) | |
| """ | |
| import cv2 | |
| import numpy as np | |
| # --- extract the real implementation from app.py --------------------------- | |
| src = open("app.py").read() | |
| ns = {"np": np, "cv2": cv2} | |
| start = src.index("def fill_enclosed_islands") | |
| end = src.index("\ndef ", start + 10) | |
| exec(compile(src[start:end], "app.py", "exec"), ns) | |
| fill_enclosed_islands = ns["fill_enclosed_islands"] | |
| def main(): | |
| h, w = 400, 600 | |
| mask = np.ones((h, w), np.uint8) | |
| protect = np.zeros((h, w), np.uint8) | |
| # 1. plain island, 20x20 | |
| mask[50:70, 50:70] = 0 | |
| # 2. island 16x16 + 1px bridge to a big protected mat hole (90x40) | |
| mask[200:240, 150:240] = 0 # mat hole | |
| protect[200:240, 150:240] = 1 # mat is occluder-protected | |
| mask[210:226, 260:276] = 0 # accent island nearby | |
| mask[217, 240:260] = 0 # 1px bridge connecting them | |
| # 3. island 20x20 with 30% protect coverage (a real object remnant) | |
| mask[300:320, 60:80] = 0 | |
| protect[300:320, 60:66] = 1 # 6/20 columns = 30% | |
| # 4. island 20x20 with 2 stray protected pixels | |
| mask[80:100, 400:420] = 0 | |
| protect[85, 405] = 1 | |
| protect[92, 412] = 1 | |
| # 5. border-touching hole | |
| mask[0:30, 500:540] = 0 | |
| # 6. big hole, over max_area | |
| mask[280:360, 380:560] = 0 # 80x180 = 14400 | |
| out = fill_enclosed_islands(mask, protect, max_area=2000) | |
| # 7. final unprotected sweep (N2b): a fully-protected small island β a | |
| # pattern feature the segmenter calls an object β must fill when the sweep | |
| # runs without class protection on the finished surface, while the big | |
| # protected mat hole still survives via max_area. | |
| mask7 = np.ones((400, 600), np.uint8) | |
| mask7[150:175, 300:330] = 0 # "blue accent tile" island | |
| mask7[200:240, 100:190] = 0 # mat-sized hole (3600 px) | |
| out7 = fill_enclosed_islands(mask7, None, max_area=1000) | |
| checks = [ | |
| ("1 plain island filled", bool((out[52:68, 52:68] == 1).all())), | |
| ("2 bridged island filled", bool((out[212:224, 262:274] == 1).all())), | |
| ("2 mat hole kept", bool((out[205:235, 155:235] == 0).all())), | |
| ("3 protected island kept", bool((out[302:318, 62:78] == 0).all())), | |
| ("4 stray-pixel island filled", bool((out[82:98, 402:418] == 1).all())), | |
| ("5 border hole kept", bool((out[2:28, 502:538] == 0).all())), | |
| ("6 big hole kept", bool((out[285:355, 385:555] == 0).all())), | |
| ("7 final sweep fills pattern island", bool((out7[152:173, 302:328] == 1).all())), | |
| ("7 final sweep keeps big hole", bool((out7[205:235, 105:185] == 0).all())), | |
| ] | |
| ok = True | |
| for name, passed in checks: | |
| print(f" [{'PASS' if passed else 'FAIL'}] {name}") | |
| ok &= passed | |
| print("\n" + ("ALL N2 CHECKS PASSED" if ok else "N2 CHECKS FAILED")) | |
| return 0 if ok else 1 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |