#!/usr/bin/env python3 # -*- coding: utf-8 -*- """分辨率对比测试(新提示词版):4图×5发型=20行,每行4种分辨率,steps=15。 提示词固定为 "填充遮罩区域的头发,皮肤加一点磨皮"(去掉了"再加一点美颜")。 热数据:预热1次+正式1次。 """ import base64 import json import os import time from pathlib import Path import requests API = "http://127.0.0.1:8187/api/v1/debug/grow-timing" TOKEN = "dev-shared-secret-2026" PROMPT = "填充遮罩区域的头发,皮肤加一点磨皮" OUT = Path("/home/ubuntu/hair/benchmark_out/bench4") OUT.mkdir(parents=True, exist_ok=True) IMGS = [ ("asdf", "/home/ubuntu/hair/image/asdf.jpg"), ("qwer", "/home/ubuntu/hair/image/qwer.jpg"), ("girl2", "/home/ubuntu/hair/image/girl_img/girl2.jpg"), ("girl5", "/home/ubuntu/hair/image/girl_img/girl5.jpg"), ] HAIRSTYLES = [ (1, "ellipse", "椭圆"), (2, "flower", "花瓣"), (3, "heart", "心形"), (4, "straight", "直线"), (5, "wave", "波浪"), ] RES_LIST = [("orig", "0"), ("896", "896"), ("768", "768"), ("640", "640")] RES_TITLES = ["原图(不缩放)", "896", "768", "640"] STEPS = 15 def call(img_path, hair_num, redraw_max_side, save_grown=None, timeout=300): data = {"hair_style": str(hair_num), "webui_steps": str(STEPS), "redraw_max_side": str(redraw_max_side), "redraw_prompt": PROMPT} t0 = time.perf_counter() try: with open(img_path, "rb") as f: r = requests.post(API, headers={"X-Internal-Token": TOKEN}, files={"image_file": (os.path.basename(img_path), f, "image/jpeg")}, data=data, timeout=timeout) wall = time.perf_counter() - t0 j = r.json() if j.get("code") != 0: return {"ok": False, "error": j.get("message", "")[:80], "wall": wall} d = j["data"] hs = d["per_hairstyle"][0] if save_grown and hs.get("grown_b64"): b = hs["grown_b64"].split(",")[1] if "," in hs["grown_b64"] else hs["grown_b64"] with open(save_grown, "wb") as gf: gf.write(base64.b64decode(b)) return { "ok": hs.get("ok", False), "wall": wall, "total_ms": d["total_ms"], "swap_ms": hs.get("swap_ms"), "comfy_ms": hs.get("comfyui_redraw_ms"), "error": hs.get("error"), } except Exception as e: return {"ok": False, "error": str(e)[:80], "wall": time.perf_counter() - t0} def main(): rows = [] total = len(IMGS) * len(HAIRSTYLES) * len(RES_LIST) * 2 idx = 0 for ilabel, ipath in IMGS: for hnum, hkey, hname in HAIRSTYLES: cells = [] for (rlabel, rval), rtitle in zip(RES_LIST, RES_TITLES): idx += 1 print(f"[{idx}/{total}] 预热 {ilabel}|{hname}|{rtitle}", flush=True) try: call(ipath, hnum, rval, timeout=120) except Exception: pass idx += 1 save = OUT / f"{ilabel}_{hkey}_{rlabel}.jpg" print(f"[{idx}/{total}] 正式 {ilabel}|{hname}|{rtitle}", flush=True) r = call(ipath, hnum, rval, save_grown=save, timeout=300) r["res_label"] = rlabel; r["res_title"] = rtitle r["grown_path"] = str(save) if r.get("ok") else None status = f"{r.get('total_ms')}ms" if r.get("ok") else f"FAIL:{r.get('error','')[:30]}" print(f" -> {status}", flush=True) cells.append(r) rows.append({"img": ilabel, "img_path": ipath, "hair_num": hnum, "hair_key": hkey, "hair_name": hname, "cells": cells}) with open(OUT / "results.json", "w", encoding="utf-8") as f: json.dump({"res_titles": RES_TITLES, "prompt": PROMPT, "rows": rows}, f, ensure_ascii=False, indent=2) ok = sum(1 for row in rows for c in row["cells"] if c.get("ok")) print(f"\n✓ 完成: {ok}/{len(rows)*len(RES_LIST)} 成功 -> {OUT/'results.json'}", flush=True) if __name__ == "__main__": main()