Files
AI_spine/run_case_matrix.py
T
2026-09-12 13:06:59 +08:00

43 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Run the placement stage against several existing split candidates.
This is an offline regression matrix: it does not call the image API. Point
the input map at generated candidate folders, then inspect each assembled.png
and case-summary.json under --out-dir.
"""
import argparse, json, shutil, subprocess
from pathlib import Path
from PIL import Image
import numpy as np
def main():
ap = argparse.ArgumentParser()
ap.add_argument('--reference', required=True)
ap.add_argument('--genielabs-dir', required=True)
ap.add_argument('--out-dir', required=True)
ap.add_argument('--candidate', action='append', nargs=2, metavar=('NAME','PARTS_DIR'), required=True)
args = ap.parse_args()
root = Path(args.out_dir); root.mkdir(parents=True, exist_ok=True)
py = '/Users/zhaoziyu/anaconda3/bin/python'
ref = Image.open(args.reference).convert('RGBA')
ref_rgb = np.asarray(ref)[:, :, :3].astype(np.float32)
ref_fg = np.asarray(ref)[:, :, 3] > 128
rows = []
for name, source in args.candidate:
case = root / name; parts = case / 'parts'; parts.mkdir(parents=True, exist_ok=True)
for f in Path(source).glob('*.png'): shutil.copy2(f, parts / f.name)
layout = case / 'layout.json'
subprocess.run([py, str(Path(args.genielabs_dir)/'scripts/position_parts.py'), '--reference', args.reference, '--parts', str(parts), '--output', str(layout)], check=True)
assembled = case / 'assembled.png'
subprocess.run([py, str(Path(__file__).with_name('compose_preview.py')), '--reference', args.reference, '--parts', str(parts), '--layout', str(layout), '--output', str(assembled)], check=True)
out = np.asarray(Image.open(assembled).convert('RGBA'))[:, :, :3].astype(np.float32)
err = float(np.mean(np.abs(out[ref_fg] - ref_rgb[ref_fg]))) if ref_fg.any() else None
data = json.loads(layout.read_text())
summary = {'name': name, 'parts': len(data.get('parts', {})), 'sift': sum(v.get('method') == 'sift' for v in data.get('parts', {}).values()), 'template': sum(v.get('method') == 'template' for v in data.get('parts', {}).values()), 'foreground_mae': round(err, 2) if err is not None else None, 'z_order': data.get('z_order', [])}
(case/'case-summary.json').write_text(json.dumps(summary, ensure_ascii=False, indent=2))
rows.append(summary)
(root/'case-report.json').write_text(json.dumps(rows, ensure_ascii=False, indent=2))
print(json.dumps(rows, ensure_ascii=False, indent=2))
if __name__ == '__main__': main()