Add the photo-anchored variant pass with night and overcast facade frames
Full build / Import + headless tests (push) Successful in 40s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-03 15:04:20 +01:00
1 parent 6e04c59589
commit ad91e71eeb
9 files changed
+183 -2

No files matched your search

+74
View File
@@ -31,6 +31,7 @@ import argparse
import json
import math
import os
import re
import sys
from pathlib import Path
@@ -1088,6 +1089,62 @@ def render_markdown(report: dict) -> str:
# ---------------------------------------------------------------------------
# Treatment clauses for the photo-anchored variant pass: one framing, several
# restaged conditions, so a concept board stays comparable with its photo board.
TREATMENTS = {
"day": "clean midday daylight, soft haze fading the far street to beige",
"night": "night scene lit by practical lights only (marquee, signage, street "
"lamps), dark sky, wet pavement reflections",
"weathered": "overcast flat light, weathered and grimy facade surfaces, faded "
"signage, scattered litter near the kerb",
}
def _anchor_treatment_prompt(context: str, treatment: str) -> str:
if treatment not in TREATMENTS:
sys.exit(f"error: unknown treatment '{treatment}'; "
f"choose from {sorted(TREATMENTS)}")
return f"{context}\n\n{REFERENCE_PROMPT_SUFFIX}\n\nRestage the scene: {TREATMENTS[treatment]}"
def cmd_anchor(args) -> int:
"""Generate day/night/weathered variants of one reference photo's framing."""
_load_env_file()
reference = _reference_source(args.reference, args.reference_unchecked)
treatments = [t.strip() for t in args.treatments.split(",") if t.strip()]
unknown = [t for t in treatments if t not in TREATMENTS]
if unknown:
sys.exit(f"error: unknown treatment(s) {unknown}; "
f"choose from {sorted(TREATMENTS)}")
out_dir = ROOT / args.out_dir
out_dir.mkdir(parents=True, exist_ok=True)
stem = args.name or re.sub(r"-[0-9]{4}-[0-9]{2}-[0-9]{2}$", "",
reference["path"].stem)
stem = re.sub(r"[^a-z0-9_]+", "_", stem.lower()).strip("_")
failed = []
for treatment in treatments:
prompt = _anchor_treatment_prompt(args.context, treatment)
print(f"anchoring {stem}_{treatment} ...", flush=True)
try:
image = generate_textures.generate_image(
prompt, args.model, args.request_size,
reference_path=reference["path"])
image = ImageOps.fit(image.convert("RGB"), (SCENE_W, SCENE_H),
method=Image.Resampling.LANCZOS)
except SystemExit as exc: # generate_textures exits on API errors
failed.append(treatment)
print(f" FAILED {treatment}: {exc}", file=sys.stderr)
continue
out = next_free_path(out_dir / f"{stem}_{treatment}.png")
image.save(out)
_write_reference_provenance(out, reference, f"{stem}_{treatment}", args.model)
print(f"wrote {_rel(out)} {image.size}")
if failed:
print("failed: " + ", ".join(failed), file=sys.stderr)
return 1
return 0
def cmd_list(_args) -> int:
for name, (group, _) in CATALOGUE.items():
have = len(raw_variants(name))
@@ -1123,6 +1180,23 @@ def build_parser():
prom.add_argument("--pick", default="", help="name=candidate overrides")
prom.set_defaults(handler=cmd_promote)
sub.add_parser("audit").set_defaults(handler=cmd_audit)
anchor = sub.add_parser("anchor",
help="generate day/night/weathered variants of one "
"reference photo's framing")
anchor.add_argument("--reference", required=True,
help="licence-cleared photo (listed in its refs SIDECAR.md)")
anchor.add_argument("--context", required=True,
help="what the photo shows and how to restage it")
anchor.add_argument("--treatments", default="day,night,weathered",
help="comma list from: " + ", ".join(sorted(TREATMENTS)))
anchor.add_argument("--out-dir", required=True,
help="concepts subfolder for the frames, relative to the repo root")
anchor.add_argument("--name", default="",
help="output stem (default: derived from the photo filename)")
anchor.add_argument("--model", default=DEFAULT_MODEL)
anchor.add_argument("--request-size", type=int, default=1536)
anchor.add_argument("--reference-unchecked", action="store_true")
anchor.set_defaults(handler=cmd_anchor)
real = sub.add_parser("realism")
real.add_argument("--run", required=True)
real.add_argument("--judge", action="store_true")