#!/usr/bin/env python3
"""Ri-ritaglio ROBUSTO di una carta (soglia-distanza auto-tarata).

Per carte dove autocrop (GrabCut+edge-fit) sbaglia: skew, sfondo che rientra,
carta ruotata, o pannello che si confonde col fondo. Sceglie la soglia di
distanza-dal-fondo il cui blob piu grande ha rapporto ~1.528 (cosi include il
pannello), ne prende il minAreaRect e raddrizza. Scrive in CROP_DIR/NN.jpg.

Uso: python recognition/recrop.py 1 17 23 50
Poi:  python recognition/build_cards.py --build 1 17 23 50
"""
import sys, cv2, numpy as np
import autocrop as AC

CROP_DIR = "/tmp/s53_crop3"
TARGET = 1.528


def recrop(n):
    img = cv2.imread(f"/tmp/s53/{n:02d}.jpg")
    if img is None:
        print(f"{n}: originale mancante"); return None
    H, W = img.shape[:2]; sc = 900 / max(H, W)
    s = cv2.resize(img, None, fx=sc, fy=sc)
    lab = cv2.cvtColor(s, cv2.COLOR_BGR2LAB).astype(np.float32)
    b = max(2, int(min(s.shape[:2]) * 0.05))
    bg = np.median(np.concatenate([lab[:b].reshape(-1, 3), lab[-b:].reshape(-1, 3),
                                   lab[:, :b].reshape(-1, 3), lab[:, -b:].reshape(-1, 3)]), 0)
    d = np.linalg.norm(lab - bg, axis=2)
    best = None
    for pct in range(55, 96, 2):
        m = (d > np.percentile(d, pct)).astype(np.uint8) * 255
        m = cv2.morphologyEx(m, cv2.MORPH_CLOSE, np.ones((25, 25), np.uint8), iterations=3)
        m = cv2.morphologyEx(m, cv2.MORPH_OPEN, np.ones((7, 7), np.uint8), iterations=1)
        cn, _ = cv2.findContours(m, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        if not cn:
            continue
        c = max(cn, key=cv2.contourArea); rect = cv2.minAreaRect(c); (cw, ch) = rect[1]
        if min(cw, ch) < 10:
            continue
        ratio = max(cw, ch) / min(cw, ch)
        area = cv2.contourArea(c) / (s.shape[0] * s.shape[1])
        if 0.03 < area < 0.7 and (best is None or abs(ratio - TARGET) < best[0]):
            best = (abs(ratio - TARGET), rect, ratio)
    if best is None:
        print(f"{n}: FAIL"); return None
    box = cv2.boxPoints(best[1]) / sc
    card = AC.warp(img, AC._order_pts(box.astype(np.float32)))
    cv2.imwrite(f"{CROP_DIR}/{n:02d}.jpg", card)
    print(f"{n}: ricavata ratio {best[2]:.3f}")
    return best[2]


if __name__ == "__main__":
    for n in map(int, sys.argv[1:]):
        recrop(n)
