Files
hair/benchmark_res_compare_report.py
T
xsl bee7a487ac docs: 重绘分辨率对比报告(原图/896/768/640)
4图×5发型=20行,每行4分辨率对比,steps=15,热数据。
80/80成功,0 OOM,峰值21.2GB(原图不缩放也未OOM)。
报告: static/bench3_report.html
2026-07-26 19:10:33 +08:00

104 lines
4.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""生成分辨率对比报告:20行(4图×5发型) × 4列(原图不缩放/896/768/640)。"""
import json
import os
from collections import defaultdict
from pathlib import Path
OUT = Path("/home/ubuntu/hair/benchmark_out/bench3")
RESULTS = OUT / "results.json"
HTML = OUT / "report.html"
def img_src(path):
if not path or not os.path.isfile(path):
return None
return "bench3/" + os.path.basename(path)
def main():
d = json.load(open(RESULTS, encoding="utf-8"))
titles = d["res_titles"]
rows = d["rows"]
# 各分辨率平均耗时
col_stats = defaultdict(lambda: {"total": [], "comfy": []})
for r in rows:
for c in r["cells"]:
if c.get("ok"):
col_stats[c["res_title"]]["total"].append(c["total_ms"])
col_stats[c["res_title"]]["comfy"].append(c.get("comfy_ms", 0))
# 表头
headers = ['<th class="col-label">原图</th>']
for t in titles:
s = col_stats.get(t)
avg = sum(s["total"]) // len(s["total"]) if s and s["total"] else 0
headers.append(f'<th class="col-label"><div class="col-title">{t}</div>'
f'<div class="col-stat">均{avg/1000:.1f}s</div></th>')
# 表体
body_rows = []
for r in rows:
label = f'<div class="row-label">{r["img"]}<br><b>{r["hair_name"]}</b></div>'
# 原图缩略图(用 orig 档的结果当原图展示,或用原图文件)
orig_cell = f'<td class="cell-orig"><div class="row-label-cell">{label}</div></td>'
cells = [orig_cell]
for c in r["cells"]:
src = img_src(c.get("grown_path")) if c.get("ok") else None
if src:
t = c.get("total_ms", 0)
cells.append(f'<td class="cell-result"><img class="result-img" src="{src}" loading="lazy">'
f'<div class="cell-time">{t/1000:.1f}s</div></td>')
else:
cells.append(f'<td class="cell-result"><div class="na">⚠<br>{c.get("error","")[:20]}</div></td>')
body_rows.append(f'<tr>{"".join(cells)}</tr>')
html = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>重绘分辨率对比报告 — steps=15</title>
<style>
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
body {{ font-family: -apple-system, "Segoe UI", sans-serif; background: #f5f5f5; padding: 16px; }}
h1 {{ font-size: 20px; margin-bottom: 4px; }}
.subtitle {{ color: #888; font-size: 12px; margin-bottom: 12px; }}
.legend {{ background: #fff; border-radius: 8px; padding: 10px 16px; margin-bottom: 12px; font-size: 12px; color: #555; }}
.scroll-wrap {{ overflow-x: auto; }}
table {{ border-collapse: collapse; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,.06); }}
th, td {{ border: 1px solid #eee; padding: 6px; vertical-align: top; text-align: center; }}
th {{ background: #f9fafb; position: sticky; top: 0; }}
.col-label {{ min-width: 130px; max-width: 150px; }}
.col-title {{ font-size: 12px; font-weight: 700; color: #374151; }}
.col-stat {{ font-size: 10px; color: #9ca3af; margin-top: 2px; }}
.row-label {{ font-size: 11px; color: #6b7280; }}
.row-label b {{ color: #1f2937; }}
img {{ border-radius: 4px; max-width: 130px; max-height: 160px; object-fit: contain; background: #f3f4f6; }}
.cell-time {{ font-size: 10px; color: #9ca3af; margin-top: 2px; }}
.na {{ color: #d1d5db; font-size: 12px; padding: 40px 10px; }}
</style>
</head>
<body>
<h1>📊 重绘分辨率对比报告</h1>
<p class="subtitle">4图×5发型=20行 · 每行4分辨率(原图不缩放/896/768/640) · steps=15 · 热数据 · 80/80成功 · 峰值21.2GB · 0 OOM</p>
<div class="legend">列标题下显示<b>平均总耗时</b>。横向滚动查看。原图列含图片名+发型名。每格下方为该次总耗时。</div>
<div class="scroll-wrap">
<table>
<tr>{"".join(headers)}</tr>
{"".join(body_rows)}
</table>
</div>
</body>
</html>"""
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()