import sys sys.path.insert(0, "services/recolor") import numpy as np from PIL import Image import cv2 from fabric_recolor.segmentation.birefnet import BirefnetMatteSegmenter from fabric_recolor.segmentation.prompts import NEGATIVE_PROMPTS, CAVITY_PROMPTS from fabric_recolor.masks import (alpha_hysteresis, clean_binary, largest_component, fill_small_holes, _silhouette_bands, cavity_anchors) from fabric_recolor.labcolor import rgb_to_lab src = "data/media/originals/fd/fd12e584a23312c7c5edda1015fe9715d3f5fd19a2ef3d375d635cefab91f54b.jpg" img = Image.open(src).convert("RGB") W0,H0 = img.width, img.height scale = min(1.0, 1600/max(H0,W0)) seg = img.resize((round(W0*scale), round(H0*scale)), Image.BILINEAR) arr = np.asarray(seg) sb = BirefnetMatteSegmenter(); sb._load() matte = alpha_hysteresis(sb._matte(seg), ramp_px=max(4,round(8*scale))) mask = clean_binary((matte>=0.5).astype(np.uint8),0.002) mask = largest_component(mask); mask = fill_small_holes(mask,0.01) iso = Image.fromarray(arr * mask[...,None].astype(np.uint8)) raw = sb._neg_segmenter().negatives_instances(iso, NEGATIVE_PROMPTS) cav_ids = {i for i,p in enumerate(NEGATIVE_PROMPTS) if p in CAVITY_PROMPTS} lab = rgb_to_lab(arr) med = np.median(lab[mask>0].reshape(-1,3), axis=0) band,_ = _silhouette_bands(mask,6) obj = int(mask.sum()) for m,idx in raw: comp = (m>0)&(mask>0); a=int(comp.sum()) if a<16: continue bf = float((comp&(band>0)).sum())/a de = float(np.linalg.norm(lab[comp].mean(0)-med)) cav = idx in cav_ids verdict=[] if cav and a<=0.5*obj and bf<0.005: verdict.append("CAVITY_CUT") if de>12: verdict.append("DE_CUT") if bf>=0.5: verdict.append("APPENDAGE_CUT") if not verdict: verdict=["KEEP"] print(f"'{NEGATIVE_PROMPTS[idx]}' area={a}({a/obj:.0%}) band={bf:.3f} dE={de:.1f} -> {'+'.join(verdict)}")