| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- from __future__ import annotations
- import json
- from pathlib import Path
- from PIL import Image, ImageDraw, ImageFont
- ROOT = Path(__file__).resolve().parents[1]
- REVIEW_DIR = ROOT / "artifacts" / "music-template-extraction" / "review"
- OUTPUT_DIR = ROOT / "artifacts" / "music-template-extraction" / "contact-sheets-local"
- def load_font(size: int) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
- for path in (
- Path(r"C:\Windows\Fonts\msyh.ttc"),
- Path(r"C:\Windows\Fonts\simhei.ttf"),
- ):
- if path.exists():
- return ImageFont.truetype(str(path), size)
- return ImageFont.load_default()
- def crop_text(text: str, length: int = 38) -> str:
- return text if len(text) <= length else f"{text[:length]}…"
- def main() -> None:
- manifest = json.loads((REVIEW_DIR / "manifest.json").read_text(encoding="utf-8"))
- items = manifest["items"]
- OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
- title_font = load_font(24)
- meta_font = load_font(17)
- for scene in dict.fromkeys(item["scene"] for item in items):
- scene_items = [item for item in items if item["scene"] == scene]
- width = 1820
- row_height = 245
- canvas = Image.new("RGB", (width, 52 + row_height * len(scene_items)), "#f5f7fa")
- draw = ImageDraw.Draw(canvas)
- draw.text((18, 12), f"{scene} · {len(scene_items)} candidates", fill="#172033", font=title_font)
- for row, item in enumerate(scene_items):
- top = 52 + row * row_height
- draw.rectangle((8, top + 4, width - 8, top + row_height - 4), fill="white", outline="#d8dee8")
- label = f"{item['id']} {crop_text(item['name'])} · {item['slides']}页 · {item['score']}分"
- draw.text((20, top + 14), label, fill="#172033", font=meta_font)
- for column, filename in enumerate(item["samples"]):
- image_path = REVIEW_DIR / item["id"] / filename
- with Image.open(image_path) as sample:
- sample = sample.convert("RGB")
- sample.thumbnail((342, 192))
- x = 20 + column * 358
- y = top + 45
- canvas.paste(sample, (x, y))
- draw.rectangle((x, y, x + sample.width, y + sample.height), outline="#c9d1dc")
- canvas.save(OUTPUT_DIR / f"{scene}.jpg", quality=91, optimize=True)
- if __name__ == "__main__":
- main()
|