# Grouper: closed regions of the sheet by flood fill from a seed through non-line pixels (plain Python). # region(seed, box) -> mask; describe() -> bbox, area, per-row extents. Used to read windows, door, porthole, panels. import numpy as np from PIL import Image import os, json, sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from gr_trace import R, dilate, propagate, LINE_T def region(seed, box, thr=LINE_T, grow=0): x0, y0, x1, y1 = box line = R[y0:y1, x0:x1] > thr if grow: line = dilate(line, grow) s = np.zeros_like(line) s[seed[1] - y0, seed[0] - x0] = True m = propagate(s, ~line) full = np.zeros(R.shape, bool) full[y0:y1, x0:x1] = m return full def describe(m, step=2, axis="rows"): ys, xs = np.where(m) d = {"bbox": [int(xs.min()), int(ys.min()), int(xs.max()), int(ys.max())], "area": int(m.sum()), "centroid": [round(float(xs.mean()), 1), round(float(ys.mean()), 1)]} if axis == "rows": d["rows"] = [(int(y), int(xs[ys == y].min()), int(xs[ys == y].max())) for y in range(ys.min(), ys.max() + 1, step) if (ys == y).any()] else: d["cols"] = [(int(x), int(ys[xs == x].min()), int(ys[xs == x].max())) for x in range(xs.min(), xs.max() + 1, step) if (xs == x).any()] return d if __name__ == "__main__": SEEDS = json.loads(sys.argv[1]) for name, (sx, sy, x0, y0, x1, y1, axis, step, grow) in SEEDS.items(): m = region((sx, sy), (x0, y0, x1, y1), grow=grow) print(name, json.dumps(describe(m, step, axis)))