Adding fix

This commit is contained in:
2026-07-19 20:45:40 +02:00
parent 71f2c51b1b
commit 99ddc2e425
+41 -14
View File
@@ -4772,11 +4772,29 @@ def _measure_suit(ref: Path, filters: "list[dict]") -> "tuple[int, int, int]":
return (sr // n, sg // n, sb // n) if n else (0, 0, 0)
def _png_dims(path: Path) -> "tuple[int, int]":
"""Return (width, height) of an image/frame, or (1920, 1080) on failure."""
r = subprocess.run(
["ffprobe", "-v", "error", "-select_streams", "v:0",
"-show_entries", "stream=width,height", "-of", "csv=p=0:s=x", str(path)],
capture_output=True, text=True,
)
try:
w, h = r.stdout.strip().split("x")[:2]
return int(w), int(h)
except ValueError:
return (1920, 1080)
def _render_preview(ref: Path, filters: "list[dict]", out_png: Path) -> None:
"""Save the filtered still composited over magenta (to judge the matte)."""
"""Save the filtered still composited over magenta (to judge the matte).
The magenta layer is sized to the frame so the full frame shows at any
source resolution — a fixed-size backdrop would crop the overlay."""
vf = _grade_video_filter(filters)
w, h = _png_dims(ref)
cmd = ["ffmpeg", "-y", "-v", "error",
"-f", "lavfi", "-i", "color=c=magenta:s=1280x720",
"-f", "lavfi", "-i", f"color=c=magenta:s={w}x{h}",
"-i", str(ref), "-filter_complex",
f"[1]{vf},format=yuva444p10le[fg];"
f"[0][fg]overlay=shortest=1,format=rgb24",
@@ -4861,24 +4879,32 @@ def _stage_key(project_path, filters, ref, out_dir, source_name, ss) -> int:
def _stage_despill(project_path, filters, ref, out_dir, source_name, ss) -> int:
"""Deterministic spill_suppress sweep 0.71.5 → candidates for a visual pick."""
"""Deterministic spill_suppress sweep 0.51.5 → candidates for a visual pick.
Reports both sides of the tradeoff: scalp green_cast (want ~0) AND the
costume's orange-ness (suit RG, want low). Over-despilling clears the
scalp but pushes a yellow costume orange, so the balance point — not the
maximum — is usually right."""
base = _grade_step(filters, "gnommokey")
values = [round(0.7 + (1.5 - 0.7) * i / 6, 2) for i in range(7)] # 0.7 .. 1.5
print(" Sweeping spill_suppress 0.7 → 1.5 (yellow_protect held fixed)")
values = [round(0.5 + (1.5 - 0.5) * i / 8, 3) for i in range(9)] # 0.5 .. 1.5
print(" Sweeping spill_suppress 0.5 → 1.5 (yellow_protect held fixed)")
suit_raw = _measure_suit(ref, _mask_and(filters, dict(base, spill_suppress=0)))
candidates = []
for i, v in enumerate(values, 1):
cfg = dict(base)
cfg["spill_suppress"] = v
chain = _mask_and(filters, cfg)
cast = _measure_green_cast(ref, chain)
suit = _measure_suit(ref, chain)
png = out_dir / f"despill_{i}.png"
_render_preview(ref, chain, png)
candidates.append({
"id": f"despill_{i}", "file": png.name,
"params": {"spill_suppress": v}, "hint": {"green_cast": cast},
"params": {"spill_suppress": v},
"hint": {"green_cast": cast, "suit_orange": suit[0] - suit[1]},
})
# Advisory only: the value nearest neutral green cast. Localized bald-head
# spill means the eye is the real judge, hence a full sweep to pick from.
# Advisory: nearest-neutral scalp cast — the balance point that clears the
# scalp without needlessly orange-ing the costume (over-despill goes magenta).
rec = min(candidates, key=lambda c: abs(c["hint"]["green_cast"]))["id"]
manifest = {
"stage": "despill", "target_step": "gnommokey",
@@ -4886,15 +4912,16 @@ def _stage_despill(project_path, filters, ref, out_dir, source_name, ss) -> int:
"recommended": rec, "candidates": candidates,
}
mpath = _grade_write_manifest(out_dir, manifest)
print(f" {'id':>12} {'spill':>7} {'green_cast':>10} png")
print(f" {'-'*12} {'-'*7} {'-'*10} {'-'*3}")
print(f" raw costume RG (target for suit_orange): {suit_raw[0] - suit_raw[1]}")
print(f" {'id':>12} {'spill':>6} {'scalp cast':>10} {'suit_orange':>11} png")
print(f" {'-'*12} {'-'*6} {'-'*10} {'-'*11} {'-'*3}")
for c in candidates:
star = " ◀ suggested" if c["id"] == rec else ""
print(f" {c['id']:>12} {c['params']['spill_suppress']:>7} "
f"{c['hint']['green_cast']:>10} {c['file']}{star}")
print("\n green_cast: >0 residual green · ~0 neutral · <0 over-despilled (magenta)")
print(f" {c['id']:>12} {c['params']['spill_suppress']:>6} "
f"{c['hint']['green_cast']:>10} {c['hint']['suit_orange']:>11} {c['file']}{star}")
print("\n scalp cast: >0 green · ~0 neutral · <0 magenta | suit_orange: lower = more yellow")
print(f" Manifest: {mpath}")
print(" Pick the one with a clean crown and no magenta skin:")
print(" Pick the balance — scalp near 0 without the suit going orange:")
print(f" gnommo -p {project_path.name} grade --pick despill_5")
return 0