"""Câmera ajustada das cenas G, H, I, K (agente w-google, 17/10).

A câmera medida (cena-<id>.json) confundia a inclinação 3D das interfaces com giro e errava zoom/mira nos
chicotes. Aqui ela é refeita por homografia contra o quadro de referência (SIFT, direto ou em cadeia) e
decomposta em: similaridade no centro da tela (controles do CAM: zoom, mira, giro) + resto projetivo
(Corner Pin no comp da cena, guardado como deslocamento dos 4 cantos do quadro ampliado com margem).
Entradas: JSON por quadro gerados por ajustar_h.py / ecc_cadeia.py (scratchpad do agente; o essencial está aqui).
Saída: camera/cena-<id>-ajustada.json no formato do camera.jsx ({chaves: zoom, mx, my, giro}) + "pin" e "margem".
Regras: Savitzky-Golay de 5 quadros; pin zerado no quadro da troca e misturado (smoothstep) até a primeira
medida boa, para o encaixe encher a tela exatamente na troca.
uso: python camera/wg_finalizar_cam.py <id> <entrada.json> [--pin-zero t_ini t_fim_rampa] [--json-ate t] [--mistura t0 t1]
"""
import sys, json, math, numpy as np
from scipy.signal import savgol_filter
a = sys.argv; cid = a[1]; ent = json.load(open(a[2]))
P = "<SUA_CENTRAL>/07-videos/projetos/2026-10-17-subzmotion-recriacao/"
q = ent["quadros"]; t = np.array([x["t"] for x in q])
z = np.array([x["zoom"] for x in q]); mx = np.array([x["mx"] for x in q]); my = np.array([x["my"] for x in q]); g = np.array([x["giro"] for x in q])
cp = np.array([x.get("cp", [0.0] * 8) for x in q])
def ss(u): u = min(1, max(0, u)); return u * u * (3 - 2 * u)
if "--pin-zero" in a:
    i = a.index("--pin-zero"); ta, tb = float(a[i + 1]), float(a[i + 2])
    jb = int(np.argmin(abs(t - tb))); alvo = cp[jb].copy()
    for j in range(len(t)):
        if t[j] <= ta + 1e-6: cp[j] = 0
        elif t[j] < tb: cp[j] = alvo * ss((t[j] - ta) / (tb - ta))
if "--mistura" in a:   # troca suave entre a câmera json (antes de t0) e a ajustada (depois de t1)
    i = a.index("--mistura"); t0, t1 = float(a[i + 1]), float(a[i + 2])
    d = json.load(open(P + "camera/cena-%s.json" % cid, encoding="utf-8"))["chaves"]
    def jv(n, tt): return float(np.interp(tt, [x[0] for x in d[n]], [x[1] for x in d[n]]))
    for j in range(len(t)):
        if t[j] < t1:
            w = ss((t[j] - t0) / (t1 - t0)) if t[j] > t0 else 0.0
            z[j] = jv("zoom", t[j]) * (1 - w) + z[j] * w; mx[j] = jv("mx", t[j]) * (1 - w) + mx[j] * w
            my[j] = jv("my", t[j]) * (1 - w) + my[j] * w; g[j] = jv("giro", t[j]) * (1 - w) + g[j] * w
            cp[j] = cp[j] * w
z, mx, my, g = [savgol_filter(v, 5, 2) for v in (z, mx, my, g)]
cp = savgol_filter(cp, 5, 2, axis=0)
if "--pin-zero" in a:
    for j in range(len(t)):
        if t[j] <= ta + 1e-6: cp[j] = 0
src = json.load(open(P + "camera/cena-%s.json" % cid, encoding="utf-8"))
out = {"fps": 24, "ini": src["ini"], "fim": src["fim"], "ref": src["ref"], "pegada": src["pegada"], "margem": ent.get("margem", 270),
       "origem": "wg_finalizar_cam.py (homografia + Corner Pin)",
       "chaves": {"zoom": [[round(float(t[j]), 4), round(float(z[j]), 4)] for j in range(len(t))],
                  "mx": [[round(float(t[j]), 4), round(float(mx[j]), 3)] for j in range(len(t))],
                  "my": [[round(float(t[j]), 4), round(float(my[j]), 3)] for j in range(len(t))],
                  "giro": [[round(float(t[j]), 4), round(float(g[j]), 3)] for j in range(len(t))]},
       "pin": [[round(float(t[j]), 4)] + [round(float(v), 2) for v in cp[j]] for j in range(len(t))]}
json.dump(out, open(P + "camera/cena-%s-ajustada.json" % cid, "w"))
print("ok", cid, len(t), "quadros; pin max %.1f" % abs(cp).max())
# --- cantos do Corner Pin para a margem real do comp interno (alvo em coordenadas da camada interna)
import cv2
MR = float(a[a.index("--margem-real") + 1]) if "--margem-real" in a else out["margem"]
MG = out["margem"]
CANT = np.float32([[-MG, -MG], [1080 + MG, -MG], [-MG, 1080 + MG], [1080 + MG, 1080 + MG]])
REAL = np.float32([[[-MR, -MR], [1080 + MR, -MR], [-MR, 1080 + MR], [1080 + MR, 1080 + MR]]])
cantos = []
for row in out["pin"]:
    Pm = cv2.getPerspectiveTransform(CANT, (CANT + np.float32(row[1:]).reshape(4, 2)).astype(np.float32))
    alvo = cv2.perspectiveTransform(REAL, Pm)[0] + MR
    cantos.append([row[0]] + [round(float(v), 2) for v in alvo.ravel()])
out["margem_real"] = MR; out["cantos"] = cantos
json.dump(out, open(P + "camera/cena-%s-ajustada.json" % cid, "w"))
print("cantos para margem real", MR)
