#!/usr/bin/env python3 # -*- coding: utf-8 -*- """把发型对比测试结果生成 HTML 报告。 15行(3图×5发型) × 10列(4b@896 + 9b三模型×三分辨率),每行首列=原图。 图片 base64 内嵌,自包含单文件。 """ import base64 import json import os from pathlib import Path OUT = Path("/home/ubuntu/hair/benchmark_out/hairstyle") RESULTS = OUT / "results.json" HTML = OUT / "report.html" def img_src(path): """把绝对路径转成报告里的相对 URL(报告在 static/,图片在 static/bench/)。""" if not path: return None p = str(path) if "benchmark_out/hairstyle/" in p: return "bench/hairstyle/" + os.path.basename(p) if "benchmark_out/matrix/" in p: return "bench/matrix/" + os.path.basename(p) return None def main(): d = json.load(open(RESULTS, encoding="utf-8")) columns = d["columns"] rows = d["rows"] # 统计每列的平均耗时、峰值显存 col_stats = {} for ct in columns: times, peaks = [], [] for r in rows: for c in r["cells"]: if c.get("title") == ct and not c.get("error"): times.append(c["elapsed"]) peaks.append(c["gpu_peak"]) col_stats[ct] = { "avg_t": sum(times) / len(times) if times else 0, "max_p": max(peaks) / 1024 if peaks else 0, } # 表头:原图 + 10列 headers = ['原图'] for ct in columns: s = col_stats[ct] headers.append( f'
{ct}
' f'
{s["avg_t"]:.0f}s · {s["max_p"]:.0f}G
' ) # 表体:15行 body_rows = [] for r in rows: # 发型+图标签 label = f'
{r["img"]}
{r["hair_name"]}
' # 原图 ORIG_SRC = {"asdf": "bench/orig/asdf.jpg", "qwer": "bench/orig/qwer.jpg", "girl5": "bench/orig/girl5.jpg"} orig = ORIG_SRC.get(r["img"]) cells = [f'
{label}
' f''] # 10个结果列 for ct in columns: c = next((x for x in r["cells"] if x.get("title") == ct), {}) src = img_src(c.get("grown_path")) if not c.get("error") else None if src: cells.append( f'' f'
{c["elapsed"]:.1f}s
') else: cells.append(f'
') body_rows.append(f'{"".join(cells)}') html = f""" 发型对比测试报告 — 4模型×3分辨率

💇 发型对比测试报告

接口2女性 · 3图×5发型=15行 · 每行: 4B@896(1) + 9B(fp8/Q5/Q4)×(原图/896/640)(9) · 150/150成功 · RTX3090

列标题下显示平均耗时 · 峰值显存。横向滚动查看更多列。原图列含图片名+发型名。
{"".join(headers)} {"".join(body_rows)}
""" with open(HTML, "w", encoding="utf-8") as f: f.write(html) print(f"✓ 报告: {HTML} ({HTML.stat().st_size//1024} KB)") if __name__ == "__main__": main()