# Mako: silhouettes and colour classes of the user's reference sheet (plain Python + Pillow + numpy). # Object pixels: anything not near-white (the sheet's background and its pale grid are all >= 230); the user's red marking # (the holder clips' place) is left out of the silhouettes and kept as its own mask. # Writes reference/classes.png (orange, glass, grey, dark, red in flat colours) and checks/silhouettes.json: # per view, per image column (or row), the first and last object pixel. import os, json import numpy as np from PIL import Image HERE = os.path.dirname(os.path.abspath(__file__)) REF = os.path.join(os.path.dirname(HERE), "reference") a = np.asarray(Image.open(os.path.join(REF, "user_reference.webp")).convert("RGB")).astype(int) R, G, B = a[..., 0], a[..., 1], a[..., 2] mx, mn = a.max(-1), a.min(-1) red = (R - G > 25) & (B - G > -15) & (R > 120) obj = ((mn < 222) | (mx - mn > 45)) & ~red orange = obj & (R > 120) & (R - G > 25) & (G - B > 20) glass = obj & (B - R > 35) & (B > 120) dark = obj & (mx < 90) grey = obj & ~orange & ~glass & ~dark cls = np.full(a.shape, 255, np.uint8) cls[grey] = (150, 150, 150); cls[dark] = (40, 40, 40); cls[glass] = (90, 170, 240); cls[orange] = (250, 150, 30) cls[red] = (230, 0, 0) Image.fromarray(cls).save(os.path.join(REF, "classes.png")) BOX = {"top": (30, 40, 970, 520), "side": (30, 530, 970, 1065), "front": (970, 30, 1410, 530), "rear": (960, 545, 1410, 1030)} out = {} for name, (x0, y0, x1, y1) in BOX.items(): m = obj[y0:y1, x0:x1] cols = {} for x in range(x0, x1): ys = np.where(m[:, x - x0])[0] if len(ys): cols[x] = [int(ys[0] + y0), int(ys[-1] + y0)] rows = {} for y in range(y0, y1): xs = np.where(m[y - y0])[0] if len(xs): rows[y] = [int(xs[0] + x0), int(xs[-1] + x0)] out[name] = {"cols": cols, "rows": rows} ry, rx = np.where(red) out["red"] = {"n": int(len(rx)), "x": [int(rx.min()), int(rx.max())] if len(rx) else None} os.makedirs(os.path.join(HERE, "checks"), exist_ok=True) json.dump(out, open(os.path.join(HERE, "checks", "silhouettes.json"), "w")) for name in ("top", "side"): c = out[name]["cols"] print(name, " ".join("%d:%s" % (x, c.get(x)) for x in range(40, 970, 20))) for name in ("front", "rear"): r = out[name]["rows"] print(name, " ".join("%d:%s" % (y, r.get(y)) for y in range(BOX[name][1], BOX[name][3], 20)))