Document the two repixelization engines

This commit is contained in:
Meta Vens 2026-04-24 01:10:40 +01:00
commit f95440351c
5 changed files with 241 additions and 8 deletions

View file

@ -20,7 +20,7 @@ class RenderedPanel:
def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Regenerate the README comparison sheet and guard closeup from repo fixtures.")
parser = argparse.ArgumentParser(description="Regenerate the README comparison sheets and closeups from repo fixtures.")
parser.add_argument(
"--vector-input",
default="tests/fixtures/real/ai-badge-vector.png",
@ -41,6 +41,11 @@ def _parse_args() -> argparse.Namespace:
default="docs/readme-assets/guard-right-crop-comparison.png",
help="Output path for the standalone sword-guard closeup strip.",
)
parser.add_argument(
"--out-engine-sheet",
default="docs/readme-assets/engine-comparison-sheet.png",
help="Output path for the pinned phase-field vs tile-graph engine comparison sheet.",
)
parser.add_argument(
"--scratch-dir",
default="artifacts/readme-build",
@ -60,6 +65,38 @@ def _parse_args() -> argparse.Namespace:
metavar=("X0", "Y0", "X1", "Y1"),
help="Sword-guard crop bounds in output-grid cell coordinates for the AI row.",
)
parser.add_argument(
"--engine-target-width",
type=int,
default=126,
help="Pinned target width for the engine-vs-engine badge comparison.",
)
parser.add_argument(
"--engine-target-height",
type=int,
default=126,
help="Pinned target height for the engine-vs-engine badge comparison.",
)
parser.add_argument(
"--engine-phase-x",
type=float,
default=0.0,
help="Pinned lattice phase X for the engine-vs-engine badge comparison.",
)
parser.add_argument(
"--engine-phase-y",
type=float,
default=-0.2,
help="Pinned lattice phase Y for the engine-vs-engine badge comparison.",
)
parser.add_argument(
"--engine-cell-bbox",
nargs=4,
type=int,
default=(67, 90, 97, 122),
metavar=("X0", "Y0", "X1", "Y1"),
help="Tracked sword-tip crop bounds in output-grid cell coordinates for the pinned engine comparison.",
)
parser.add_argument("--steps", type=int, default=48, help="Optimizer step budget for both runs.")
parser.add_argument("--device", default="cpu", choices=("auto", "cpu", "cuda"), help="Torch device for generation.")
return parser.parse_args()
@ -247,6 +284,135 @@ def _save_summary(path: Path, payload: dict[str, object]) -> None:
path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
def _build_engine_comparison_sheet(
*,
source_rgba: np.ndarray,
phase_field_rgba: np.ndarray,
tile_graph_rgba: np.ndarray,
focus_source_bbox: tuple[int, int, int, int],
focus_cell_bbox: tuple[int, int, int, int],
target_width: int,
target_height: int,
phase_x: float,
phase_y: float,
) -> Image.Image:
top_panel_width = 320
top_panel_height = 338
crop_panel_width = 240
crop_panel_height = 210
col_gap = 18
row_gap = 18
margin = 24
title_height = 24
row_title_height = 20
top_panels = [
_render_panel(
"Source",
rgba=source_rgba,
pixelated=False,
panel_width=top_panel_width,
panel_height=top_panel_height,
subtitle="Cleaned AI fake pixel badge",
),
_render_panel(
"Phase-field",
rgba=phase_field_rgba,
pixelated=True,
panel_width=top_panel_width,
panel_height=top_panel_height,
subtitle=f"{target_width}x{target_height} pinned lattice",
),
_render_panel(
"Tile-graph",
rgba=tile_graph_rgba,
pixelated=True,
panel_width=top_panel_width,
panel_height=top_panel_height,
subtitle=f"{target_width}x{target_height} pinned lattice",
),
]
_draw_source_bbox(
top_panels[0],
focus_source_bbox,
source_width=source_rgba.shape[1],
source_height=source_rgba.shape[0],
)
_draw_source_bbox(
top_panels[1],
focus_cell_bbox,
source_width=phase_field_rgba.shape[1],
source_height=phase_field_rgba.shape[0],
)
_draw_source_bbox(
top_panels[2],
focus_cell_bbox,
source_width=tile_graph_rgba.shape[1],
source_height=tile_graph_rgba.shape[0],
)
crop_panels = [
_render_panel(
"Source focus",
rgba=_crop_rgba(source_rgba, focus_source_bbox),
pixelated=True,
panel_width=crop_panel_width,
panel_height=crop_panel_height,
subtitle="Tracked sword-tip crop",
),
_render_panel(
"Phase-field focus",
rgba=_crop_rgba(phase_field_rgba, focus_cell_bbox),
pixelated=True,
panel_width=crop_panel_width,
panel_height=crop_panel_height,
subtitle="Default optimizer",
),
_render_panel(
"Tile-graph focus",
rgba=_crop_rgba(tile_graph_rgba, focus_cell_bbox),
pixelated=True,
panel_width=crop_panel_width,
panel_height=crop_panel_height,
subtitle="Source-owned alternate solver",
),
]
width = margin * 2 + top_panel_width * 3 + col_gap * 2
height = (
margin * 2
+ title_height
+ row_title_height * 2
+ top_panel_height
+ crop_panel_height
+ row_gap
)
canvas = Image.new("RGBA", (width, height), (11, 11, 13, 255))
draw = ImageDraw.Draw(canvas)
draw.text(
(margin, margin - 2),
f"Pinned badge lattice: {target_width}x{target_height} @ ({phase_x:.1f}, {phase_y:.1f})",
fill=(255, 255, 255, 255),
)
draw.text((margin, margin + title_height), "Whole image", fill=(255, 255, 255, 255))
top_y = margin + title_height + row_title_height
crop_row_y = top_y + top_panel_height + row_gap
draw.text((margin, crop_row_y), "Tracked sword-tip crop", fill=(255, 255, 255, 255))
crop_y = crop_row_y + row_title_height
x = margin
for panel in top_panels:
canvas.alpha_composite(panel.image, (x, top_y))
x += top_panel_width + col_gap
x = margin
for panel in crop_panels:
canvas.alpha_composite(panel.image, (x, crop_y))
x += crop_panel_width + col_gap
return canvas
def main() -> None:
args = _parse_args()
scratch_dir = Path(args.scratch_dir)
@ -256,8 +422,10 @@ def main() -> None:
ai_input = Path(args.ai_input)
out_sheet = Path(args.out_sheet)
out_guard_crop = Path(args.out_guard_crop)
out_engine_sheet = Path(args.out_engine_sheet)
out_sheet.parent.mkdir(parents=True, exist_ok=True)
out_guard_crop.parent.mkdir(parents=True, exist_ok=True)
out_engine_sheet.parent.mkdir(parents=True, exist_ok=True)
vector_result = run_pipeline(
vector_input,
@ -274,6 +442,32 @@ def main() -> None:
steps=args.steps,
device=args.device,
)
phase_field_engine_result = run_pipeline(
ai_input,
scratch_dir / "badge-ai-phase-field-pinned.png",
target_width=args.engine_target_width,
target_height=args.engine_target_height,
phase_x=args.engine_phase_x,
phase_y=args.engine_phase_y,
diagnostics_dir=scratch_dir / "engine-phase-field-diag",
steps=args.steps,
device=args.device,
reconstruction_mode="phase-field",
enable_phase_rerank=False,
)
tile_graph_engine_result = run_pipeline(
ai_input,
scratch_dir / "badge-ai-tile-graph-pinned.png",
target_width=args.engine_target_width,
target_height=args.engine_target_height,
phase_x=args.engine_phase_x,
phase_y=args.engine_phase_y,
diagnostics_dir=scratch_dir / "engine-tile-graph-diag",
steps=args.steps,
device=args.device,
reconstruction_mode="tile-graph",
enable_phase_rerank=False,
)
vector_source = load_rgba(vector_input)
ai_source = load_rgba(ai_input)
@ -430,6 +624,26 @@ def main() -> None:
out_sheet.parent.mkdir(parents=True, exist_ok=True)
canvas.save(out_sheet)
engine_focus_source_bbox = _cell_bbox_to_source_bbox(
tuple(args.engine_cell_bbox),
source_width=ai_source.shape[1],
source_height=ai_source.shape[0],
target_width=args.engine_target_width,
target_height=args.engine_target_height,
)
engine_sheet = _build_engine_comparison_sheet(
source_rgba=ai_source,
phase_field_rgba=phase_field_engine_result.output_rgba,
tile_graph_rgba=tile_graph_engine_result.output_rgba,
focus_source_bbox=engine_focus_source_bbox,
focus_cell_bbox=tuple(args.engine_cell_bbox),
target_width=args.engine_target_width,
target_height=args.engine_target_height,
phase_x=args.engine_phase_x,
phase_y=args.engine_phase_y,
)
engine_sheet.save(out_engine_sheet)
_save_summary(
scratch_dir / "readme-preview-summary.json",
{
@ -443,14 +657,22 @@ def main() -> None:
"vector_guard_inset_source_bbox": list(vector_guard_inset_bbox),
"guard_source_bbox": list(guard_bbox),
"ai_guard_inset_source_bbox": list(ai_guard_inset_bbox),
"engine_target_width": args.engine_target_width,
"engine_target_height": args.engine_target_height,
"engine_phase_x": args.engine_phase_x,
"engine_phase_y": args.engine_phase_y,
"engine_cell_bbox": list(args.engine_cell_bbox),
"engine_focus_source_bbox": list(engine_focus_source_bbox),
"out_sheet": str(out_sheet),
"out_guard_crop": str(out_guard_crop),
"out_engine_sheet": str(out_engine_sheet),
"scratch_dir": str(scratch_dir),
},
)
print(str(out_sheet))
print(str(out_guard_crop))
print(str(out_engine_sheet))
if __name__ == "__main__":