refactor(报告): 图片改为独立JPG文件引用,不再base64内嵌
- 测试结果图(258张)和原图(3张)以JPG存入 static/bench/{matrix,hairstyle,orig}/
- 报告HTML改为 <img src> 引用相对路径,体积从 ~45MB 降至 ~30KB
- 报告和图片均部署在 static/ 下,可通过URL直接访问
@@ -14,19 +14,16 @@ RESULTS = OUT / "results.json"
|
|||||||
HTML = OUT / "report.html"
|
HTML = OUT / "report.html"
|
||||||
|
|
||||||
|
|
||||||
def img_b64(path, max_w=300, quality=70):
|
def img_src(path):
|
||||||
"""读图片,缩放到 max_w 宽、JPEG 降质后转 base64 data URI(压缩体积便于入 git)。"""
|
"""把绝对路径转成报告里的相对 URL(报告在 static/,图片在 static/bench/)。"""
|
||||||
if not path or not os.path.isfile(path):
|
if not path:
|
||||||
return None
|
return None
|
||||||
from io import BytesIO
|
p = str(path)
|
||||||
from PIL import Image
|
if "benchmark_out/hairstyle/" in p:
|
||||||
im = Image.open(path).convert("RGB")
|
return "bench/hairstyle/" + os.path.basename(p)
|
||||||
if im.width > max_w:
|
if "benchmark_out/matrix/" in p:
|
||||||
nh = round(im.height * max_w / im.width)
|
return "bench/matrix/" + os.path.basename(p)
|
||||||
im = im.resize((max_w, nh), Image.LANCZOS)
|
return None
|
||||||
buf = BytesIO()
|
|
||||||
im.save(buf, format="JPEG", quality=quality, optimize=True)
|
|
||||||
return f"data:image/jpeg;base64,{base64.b64encode(buf.getvalue()).decode()}"
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -63,16 +60,17 @@ def main():
|
|||||||
# 发型+图标签
|
# 发型+图标签
|
||||||
label = f'<div class="row-label">{r["img"]}<br><b>{r["hair_name"]}</b></div>'
|
label = f'<div class="row-label">{r["img"]}<br><b>{r["hair_name"]}</b></div>'
|
||||||
# 原图
|
# 原图
|
||||||
orig = img_b64(r["img_path"])
|
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'<td class="cell-orig"><div class="row-label-cell">{label}</div>'
|
cells = [f'<td class="cell-orig"><div class="row-label-cell">{label}</div>'
|
||||||
f'<img class="orig-img" src="{orig}"></td>']
|
f'<img class="orig-img" src="{orig}"></td>']
|
||||||
# 10个结果列
|
# 10个结果列
|
||||||
for ct in columns:
|
for ct in columns:
|
||||||
c = next((x for x in r["cells"] if x.get("title") == ct), {})
|
c = next((x for x in r["cells"] if x.get("title") == ct), {})
|
||||||
uri = img_b64(c.get("grown_path")) if not c.get("error") else None
|
src = img_src(c.get("grown_path")) if not c.get("error") else None
|
||||||
if uri:
|
if src:
|
||||||
cells.append(
|
cells.append(
|
||||||
f'<td class="cell-result"><img class="result-img" src="{uri}" loading="lazy">'
|
f'<td class="cell-result"><img class="result-img" src="{src}" loading="lazy">'
|
||||||
f'<div class="cell-time">{c["elapsed"]:.1f}s</div></td>')
|
f'<div class="cell-time">{c["elapsed"]:.1f}s</div></td>')
|
||||||
else:
|
else:
|
||||||
cells.append(f'<td class="cell-result"><div class="na">⚠</div></td>')
|
cells.append(f'<td class="cell-result"><div class="na">⚠</div></td>')
|
||||||
|
|||||||
@@ -23,36 +23,29 @@ MODEL_LABEL = {
|
|||||||
MODEL_ORDER = ["4b-fp8", "9b-Q4", "9b-Q5", "9b-fp8"]
|
MODEL_ORDER = ["4b-fp8", "9b-Q4", "9b-Q5", "9b-fp8"]
|
||||||
|
|
||||||
|
|
||||||
def img_b64(path, max_w=320, quality=72):
|
def img_src(path):
|
||||||
"""读图片,缩放到 max_w 宽、JPEG 降质后转 base64 data URI(压缩体积便于入 git)。"""
|
"""把绝对路径转成报告里的相对 URL(报告在 static/,图片在 static/bench/)。"""
|
||||||
if not path or not os.path.isfile(path):
|
if not path:
|
||||||
return None
|
return None
|
||||||
from io import BytesIO
|
p = str(path)
|
||||||
from PIL import Image
|
# benchmark_out/matrix/xxx.jpg -> bench/matrix/xxx.jpg
|
||||||
im = Image.open(path).convert("RGB")
|
if "benchmark_out/matrix/" in p:
|
||||||
if im.width > max_w:
|
return "bench/matrix/" + os.path.basename(p)
|
||||||
nh = round(im.height * max_w / im.width)
|
if "benchmark_out/hairstyle/" in p:
|
||||||
im = im.resize((max_w, nh), Image.LANCZOS)
|
return "bench/hairstyle/" + os.path.basename(p)
|
||||||
buf = BytesIO()
|
return None
|
||||||
im.save(buf, format="JPEG", quality=quality, optimize=True)
|
|
||||||
b = base64.b64encode(buf.getvalue()).decode()
|
|
||||||
return f"data:image/jpeg;base64,{b}"
|
|
||||||
|
|
||||||
|
|
||||||
def thumb(data_uri, alt="", cls=""):
|
def thumb(src, alt="", cls=""):
|
||||||
if not data_uri:
|
if not src:
|
||||||
return f'<div class="na {cls}">⚠ 失败</div>'
|
return f'<div class="na {cls}">⚠ 失败</div>'
|
||||||
return f'<img class="{cls}" src="{data_uri}" alt="{alt}" loading="lazy">'
|
return f'<img class="{cls}" src="{src}" alt="{alt}" loading="lazy">'
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
data = json.load(open(RESULTS, encoding="utf-8"))
|
data = json.load(open(RESULTS, encoding="utf-8"))
|
||||||
# 预读原图 base64(3 张图)
|
# 原图相对路径映射(图片在 static/bench/orig/)
|
||||||
orig_b64 = {}
|
ORIG_SRC = {"asdf": "bench/orig/asdf.jpg", "qwer": "bench/orig/qwer.jpg", "girl5": "bench/orig/girl5.jpg"}
|
||||||
for c in data:
|
|
||||||
ip = c["img_path"]
|
|
||||||
if c["img"] not in orig_b64:
|
|
||||||
orig_b64[c["img"]] = img_b64(ip, 200)
|
|
||||||
|
|
||||||
# 统计:每个模型的平均耗时、平均峰值显存
|
# 统计:每个模型的平均耗时、平均峰值显存
|
||||||
stats = {}
|
stats = {}
|
||||||
@@ -76,11 +69,11 @@ def main():
|
|||||||
# 3 次结果图
|
# 3 次结果图
|
||||||
run_cells = []
|
run_cells = []
|
||||||
for i, r in enumerate(c["runs"]):
|
for i, r in enumerate(c["runs"]):
|
||||||
uri = img_b64(r["grown_path"]) if not r["error"] else None
|
src = img_src(r["grown_path"]) if not r["error"] else None
|
||||||
if uri:
|
if src:
|
||||||
run_cells.append(
|
run_cells.append(
|
||||||
f'<div class="run-cell"><div class="run-label">第{i+1}次 · {r["elapsed"]:.1f}s</div>'
|
f'<div class="run-cell"><div class="run-label">第{i+1}次 · {r["elapsed"]:.1f}s</div>'
|
||||||
f'{thumb(uri, f"r{i+1}", "result-img")}</div>'
|
f'{thumb(src, f"r{i+1}", "result-img")}</div>'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
run_cells.append(
|
run_cells.append(
|
||||||
@@ -88,7 +81,7 @@ def main():
|
|||||||
f'<div class="na">⚠ {r["error"][:30] if r["error"] else ""}</div></div>'
|
f'<div class="na">⚠ {r["error"][:30] if r["error"] else ""}</div></div>'
|
||||||
)
|
)
|
||||||
|
|
||||||
orig = orig_b64.get(c["img"])
|
orig = ORIG_SRC.get(c["img"])
|
||||||
rows_html.append(f'''
|
rows_html.append(f'''
|
||||||
<div class="combo-row">
|
<div class="combo-row">
|
||||||
<div class="cell-model">{MODEL_LABEL.get(m, m)}<div class="cell-sub">res={RES_LABEL.get(rlabel, rlabel)}</div></div>
|
<div class="cell-model">{MODEL_LABEL.get(m, m)}<div class="cell-sub">res={RES_LABEL.get(rlabel, rlabel)}</div></div>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 235 KiB |
|
After Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 296 KiB |
|
After Width: | Height: | Size: 334 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 277 KiB |
|
After Width: | Height: | Size: 309 KiB |
|
After Width: | Height: | Size: 233 KiB |
|
After Width: | Height: | Size: 271 KiB |
|
After Width: | Height: | Size: 286 KiB |
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 235 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 306 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 287 KiB |
|
After Width: | Height: | Size: 209 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 233 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 274 KiB |
|
After Width: | Height: | Size: 277 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 300 KiB |
|
After Width: | Height: | Size: 303 KiB |
|
After Width: | Height: | Size: 243 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 275 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 291 KiB |
|
After Width: | Height: | Size: 278 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 285 KiB |
|
After Width: | Height: | Size: 335 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 263 KiB |
|
After Width: | Height: | Size: 300 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 292 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 94 KiB |