"""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())