"""Inpaint mask construction from a floor footprint + item height (stage 5). The mask is the silhouette of the item's 3D bounding box: the floor footprint quad plus the same quad raised by the item's pixel height. The image-conditioned inpaint then paints the reference furniture into exactly this region. """ from __future__ import annotations from PIL import Image, ImageDraw, ImageFilter from shapely.geometry import Polygon def build_mask( image_size: tuple[int, int], footprint_quad: list[list[float]], height_px: float, feather: int = 6, ) -> tuple[Image.Image, tuple[int, int, int, int]]: """Return (mask, bbox). ``mask`` is an 'L' image, 255 = region to inpaint.""" w, h = image_size pts = [(float(x), float(y)) for x, y in footprint_quad] raised = [(x, y - height_px) for x, y in pts] hull = Polygon(pts + raised).convex_hull coords = [(float(x), float(y)) for x, y in hull.exterior.coords] mask = Image.new("L", (w, h), 0) ImageDraw.Draw(mask).polygon(coords, fill=255) if feather > 0: mask = mask.filter(ImageFilter.GaussianBlur(feather)) xs = [c[0] for c in coords] ys = [c[1] for c in coords] bbox = ( max(0, int(min(xs))), max(0, int(min(ys))), min(w, int(max(xs))), min(h, int(max(ys))), ) return mask, bbox