43 lines
2.5 KiB
Python
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()
|