Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f509fe99b4 | ||
|
|
a1d458eb20 | ||
|
|
92e628b0d5 | ||
|
|
b4714cedf3 | ||
|
|
e7b62f2b2e | ||
|
|
4291f125d4 | ||
|
|
7fc0210ce6 | ||
|
|
085ad3ced0 | ||
|
|
2993a0b948 | ||
|
|
08b31a3baa | ||
|
|
51e313e845 | ||
|
|
fbbcd48418 | ||
|
|
74ccab0ff8 |
@@ -53,32 +53,3 @@ static/report_hairline_v2.zip
|
||||
# local_test 运行期日志 / pid(不入 git)
|
||||
local_test/hair_service.log
|
||||
local_test/hair_service.pid
|
||||
|
||||
# benchmark 原始输出(含结果图+原图,体积大,不入 git)
|
||||
benchmark_out/
|
||||
|
||||
# benchmark 部署的 HTML 报告(图片 base64 内嵌,体积大,不入 git)
|
||||
static/hairstyle_thumbs/
|
||||
|
||||
# 网关运行期日志(不入 git)
|
||||
gateway.log
|
||||
|
||||
# 工作流备份文件(不入 git)
|
||||
*.json.bak.*
|
||||
|
||||
# 脸型测试素材(人像照片,体积大,不入 git;仅保留 6 张基准标注图)
|
||||
face/test_img/脸型测试集合/
|
||||
face/test_img/girl/
|
||||
face/test_img/man/
|
||||
|
||||
# 脸型特征缓存(由 face/dump_features.py 生成,可随时重跑)
|
||||
face/cache/
|
||||
|
||||
# 脸型报告输出(标注图体积大,不入 git)
|
||||
static/face_shape_report/
|
||||
static/face_shape_report.html
|
||||
static/facetest_report/
|
||||
static/facetest_report.html
|
||||
static/facetest_all_report/
|
||||
static/facetest_all_report.html
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"60": {
|
||||
"class_type": "JjkText",
|
||||
"inputs": {
|
||||
"text": "填充遮罩区域的头发"
|
||||
"text": "填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜"
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
{
|
||||
"16": {"class_type": "UNETLoader", "inputs": {
|
||||
"unet_name": "flux2.0/flux-2-klein-9b-fp8.safetensors",
|
||||
"weight_dtype": "fp8_e4m3fn_fast"}},
|
||||
"3": {"class_type": "VAELoader", "inputs": {
|
||||
"vae_name": "flux2-vae.safetensors"}},
|
||||
"61": {"class_type": "CLIPLoader", "inputs": {
|
||||
"clip_name": "qwen_3_8b_fp8mixed.safetensors",
|
||||
"type": "flux2",
|
||||
"device": "default"}},
|
||||
|
||||
"26": {"class_type": "LoadImage", "inputs": {
|
||||
"image": "placeholder.png"}},
|
||||
|
||||
"60": {"class_type": "JjkText", "inputs": {
|
||||
"text": "填充遮罩区域的头发,皮肤加一点磨皮"}},
|
||||
"22": {"class_type": "CLIPTextEncode", "inputs": {
|
||||
"clip": ["61", 0],
|
||||
"text": ["60", 0]}},
|
||||
|
||||
"31": {"class_type": "easy imageSize", "inputs": {
|
||||
"image": ["26", 0]}},
|
||||
|
||||
"33": {"class_type": "Mask Fill Holes", "inputs": {
|
||||
"masks": ["26", 1]}},
|
||||
"36": {"class_type": "Convert Masks to Images", "inputs": {
|
||||
"masks": ["33", 0]}},
|
||||
"39": {"class_type": "ImageScale", "inputs": {
|
||||
"image": ["36", 0],
|
||||
"upscale_method": "nearest-exact",
|
||||
"width": ["31", 0],
|
||||
"height": ["31", 1],
|
||||
"crop": "disabled"}},
|
||||
"37": {"class_type": "Image To Mask", "inputs": {
|
||||
"image": ["39", 0],
|
||||
"method": "intensity"}},
|
||||
|
||||
"32": {"class_type": "LayerUtility: ImageScaleByAspectRatio V2", "inputs": {
|
||||
"image": ["26", 0],
|
||||
"mask": ["37", 0],
|
||||
"aspect_ratio": "custom",
|
||||
"proportional_width": ["31", 0],
|
||||
"proportional_height": ["31", 1],
|
||||
"fit": "letterbox",
|
||||
"method": "lanczos",
|
||||
"round_to_multiple": "8",
|
||||
"scale_to_side": "None",
|
||||
"scale_to_length": 1024,
|
||||
"background_color": "#000000"}},
|
||||
|
||||
"44": {"class_type": "ImageAndMaskPreview", "inputs": {
|
||||
"image": ["32", 0],
|
||||
"mask": ["32", 1],
|
||||
"mask_opacity": 1,
|
||||
"mask_color": "FFFF00",
|
||||
"pass_through": true}},
|
||||
|
||||
"14": {"class_type": "GetImageSize+", "inputs": {
|
||||
"image": ["44", 0]}},
|
||||
|
||||
"13": {"class_type": "VAEEncode", "inputs": {
|
||||
"pixels": ["44", 0],
|
||||
"vae": ["3", 0]}},
|
||||
|
||||
"2": {"class_type": "ModelSamplingFlux", "inputs": {
|
||||
"model": ["16", 0],
|
||||
"max_shift": 1.15,
|
||||
"base_shift": 0.5,
|
||||
"width": ["14", 0],
|
||||
"height": ["14", 1]}},
|
||||
"19": {"class_type": "FluxGuidance", "inputs": {
|
||||
"conditioning": ["22", 0],
|
||||
"guidance": 1}},
|
||||
"5": {"class_type": "ReferenceLatent", "inputs": {
|
||||
"conditioning": ["19", 0],
|
||||
"latent": ["13", 0]}},
|
||||
|
||||
"7": {"class_type": "EmptySD3LatentImage", "inputs": {
|
||||
"width": ["14", 0],
|
||||
"height": ["14", 1],
|
||||
"batch_size": 1}},
|
||||
|
||||
"1": {"class_type": "BasicScheduler", "inputs": {
|
||||
"model": ["2", 0],
|
||||
"scheduler": "simple",
|
||||
"steps": 4,
|
||||
"denoise": 1}},
|
||||
"20": {"class_type": "BasicGuider", "inputs": {
|
||||
"model": ["2", 0],
|
||||
"conditioning": ["5", 0]}},
|
||||
|
||||
"6": {"class_type": "RandomNoise", "inputs": {
|
||||
"noise_seed": 0}},
|
||||
"8": {"class_type": "KSamplerSelect", "inputs": {
|
||||
"sampler_name": "euler"}},
|
||||
"9": {"class_type": "SamplerCustomAdvanced", "inputs": {
|
||||
"noise": ["6", 0],
|
||||
"guider": ["20", 0],
|
||||
"sampler": ["8", 0],
|
||||
"sigmas": ["1", 0],
|
||||
"latent_image": ["7", 0]}},
|
||||
|
||||
"10": {"class_type": "VAEDecode", "inputs": {
|
||||
"samples": ["9", 0],
|
||||
"vae": ["3", 0]}},
|
||||
|
||||
"62": {"class_type": "ColorMatch", "inputs": {
|
||||
"image_ref": ["26", 0],
|
||||
"image_target": ["10", 0],
|
||||
"method": "mkl",
|
||||
"strength": 1,
|
||||
"multithread": true}},
|
||||
|
||||
"17": {"class_type": "SaveImage", "inputs": {
|
||||
"images": ["62", 0],
|
||||
"filename_prefix": "hair_inpaint"}}
|
||||
}
|
||||
@@ -82,8 +82,7 @@ model.safetensors https://huggingface.co/jonathandinu/face-parsing/resol
|
||||
模型已就位,但**内网机还需要 Python 依赖的离线 wheel 包**,否则 `pip install` 在内网无法联网安装。这部分**与目标机的操作系统、Python 版本、CUDA 版本强相关**,需确认后单独打包:
|
||||
|
||||
- **worker(GPU 机)**:`mediapipe` / `opencv-python` / `numpy<2` / `Pillow` / **`torch`+`torchvision` 的 CUDA 版**(按 GPU 的 CUDA 版本选 cu118/cu121 等)/ `transformers`(接口2 SegFormer)+ FastAPI/uvicorn 全家桶。
|
||||
- **网关机**:FastAPI/uvicorn/httpx 等代理依赖 + **接口4 现需 `mediapipe`/`opencv-python`/`numpy<2`**(脸型本机计算),
|
||||
仍**不需要 torch**(无 GPU 推理需求)。
|
||||
- **网关机**:很轻,只需 FastAPI/uvicorn/httpx 等代理依赖,**不需要 torch/mediapipe**。
|
||||
|
||||
> 架构已拆分(见 `docs/实现说明.md`):算法依赖只装在 worker,网关保持轻量。
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
"16": {
|
||||
"inputs": {
|
||||
"unet_name": "flux-2-klein-4b-fp8.safetensors",
|
||||
"weight_dtype": "fp8_e4m3fn"
|
||||
"weight_dtype": "fp8_e4m3fn_fast"
|
||||
},
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
@@ -410,7 +410,7 @@
|
||||
},
|
||||
"60": {
|
||||
"inputs": {
|
||||
"text": "填充遮罩区域的头发"
|
||||
"text": "填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜"
|
||||
},
|
||||
"class_type": "JjkText",
|
||||
"_meta": {
|
||||
@@ -447,4 +447,4 @@
|
||||
"title": "Color Match"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,450 +0,0 @@
|
||||
{
|
||||
"1": {
|
||||
"inputs": {
|
||||
"scheduler": "simple",
|
||||
"steps": 6,
|
||||
"denoise": 1,
|
||||
"model": [
|
||||
"2",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicScheduler",
|
||||
"_meta": {
|
||||
"title": "基本调度器"
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"inputs": {
|
||||
"max_shift": 1.15,
|
||||
"base_shift": 0.5,
|
||||
"width": [
|
||||
"14",
|
||||
0
|
||||
],
|
||||
"height": [
|
||||
"14",
|
||||
1
|
||||
],
|
||||
"model": [
|
||||
"16",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ModelSamplingFlux",
|
||||
"_meta": {
|
||||
"title": "采样算法(Flux)"
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"inputs": {
|
||||
"vae_name": "flux2-vae.safetensors"
|
||||
},
|
||||
"class_type": "VAELoader",
|
||||
"_meta": {
|
||||
"title": "加载VAE"
|
||||
}
|
||||
},
|
||||
"5": {
|
||||
"inputs": {
|
||||
"conditioning": [
|
||||
"19",
|
||||
0
|
||||
],
|
||||
"latent": [
|
||||
"13",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ReferenceLatent",
|
||||
"_meta": {
|
||||
"title": "参考Latent"
|
||||
}
|
||||
},
|
||||
"6": {
|
||||
"inputs": {
|
||||
"noise_seed": 217742615722421
|
||||
},
|
||||
"class_type": "RandomNoise",
|
||||
"_meta": {
|
||||
"title": "随机噪波"
|
||||
}
|
||||
},
|
||||
"7": {
|
||||
"inputs": {
|
||||
"width": [
|
||||
"14",
|
||||
0
|
||||
],
|
||||
"height": [
|
||||
"14",
|
||||
1
|
||||
],
|
||||
"batch_size": 1
|
||||
},
|
||||
"class_type": "EmptySD3LatentImage",
|
||||
"_meta": {
|
||||
"title": "空Latent图像(SD3)"
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"sampler_name": "euler"
|
||||
},
|
||||
"class_type": "KSamplerSelect",
|
||||
"_meta": {
|
||||
"title": "K采样器选择"
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"noise": [
|
||||
"6",
|
||||
0
|
||||
],
|
||||
"guider": [
|
||||
"20",
|
||||
0
|
||||
],
|
||||
"sampler": [
|
||||
"8",
|
||||
0
|
||||
],
|
||||
"sigmas": [
|
||||
"1",
|
||||
0
|
||||
],
|
||||
"latent_image": [
|
||||
"7",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SamplerCustomAdvanced",
|
||||
"_meta": {
|
||||
"title": "自定义采样器(高级)"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"inputs": {
|
||||
"samples": [
|
||||
"9",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"3",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "VAEDecode",
|
||||
"_meta": {
|
||||
"title": "VAE解码"
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"inputs": {
|
||||
"pixels": [
|
||||
"44",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"3",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "VAEEncode",
|
||||
"_meta": {
|
||||
"title": "VAE编码"
|
||||
}
|
||||
},
|
||||
"14": {
|
||||
"inputs": {
|
||||
"image": [
|
||||
"44",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "GetImageSize+",
|
||||
"_meta": {
|
||||
"title": "🔧 Get Image Size"
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"inputs": {
|
||||
"unet_name": "flux2.0/flux-2-klein-9b-fp8.safetensors",
|
||||
"weight_dtype": "fp8_e4m3fn"
|
||||
},
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "UNet加载器"
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"inputs": {
|
||||
"filename_prefix": "ComfyUI",
|
||||
"images": [
|
||||
"62",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SaveImage",
|
||||
"_meta": {
|
||||
"title": "保存图像"
|
||||
}
|
||||
},
|
||||
"19": {
|
||||
"inputs": {
|
||||
"guidance": 1,
|
||||
"conditioning": [
|
||||
"22",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "FluxGuidance",
|
||||
"_meta": {
|
||||
"title": "Flux引导"
|
||||
}
|
||||
},
|
||||
"20": {
|
||||
"inputs": {
|
||||
"model": [
|
||||
"2",
|
||||
0
|
||||
],
|
||||
"conditioning": [
|
||||
"5",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicGuider",
|
||||
"_meta": {
|
||||
"title": "基本引导器"
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"inputs": {
|
||||
"text": [
|
||||
"60",
|
||||
0
|
||||
],
|
||||
"clip": [
|
||||
"61",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "CLIP文本编码"
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"inputs": {
|
||||
"image": "clipspace/clipspace-painted-masked-1781655058499.png [input]"
|
||||
},
|
||||
"class_type": "LoadImage",
|
||||
"_meta": {
|
||||
"title": "加载图像"
|
||||
}
|
||||
},
|
||||
"31": {
|
||||
"inputs": {
|
||||
"image": [
|
||||
"26",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "easy imageSize",
|
||||
"_meta": {
|
||||
"title": "图像尺寸"
|
||||
}
|
||||
},
|
||||
"32": {
|
||||
"inputs": {
|
||||
"aspect_ratio": "custom",
|
||||
"proportional_width": [
|
||||
"31",
|
||||
0
|
||||
],
|
||||
"proportional_height": [
|
||||
"31",
|
||||
1
|
||||
],
|
||||
"fit": "letterbox",
|
||||
"method": "lanczos",
|
||||
"round_to_multiple": "8",
|
||||
"scale_to_side": "None",
|
||||
"scale_to_length": 1024,
|
||||
"background_color": "#000000",
|
||||
"image": [
|
||||
"26",
|
||||
0
|
||||
],
|
||||
"mask": [
|
||||
"37",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LayerUtility: ImageScaleByAspectRatio V2",
|
||||
"_meta": {
|
||||
"title": "LayerUtility: ImageScaleByAspectRatio V2"
|
||||
}
|
||||
},
|
||||
"33": {
|
||||
"inputs": {
|
||||
"masks": [
|
||||
"26",
|
||||
1
|
||||
]
|
||||
},
|
||||
"class_type": "Mask Fill Holes",
|
||||
"_meta": {
|
||||
"title": "Mask Fill Holes"
|
||||
}
|
||||
},
|
||||
"36": {
|
||||
"inputs": {
|
||||
"masks": [
|
||||
"33",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "Convert Masks to Images",
|
||||
"_meta": {
|
||||
"title": "Convert Masks to Images"
|
||||
}
|
||||
},
|
||||
"37": {
|
||||
"inputs": {
|
||||
"method": "intensity",
|
||||
"image": [
|
||||
"39",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "Image To Mask",
|
||||
"_meta": {
|
||||
"title": "Image To Mask"
|
||||
}
|
||||
},
|
||||
"39": {
|
||||
"inputs": {
|
||||
"upscale_method": "nearest-exact",
|
||||
"width": [
|
||||
"31",
|
||||
0
|
||||
],
|
||||
"height": [
|
||||
"31",
|
||||
1
|
||||
],
|
||||
"crop": "disabled",
|
||||
"image": [
|
||||
"36",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ImageScale",
|
||||
"_meta": {
|
||||
"title": "缩放图像"
|
||||
}
|
||||
},
|
||||
"44": {
|
||||
"inputs": {
|
||||
"mask_opacity": 1,
|
||||
"mask_color": "FFFF00",
|
||||
"pass_through": true,
|
||||
"image": [
|
||||
"32",
|
||||
0
|
||||
],
|
||||
"mask": [
|
||||
"32",
|
||||
1
|
||||
]
|
||||
},
|
||||
"class_type": "ImageAndMaskPreview",
|
||||
"_meta": {
|
||||
"title": "ImageAndMaskPreview"
|
||||
}
|
||||
},
|
||||
"45": {
|
||||
"inputs": {
|
||||
"images": [
|
||||
"44",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "PreviewImage",
|
||||
"_meta": {
|
||||
"title": "预览图像"
|
||||
}
|
||||
},
|
||||
"53": {
|
||||
"inputs": {
|
||||
"rgthree_comparer": {
|
||||
"images": [
|
||||
{
|
||||
"name": "A",
|
||||
"selected": true,
|
||||
"url": "/api/view?filename=rgthree.compare._temp_zuixa_00119_.png&type=temp&subfolder=&rand=0.7926013627811991"
|
||||
},
|
||||
{
|
||||
"name": "B",
|
||||
"selected": true,
|
||||
"url": "/api/view?filename=rgthree.compare._temp_zuixa_00120_.png&type=temp&subfolder=&rand=0.43692946883795813"
|
||||
}
|
||||
]
|
||||
},
|
||||
"image_a": [
|
||||
"62",
|
||||
0
|
||||
],
|
||||
"image_b": [
|
||||
"26",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "Image Comparer (rgthree)",
|
||||
"_meta": {
|
||||
"title": "Image Comparer (rgthree)"
|
||||
}
|
||||
},
|
||||
"60": {
|
||||
"inputs": {
|
||||
"text": "补充遮罩区补充遮罩区域内的头发,头发填满遮罩区域。发际线往下挡住额头"
|
||||
},
|
||||
"class_type": "JjkText",
|
||||
"_meta": {
|
||||
"title": "Text"
|
||||
}
|
||||
},
|
||||
"61": {
|
||||
"inputs": {
|
||||
"clip_name": "qwen_3_8b_fp8mixed.safetensors",
|
||||
"type": "flux2",
|
||||
"device": "default"
|
||||
},
|
||||
"class_type": "CLIPLoader",
|
||||
"_meta": {
|
||||
"title": "加载CLIP"
|
||||
}
|
||||
},
|
||||
"62": {
|
||||
"inputs": {
|
||||
"method": "mkl",
|
||||
"strength": 1,
|
||||
"multithread": true,
|
||||
"image_ref": [
|
||||
"26",
|
||||
0
|
||||
],
|
||||
"image_target": [
|
||||
"10",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ColorMatch",
|
||||
"_meta": {
|
||||
"title": "Color Match"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,7 +381,7 @@
|
||||
},
|
||||
"60": {
|
||||
"inputs": {
|
||||
"text": "填充遮罩区域的头发"
|
||||
"text": "补充遮罩内区域的头发,区域内填充满头发,不要保留皮肤,发际线下移填充头发。自然的头发生长方向,逼真的头发质感,自然发质。"
|
||||
},
|
||||
"class_type": "JjkText",
|
||||
"_meta": {
|
||||
@@ -684,7 +684,7 @@
|
||||
},
|
||||
"87": {
|
||||
"inputs": {
|
||||
"text": "填充遮罩区域的头发",
|
||||
"text": "去掉头发接缝的黄色痕迹,头发完美融合,保持发型不变,发色不变。其他不变。",
|
||||
"clip": [
|
||||
"78",
|
||||
0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""旷视五接口 — worker 侧(高性能 GPU 后端)。
|
||||
|
||||
接口 1 等算法在 worker;接口4(用户特征)已迁到网关本机(调豆包),worker 同路径只返回明确错误、无 Mock。
|
||||
接口 1(四庭七眼测量)已为**真实算法实现**(见 face_analysis 包);接口 2~5 仍为 Mock。
|
||||
拆分架构:worker 跑算法、返回 `annotated_image_base64`(不落盘、不拼 URL,由网关完成)。
|
||||
worker 对 `/api/*` 校验内网鉴权头 `X-Internal-Token`,`/health` 供网关探测不校验。
|
||||
"""
|
||||
@@ -139,7 +139,46 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
|
||||
# 不校验鉴权的路径前缀(供网关探测 / 文档 / 静态)
|
||||
_AUTH_EXEMPT = ("/health", "/docs", "/openapi.json", "/redoc", "/static",
|
||||
"/api/v1/debug", "/api/v1/redraw")
|
||||
"/api/v1/debug", "/api/v1/redraw",
|
||||
"/api/swapHair", "/hairColor")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# change_hair 代理路由(解决 CORS 问题)
|
||||
# ---------------------------------------------------------------------------
|
||||
_CHANGE_HAIR_BASE = "http://127.0.0.1:8801"
|
||||
|
||||
|
||||
@app.post("/api/swapHair/v1", tags=["change_hair"])
|
||||
async def proxy_swap_hair(request: Request):
|
||||
"""代理转发到 change_hair /api/swapHair/v1(换发型)"""
|
||||
try:
|
||||
import httpx
|
||||
body = await request.body()
|
||||
async with httpx.AsyncClient(timeout=300.0) as client:
|
||||
resp = await client.post(f"{_CHANGE_HAIR_BASE}/api/swapHair/v1",
|
||||
content=body,
|
||||
headers={"Content-Type": "application/json"})
|
||||
return JSONResponse(content=resp.json(), status_code=resp.status_code)
|
||||
except Exception as e:
|
||||
logger.exception("代理 swapHair 失败")
|
||||
return err(1007, f"换发型服务异常:{e}")
|
||||
|
||||
|
||||
@app.post("/hairColor/v2", tags=["change_hair"])
|
||||
async def proxy_hair_color(request: Request):
|
||||
"""代理转发到 change_hair /hairColor/v2(换发色)"""
|
||||
try:
|
||||
import httpx
|
||||
body = await request.body()
|
||||
async with httpx.AsyncClient(timeout=300.0) as client:
|
||||
resp = await client.post(f"{_CHANGE_HAIR_BASE}/hairColor/v2",
|
||||
content=body,
|
||||
headers={"Content-Type": "application/json"})
|
||||
return JSONResponse(content=resp.json(), status_code=resp.status_code)
|
||||
except Exception as e:
|
||||
logger.exception("代理 hairColor 失败")
|
||||
return err(1007, f"换发色服务异常:{e}")
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
@@ -362,36 +401,21 @@ def _run_face_measure_data(image, variant="v1"):
|
||||
logger.warning("头发/耳朵分割失败,回退方案A:%s", seg_e)
|
||||
|
||||
result = measure_face(landmarks, hair_mask, w, h, head_pose=head_pose)
|
||||
discarded = result.hairline_discarded
|
||||
data = result.to_response()
|
||||
vd = result.vertical
|
||||
if variant == "v6":
|
||||
if discarded:
|
||||
# 发际线弃用:接口6 的上庭也依赖发际线,一并置 null;只保留中/下庭。
|
||||
base_px = vd["middle_court_px"] + vd["lower_court_px"]
|
||||
data["four_courts"]["upper_court_cm"] = None
|
||||
data["four_courts"]["ratios"] = {
|
||||
"upper_court": None,
|
||||
"middle_court": round(vd["middle_court_px"] / base_px, 3),
|
||||
"lower_court": round(vd["lower_court_px"] / base_px, 3),
|
||||
}
|
||||
data["four_courts"].pop("top_court_cm", None)
|
||||
data["face_total_height_cm"] = round(
|
||||
result.middle_cm + result.lower_cm, 2)
|
||||
data["landmarks"]["hairline"] = None
|
||||
else:
|
||||
base_px = vd["upper_court_px"] + vd["middle_court_px"] + vd["lower_court_px"]
|
||||
# 接口6 是三庭:去掉顶庭相关字段(top_court_cm / ratios.top_court / landmarks.hair_top)
|
||||
data["four_courts"]["ratios"] = {
|
||||
"upper_court": round(vd["upper_court_px"] / base_px, 3),
|
||||
"middle_court": round(vd["middle_court_px"] / base_px, 3),
|
||||
"lower_court": round(vd["lower_court_px"] / base_px, 3),
|
||||
}
|
||||
data["four_courts"].pop("top_court_cm", None)
|
||||
data["face_total_height_cm"] = round(
|
||||
result.upper_cm + result.middle_cm + result.lower_cm, 2)
|
||||
# 注:landmarks.hair_top 保留返回(供前端/下游定位头顶),但顶庭数值、
|
||||
# 占比、标注图仍按三庭处理,显示效果不变。
|
||||
vd = result.vertical
|
||||
base_px = vd["upper_court_px"] + vd["middle_court_px"] + vd["lower_court_px"]
|
||||
# 接口6 是三庭:去掉顶庭相关字段(top_court_cm / ratios.top_court / landmarks.hair_top)
|
||||
data["four_courts"]["ratios"] = {
|
||||
"upper_court": round(vd["upper_court_px"] / base_px, 3),
|
||||
"middle_court": round(vd["middle_court_px"] / base_px, 3),
|
||||
"lower_court": round(vd["lower_court_px"] / base_px, 3),
|
||||
}
|
||||
data["four_courts"].pop("top_court_cm", None)
|
||||
data["face_total_height_cm"] = round(
|
||||
result.upper_cm + result.middle_cm + result.lower_cm, 2)
|
||||
# 注:landmarks.hair_top 保留返回(供前端/下游定位头顶),但顶庭数值、
|
||||
# 占比、标注图仍按三庭处理,显示效果不变。
|
||||
|
||||
# 七眼段宽度(cm)。eye1=左耳外段 eye2=左脸颊 eye3=左眼 eye4=两眼间距 eye5=右眼 eye6=右脸颊 eye7=右耳外段。
|
||||
# eye2~eye6(5段)只用内部分点,接口1/6 共用;eye1/eye7 需耳朵分割端线,仅接口1 有。
|
||||
@@ -406,14 +430,11 @@ def _run_face_measure_data(image, variant="v1"):
|
||||
data["seven_eyes"][f"eye{i + 2}"] = (
|
||||
None if (a is None or b is None) else round((b - a) / pc, 2))
|
||||
if variant != "v6":
|
||||
# 接口1 额外算 eye1/eye7(左/右耳外段),需耳朵分割端线。
|
||||
# 竖向范围:发际线弃用时用眉心做上界(hair_top 不可靠),否则用头顶。
|
||||
# 接口1 额外算 eye1/eye7(左/右耳外段),需耳朵分割端线
|
||||
from face_analysis.annotation import _ear_edges_from_mask
|
||||
top_y = (vd["brow_center"][1] if discarded
|
||||
else vd["hair_top"][1])
|
||||
head_l, head_r = _ear_edges_from_mask(
|
||||
ear_mask, hair_mask,
|
||||
top_y, vd["chin_tip"][1],
|
||||
result.vertical["hair_top"][1], result.vertical["chin_tip"][1],
|
||||
lcx, rcx, (lcx + rcx) / 2)
|
||||
data["seven_eyes"]["eye1"] = (
|
||||
None if (head_l is None) else round((lcx - head_l) / pc, 2))
|
||||
@@ -488,7 +509,7 @@ async def _face_measure_impl(image_file, image_url, image_base64, variant="v1"):
|
||||
**标注图片 UI 规范**(真实版本生效):
|
||||
- 字体/线条/箭头颜色:`#FFFFFF 100%`,透明底
|
||||
- 字号/线宽/虚线/箭头按图片短边自适应缩放
|
||||
- 四庭数值(名+数值两行,不带 cm)在图片**左侧**呈现,七眼段宽**上下穿插**展示,底部标「单位cm」
|
||||
- 四庭(名 + 数值带cm + 百分比 三行)在图片**左侧**呈现,七眼段宽**上下穿插**展示(数值带cm,下方另起一行标占头宽百分比)
|
||||
- 横线/竖线渐变消失并略超出端点;段宽/庭高用虚线 + 实心三角双箭头标示
|
||||
- 竖线含人头最左/最右端线(取自头发分割轮廓),共 8 线 7 段
|
||||
""",
|
||||
@@ -593,7 +614,7 @@ async def face_measure(
|
||||
**标注图片 UI 规范**(真实版本生效):
|
||||
- 字体/线条/箭头颜色:`#FFFFFF 100%`,透明底
|
||||
- 字号/线宽/虚线/箭头按图片短边自适应缩放
|
||||
- 三庭数值(名+数值两行,不带 cm)在图片**左侧**呈现,七眼段宽**上下穿插**展示,底部标「单位cm」
|
||||
- 三庭(名 + 数值带cm + 百分比 三行)在图片**左侧**呈现,七眼段宽**上下穿插**展示(数值带cm,下方另起一行标占头宽百分比)
|
||||
- 段宽/庭高用虚线 + 实心三角双箭头标示
|
||||
""",
|
||||
responses={
|
||||
@@ -736,7 +757,7 @@ async def hair_grow(
|
||||
hair_style: Optional[str] = Form(default=None, description="发型序号逗号分隔(必填),如 1,2,3。female:1-5 male:1-4"),
|
||||
beauty_enabled: bool = Form(default=False, description="是否开启美颜(本期不生效)"),
|
||||
use_mask: bool = Form(default=True, description="是否启用 inpaint 遮罩(测试对比用)。false 时用干净原图生成(空遮罩,不烧模板线)"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发", description="ComfyUI 提示词,会替换工作流节点60的文本"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜", description="ComfyUI 提示词,会替换工作流节点60的文本"),
|
||||
):
|
||||
# 1. gender 必填校验(非法/缺失 → 1004)
|
||||
if gender not in ("male", "female"):
|
||||
@@ -808,7 +829,6 @@ async def hair_grow_v2():
|
||||
"/api/v1/hair/grow-b",
|
||||
summary="接口3 B端生发(医生/操作端)",
|
||||
tags=["生发"],
|
||||
deprecated=True,
|
||||
description="""
|
||||
医生/操作端在用户照片上**手动用马克笔划线标注**目标发际线后,**只需上传这一张划线图**,返回:
|
||||
- 生发后效果图(系统检测划线 → 据此生成「植发 3 个月」效果)
|
||||
@@ -848,11 +868,36 @@ async def hair_grow_b(
|
||||
marked_image_url: Optional[str] = Form(default=None, description="划线图片 URL"),
|
||||
marked_image_base64: Optional[str] = Form(default=None, description="划线图片 base64"),
|
||||
use_mask: bool = Form(default=True, description="是否画发际线(测试对比用)。false 时跳过划线检测、直接送划线图"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发", description="ComfyUI 提示词,会替换工作流节点60的文本"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜", description="ComfyUI 提示词,会替换工作流节点60的文本"),
|
||||
):
|
||||
"""接口3 已屏蔽:调用直接返回错误,不再执行生发/ComfyUI 逻辑。
|
||||
保留路由(含原参数签名)避免老客户端裸 404,multipart 入参仍被接受但不处理。"""
|
||||
return err(1007, "接口3(/api/v1/hair/grow-b)已屏蔽,暂不提供服务")
|
||||
# 划线图三选一取图(只需这一张)
|
||||
marked_raw, e = await resolve_image_bytes(marked_image_file, marked_image_url, marked_image_base64)
|
||||
if e is not None:
|
||||
return e
|
||||
|
||||
marked = cv2.imdecode(np.frombuffer(marked_raw, np.uint8), cv2.IMREAD_COLOR)
|
||||
if marked is None:
|
||||
return err(1008, "图片格式不支持(仅 JPG / PNG)")
|
||||
|
||||
try:
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from hairline.service import generate_grow_b
|
||||
|
||||
res = await run_in_threadpool(generate_grow_b, marked, use_mask, prompt)
|
||||
if res["status"] == "no_face":
|
||||
return err(1001, "无法识别人像")
|
||||
if res["status"] == "no_line":
|
||||
return err(1001, "未检测到发际线划线,请确认划线图额头有清晰的手绘发际线")
|
||||
|
||||
grown_b64 = _png_to_jpg_b64(res["grown_png"]) if res["grown_png"] else None # 生发图 JPG
|
||||
data = {
|
||||
"hair_growth_image_base64": grown_b64,
|
||||
"hairline_type": "custom",
|
||||
}
|
||||
return ok(data)
|
||||
except Exception as ex: # noqa: BLE001
|
||||
logger.exception("接口3 处理异常")
|
||||
return err(1007, f"处理失败:{ex}")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -861,28 +906,56 @@ async def hair_grow_b(
|
||||
|
||||
@app.post(
|
||||
"/api/v1/face/features",
|
||||
summary="接口4 用户特征分析(仅网关)",
|
||||
summary="接口4 用户特征分析",
|
||||
tags=["人脸分析"],
|
||||
description="""
|
||||
**本接口不在 worker 实现。** 请调用网关(本机默认 `http://127.0.0.1:8080`)的同路径;
|
||||
网关本机调火山方舟豆包视觉模型,不转发到 worker。
|
||||
description=f"""
|
||||
输入用户照片,返回 N 个用户面部特征字段。
|
||||
|
||||
直接打 worker(如 `:8187`)会返回错误,避免误用假数据。
|
||||
{_image_fields_desc}
|
||||
|
||||
图片同时支持 `multipart/form-data` 文件上传(字段名 `image_file`)。
|
||||
|
||||
---
|
||||
|
||||
由**火山方舟 豆包视觉模型**分析,返回**固定 6 个英文字段**。
|
||||
|
||||
**返回格式**:`data.features` 为一个 **JSON 字符串**(不是对象),需要在客户端 `JSON.parse()` 后使用。
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| face_shape | 脸形(如"鹅蛋脸") |
|
||||
| eyebrow_shape | 眉形(如"平眉") |
|
||||
| facial_age | 面部年龄(区间,如"18-25岁") |
|
||||
| dynamic_static_type | 动静类型("静态型"/"动态型") |
|
||||
| gender | 性别("男"/"女") |
|
||||
| gene_style | 基因风格(如"自然型") |
|
||||
|
||||
> 无人脸返回 `1001`。
|
||||
""",
|
||||
responses={
|
||||
200: {
|
||||
"description": "worker 不提供本接口",
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": {
|
||||
"code": 1007,
|
||||
"message": "接口4 仅在网关实现,请访问网关(本机默认 :8080),worker 不提供本接口",
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"request_id": "mock-request-id",
|
||||
"data": None,
|
||||
"data": {
|
||||
"features": '{"face_shape":"鹅蛋脸","eyebrow_shape":"平眉","facial_age":"18-25岁","dynamic_static_type":"静态型","gender":"女","gene_style":"少年型"}',
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
400: {
|
||||
"description": "参数错误 / 图片识别失败",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": {"code": 1001, "message": "无法识别人像", "request_id": "x", "data": None}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
async def face_features(
|
||||
@@ -890,12 +963,16 @@ async def face_features(
|
||||
image_url: Optional[str] = Form(default=None, description="图片 URL"),
|
||||
image_base64: Optional[str] = Form(default=None, description="图片 base64(需带 data:image/...;base64, 前缀)"),
|
||||
):
|
||||
# 接口4 只在网关实现(gateway/app.py → face_features.analyze_features)。
|
||||
# 不再返回 Mock 成功数据,避免本机打 :8187 时被假结果误导。
|
||||
return err(
|
||||
1007,
|
||||
"接口4 仅在网关实现,请访问网关(本机默认 :8080),worker 不提供本接口",
|
||||
# ⚠️ 接口4 已迁到**网关本机**实现(直接调豆包视觉模型,见 gateway/app.py)。
|
||||
# 网关不会把本接口转发到 worker,故此处仅留 Mock 占位、保持 worker 无外网依赖。
|
||||
features = json.dumps(
|
||||
{
|
||||
"face_shape": "鹅蛋脸", "eyebrow_shape": "平眉", "facial_age": "18-25岁",
|
||||
"dynamic_static_type": "静态型", "gender": "女", "gene_style": "少年型",
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
return ok({"features": features})
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1001,7 +1078,7 @@ async def hairline_generate(
|
||||
gender: Optional[str] = Form(default=None, description="性别 male/female(必填)"),
|
||||
hair_style: Optional[str] = Form(default=None, description="发型序号逗号分隔(必填,如 1,2,3)。female:1-5 male:1-4"),
|
||||
use_mask: bool = Form(default=True, description="生发是否启用 inpaint 遮罩(同接口2,测试对比用)"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发", description="ComfyUI 提示词(同接口2),会替换工作流节点60的文本"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜", description="ComfyUI 提示词(同接口2),会替换工作流节点60的文本"),
|
||||
generate_grow_image: bool = Form(default=True, description="是否生成生发效果图(ComfyUI 生发,最耗时)。默认 true 出图;false 时跳过生发,各发型 grown_image 恒为 null,仅返回三档发际线叠图与中心点"),
|
||||
):
|
||||
if gender not in ("male", "female"):
|
||||
@@ -1395,7 +1472,7 @@ async def hairline_grow_v2(
|
||||
inpainting_fill: int = Form(default=1, description="change_hair服务端重绘填充:0=保留原图 | 1=噪声 | 2=纯色 | 3=潜变量。默认 1"),
|
||||
mask_blur: int = Form(default=11, description="change_hair服务端遮罩边缘模糊像素,默认 11"),
|
||||
mask_dilate_scale: float = Form(default=1.0, description="change_hair服务端遮罩膨胀缩放,默认 1.0"),
|
||||
comfyui_prompt: Optional[str] = Form(default=None, description="Flux-2 重绘提示词,None 用默认「填充遮罩区域的头发」"),
|
||||
comfyui_prompt: Optional[str] = Form(default=None, description="Flux-2 重绘提示词,None 用默认「填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜」"),
|
||||
beauty_alpha: float = Form(default=0.6, description="redraw_band 版 band 外的全脸美颜融入强度(0=band外无美颜纯用final,1≈整帧版),默认 0.6"),
|
||||
band_lo_mult: float = Form(default=0.5, description="重绘带外推倍率下限(相对 hairline_push_cm,内轮廓=0×、原外推线=1.0×),默认 0.5"),
|
||||
band_hi_mult: float = Form(default=1.5, description="重绘带外推倍率上限(相对 hairline_push_cm),默认 1.5"),
|
||||
@@ -1561,7 +1638,7 @@ async def hairline_grow_v2_final_v2(
|
||||
async def api_redraw(
|
||||
image_file: UploadFile = File(..., description="人物图片(JPG/PNG)"),
|
||||
mask_file: UploadFile = File(..., description="遮罩图片(PNG,支持红/白/alpha 格式)"),
|
||||
prompt: str = Form(default="填充遮罩区域的头发",
|
||||
prompt: str = Form(default="填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜",
|
||||
description="ComfyUI 提示词"),
|
||||
):
|
||||
image_bytes = await image_file.read()
|
||||
@@ -1606,84 +1683,6 @@ async def download_hairline_log(rid: Optional[str] = None, tail: int = 500):
|
||||
return PlainTextResponse("".join(lines), media_type="text/plain; charset=utf-8")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 调试:MediaPipe 脸型分类(face/face_shape_classifier.py,非接口4 豆包)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@app.post(
|
||||
"/api/v1/debug/face-shape",
|
||||
summary="调试 单张脸型分类(MediaPipe)",
|
||||
tags=["调试"],
|
||||
description="""
|
||||
离线脸型分类调试接口(`face/face_shape_classifier.py`),**不是**接口4 的豆包视觉分析。
|
||||
|
||||
上传正面照 → MediaPipe 468 点 → 7 类脸型评分 + 特征标注图。
|
||||
""",
|
||||
include_in_schema=True,
|
||||
)
|
||||
async def debug_face_shape(
|
||||
image_file: Optional[UploadFile] = File(default=None, description="上传图片文件(JPG/PNG)"),
|
||||
image_url: Optional[str] = Form(default=None, description="图片 URL"),
|
||||
image_base64: Optional[str] = Form(default=None, description="图片 base64"),
|
||||
):
|
||||
raw, e = await resolve_image_bytes(image_file, image_url, image_base64)
|
||||
if e:
|
||||
return e
|
||||
try:
|
||||
nparr = np.frombuffer(raw, np.uint8)
|
||||
bgr = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
|
||||
if bgr is None:
|
||||
return err(1008, "图片格式不支持(仅 JPG / PNG)")
|
||||
except Exception: # noqa: BLE001
|
||||
return err(1008, "图片格式不支持(仅 JPG / PNG)")
|
||||
|
||||
def _jsonable(obj):
|
||||
if isinstance(obj, dict):
|
||||
return {k: _jsonable(v) for k, v in obj.items()}
|
||||
if isinstance(obj, (list, tuple)):
|
||||
return [_jsonable(v) for v in obj]
|
||||
if hasattr(obj, "item"):
|
||||
return obj.item()
|
||||
if isinstance(obj, (float, int, str, bool)) or obj is None:
|
||||
return obj
|
||||
return obj
|
||||
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
try:
|
||||
from face.face_shape_classifier import classify_from_image
|
||||
|
||||
result = await run_in_threadpool(
|
||||
classify_from_image, bgr, True, True,
|
||||
)
|
||||
except ValueError as ex:
|
||||
return err(1001, str(ex) or "无法识别人像")
|
||||
except Exception as ex: # noqa: BLE001
|
||||
return err(1007, f"脸型分类失败:{ex}")
|
||||
|
||||
details = result.get("details") or {}
|
||||
ranked = [
|
||||
{"shape": name, "score": round(float(score), 2)}
|
||||
for name, score in (details.get("ranked") or [])
|
||||
]
|
||||
annotated = result.pop("annotated", None)
|
||||
h, w = bgr.shape[:2]
|
||||
data = {
|
||||
"face_shape": result["face_shape"],
|
||||
"display": result["display"],
|
||||
"confidence": round(float(result["confidence"]), 4),
|
||||
"is_mixed": bool(details.get("is_mixed")),
|
||||
"second_shape": details.get("second_shape"),
|
||||
"score_gap": round(float(details["score_gap"]), 2) if details.get("score_gap") is not None else None,
|
||||
"ranked": ranked,
|
||||
"features": _jsonable(result.get("features") or {}),
|
||||
"zscores": _jsonable(details.get("zscores") or {}),
|
||||
"image_size": {"width": w, "height": h},
|
||||
"annotated_image_base64": _jpg_b64(annotated) if annotated is not None else None,
|
||||
}
|
||||
return ok(data)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 健康检查
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""9B vs 4B 模型对比:3 张图 × 5 种发型 = 15 张对比图。
|
||||
|
||||
第一次运行:PLAN_TAG=A (9B 模型,需先切工作流到 .bak)
|
||||
第二次运行:PLAN_TAG=Bplus(4B 模型,需切回 4B 工作流)
|
||||
"""
|
||||
import json, os, time, base64, subprocess, urllib.request
|
||||
from datetime import datetime
|
||||
|
||||
API_BASE = "http://127.0.0.1:8187"
|
||||
TOKEN = "dev-shared-secret-2026"
|
||||
IMAGES = [
|
||||
"/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
]
|
||||
PLAN_TAG = os.getenv("PLAN_TAG", "A")
|
||||
OUT_DIR = f"/home/ubuntu/hair/benchmark_out/9b_vs_4b_{PLAN_TAG}"
|
||||
RESULT_JSON = os.path.join(OUT_DIR, "results.json")
|
||||
REPORT_HTML = os.path.join(OUT_DIR, "report.html")
|
||||
HAIR_STYLES = [(1, "椭圆"), (2, "花瓣"), (3, "心形"), (4, "直线"), (5, "波浪")]
|
||||
WARMUP = os.getenv("WARMUP", "1") == "1" # 第一次调用做预热
|
||||
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def get_vram():
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
["nvidia-smi", "--query-gpu=memory.used,memory.free",
|
||||
"--format=csv,noheader,nounits"], text=True, timeout=5).strip()
|
||||
used, free = out.split(",")
|
||||
return int(used.strip()), int(free.strip())
|
||||
except Exception:
|
||||
return -1, -1
|
||||
|
||||
|
||||
def _multipart(fields, files=None):
|
||||
boundary = "----CmpTest" + str(int(time.time() * 1000))
|
||||
parts = []
|
||||
for k, v in fields.items():
|
||||
parts.append(f"--{boundary}\r\n".encode())
|
||||
parts.append(f'Content-Disposition: form-data; name="{k}"\r\n\r\n'.encode())
|
||||
parts.append(str(v).encode())
|
||||
parts.append(b"\r\n")
|
||||
if files:
|
||||
for field_name, (filename, data, mime) in files.items():
|
||||
parts.append(f"--{boundary}\r\n".encode())
|
||||
parts.append(f'Content-Disposition: form-data; name="{field_name}"; filename="{filename}"\r\n'.encode())
|
||||
parts.append(f"Content-Type: {mime}\r\n\r\n".encode())
|
||||
parts.append(data)
|
||||
parts.append(b"\r\n")
|
||||
parts.append(f"--{boundary}--\r\n".encode())
|
||||
return b"".join(parts), boundary
|
||||
|
||||
|
||||
def call_iface2(image_path, hair_style):
|
||||
with open(image_path, "rb") as f:
|
||||
img_data = f.read()
|
||||
fields = {"gender": "female", "hair_style": str(hair_style),
|
||||
"prompt": "填充遮罩区域的头发"}
|
||||
body, boundary = _multipart(
|
||||
fields, {"image_file": (os.path.basename(image_path), img_data, "image/jpeg")})
|
||||
req = urllib.request.Request(f"{API_BASE}/api/v1/hair/grow", data=body, method="POST")
|
||||
req.add_header("Content-Type", f"multipart/form-data; boundary={boundary}")
|
||||
req.add_header("X-Internal-Token", TOKEN)
|
||||
t0 = time.time()
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=600) as resp:
|
||||
data = json.loads(resp.read())
|
||||
return data, time.time() - t0, None
|
||||
except Exception as e:
|
||||
return {}, time.time() - t0, str(e)
|
||||
|
||||
|
||||
def extract_image(data, img_idx, hs):
|
||||
"""从响应提取 grown_image_base64 并保存为 jpg。"""
|
||||
if not data or not data.get("data"):
|
||||
return None
|
||||
items = data["data"].get("results") or []
|
||||
if not items:
|
||||
return None
|
||||
b64 = items[0].get("grown_image_base64") or ""
|
||||
if b64.startswith("data:"):
|
||||
b64 = b64.split(",", 1)[1]
|
||||
if not b64:
|
||||
return None
|
||||
fname = f"img{img_idx}_style{hs}.jpg"
|
||||
path = os.path.join(OUT_DIR, fname)
|
||||
with open(path, "wb") as f:
|
||||
f.write(base64.b64decode(b64))
|
||||
return path
|
||||
|
||||
|
||||
def run_test():
|
||||
results = []
|
||||
print(f"9B vs 4B 对比测试 — Plan={PLAN_TAG}")
|
||||
print(f"图片: {[os.path.basename(p) for p in IMAGES]}")
|
||||
print(f"发型: {[(s,n) for s,n in HAIR_STYLES]}")
|
||||
print(f"总调用: {len(IMAGES)*len(HAIR_STYLES)}\n")
|
||||
|
||||
# 预热请求(避免第一次冷启动计入统计)
|
||||
if WARMUP:
|
||||
print("[warmup] 预热请求 (girl13, style=1) ...")
|
||||
t0 = time.time()
|
||||
_, warmup_time, _ = call_iface2(IMAGES[2], 1)
|
||||
print(f" warmup: {warmup_time:.1f}s\n")
|
||||
|
||||
for img_idx, img_path in enumerate(IMAGES, start=1):
|
||||
img_name = os.path.basename(img_path)
|
||||
for hs, hs_name in HAIR_STYLES:
|
||||
print(f"[img{img_idx}/{len(IMAGES)}] {img_name} style={hs}({hs_name}) ...")
|
||||
|
||||
vram_before, _ = get_vram()
|
||||
data, elapsed, error = call_iface2(img_path, hs)
|
||||
vram_after, _ = get_vram()
|
||||
|
||||
code = data.get("code", -1) if data else -1
|
||||
ok = (code == 0)
|
||||
img_saved = extract_image(data, img_idx, hs) if ok else None
|
||||
|
||||
record = {
|
||||
"plan": PLAN_TAG,
|
||||
"image_idx": img_idx,
|
||||
"image_name": img_name,
|
||||
"image_path": img_path,
|
||||
"hair_style": hs,
|
||||
"hair_style_name": hs_name,
|
||||
"timestamp": datetime.now().strftime("%H:%M:%S"),
|
||||
"elapsed_s": round(elapsed, 2),
|
||||
"success": ok,
|
||||
"code": code,
|
||||
"error": error,
|
||||
"vram_before_mb": vram_before,
|
||||
"vram_after_mb": vram_after,
|
||||
"vram_delta_mb": vram_after - vram_before,
|
||||
"saved_image_path": img_saved,
|
||||
}
|
||||
results.append(record)
|
||||
|
||||
status = "✓" if ok else "✗"
|
||||
print(f" → {status} code={code} time={elapsed:.1f}s "
|
||||
f"vram={vram_before}→{vram_after}MB (Δ{vram_after-vram_before:+d}) "
|
||||
f"img={'saved' if img_saved else 'none'}")
|
||||
|
||||
with open(RESULT_JSON, "w") as f:
|
||||
json.dump(results, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"\n✅ 完成!{RESULT_JSON}")
|
||||
print(f"📊 成功: {sum(1 for r in results if r['success'])}/{len(results)}")
|
||||
if any(r['success'] for r in results):
|
||||
avg = sum(r['elapsed_s'] for r in results if r['success']) / sum(1 for r in results if r['success'])
|
||||
print(f"⏱ 平均: {avg:.2f}s")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_test()
|
||||
@@ -1,450 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""基准测试:19张图片 × 5种发际线,记录每步耗时和显存变化。
|
||||
|
||||
用法: python3 benchmark_grow.py
|
||||
输出: benchmark_results.json + benchmark_report.html
|
||||
"""
|
||||
import json, os, time, base64, subprocess, re, glob, shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import urllib.request, urllib.error
|
||||
|
||||
API_URL = "http://127.0.0.1:8187/api/v1/hair/grow"
|
||||
TOKEN = "dev-shared-secret-2026"
|
||||
IMG_DIR = "/home/ubuntu/hair/image/girl_img"
|
||||
OUT_DIR = "/home/ubuntu/hair/benchmark_out"
|
||||
RESULT_JSON = os.path.join(OUT_DIR, "benchmark_results.json")
|
||||
REPORT_HTML = os.path.join(OUT_DIR, "benchmark_report.html")
|
||||
|
||||
HAIRLINES = [
|
||||
("1", "ellipse", "椭圆形"),
|
||||
("2", "flower", "花瓣形"),
|
||||
("3", "heart", "心形"),
|
||||
("4", "straight", "直线形"),
|
||||
("5", "wave", "波浪形"),
|
||||
]
|
||||
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
|
||||
|
||||
# ── 工具函数 ──────────────────────────────────────────────
|
||||
|
||||
def get_vram():
|
||||
"""返回 (used_MB, free_MB)"""
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
["nvidia-smi", "--query-gpu=memory.used,memory.free",
|
||||
"--format=csv,noheader,nounits"], text=True, timeout=5
|
||||
).strip()
|
||||
used, free = out.split(",")
|
||||
return int(used.strip()), int(free.strip())
|
||||
except Exception:
|
||||
return -1, -1
|
||||
|
||||
|
||||
def get_gpu_procs():
|
||||
"""返回各进程显存占用 dict"""
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
["nvidia-smi", "--query-compute-apps=pid,used_memory",
|
||||
"--format=csv,noheader,nounits"], text=True, timeout=5
|
||||
).strip()
|
||||
procs = {}
|
||||
for line in out.splitlines():
|
||||
parts = line.split(",")
|
||||
if len(parts) >= 2:
|
||||
procs[parts[0].strip()] = int(parts[1].strip())
|
||||
return procs
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def read_worker_log_tail(n=50):
|
||||
"""读取 worker.log 最后 n 行"""
|
||||
log_path = "/home/ubuntu/hair/worker.log"
|
||||
try:
|
||||
result = subprocess.run(["tail", "-n", str(n), log_path],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
return result.stdout
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def call_api(image_path, hair_style_value):
|
||||
"""调用接口2,返回 (json_dict, elapsed_sec, error_or_None)"""
|
||||
import mimetypes
|
||||
boundary = "----BenchmarkBoundary" + str(int(time.time()*1000))
|
||||
filename = os.path.basename(image_path)
|
||||
mime = mimetypes.guess_type(image_path)[0] or "image/jpeg"
|
||||
|
||||
with open(image_path, "rb") as f:
|
||||
img_data = f.read()
|
||||
|
||||
body_parts = []
|
||||
body_parts.append(f"--{boundary}\r\n".encode())
|
||||
body_parts.append(f'Content-Disposition: form-data; name="image_file"; filename="{filename}"\r\n'.encode())
|
||||
body_parts.append(f"Content-Type: {mime}\r\n\r\n".encode())
|
||||
body_parts.append(img_data)
|
||||
body_parts.append(f"\r\n--{boundary}\r\n".encode())
|
||||
body_parts.append(b'Content-Disposition: form-data; name="gender"\r\n\r\n')
|
||||
body_parts.append(b"female")
|
||||
body_parts.append(f"\r\n--{boundary}\r\n".encode())
|
||||
body_parts.append(b'Content-Disposition: form-data; name="hair_style"\r\n\r\n')
|
||||
body_parts.append(hair_style_value.encode())
|
||||
body_parts.append(f"\r\n--{boundary}\r\n".encode())
|
||||
body_parts.append(b'Content-Disposition: form-data; name="use_mask"\r\n\r\n')
|
||||
body_parts.append(b"0")
|
||||
body_parts.append(f"\r\n--{boundary}\r\n".encode())
|
||||
body_parts.append(b'Content-Disposition: form-data; name="prompt"\r\n\r\n')
|
||||
body_parts.append(b"\xe5\xa1\xab\xe5\x85\x85\xe9\x81\xae\xe7\xbd\xa9\xe5\x8c\xba\xe5\x9f\x9f\xe7\x9a\x84\xe5\xa4\xb4\xe5\x8f\x91\xef\xbc\x8c\xe7\x9a\xae\xe8\x82\xa4\xe5\x8a\xa0\xe4\xb8\x80\xe7\x82\xb9\xe7\xa3\xa8\xe7\x9a\xae")
|
||||
body_parts.append(f"\r\n--{boundary}--\r\n".encode())
|
||||
body = b"".join(body_parts)
|
||||
|
||||
req = urllib.request.Request(API_URL, data=body, method="POST")
|
||||
req.add_header("Content-Type", f"multipart/form-data; boundary={boundary}")
|
||||
req.add_header("X-Internal-Token", TOKEN)
|
||||
|
||||
t0 = time.time()
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=600) as resp:
|
||||
raw = resp.read()
|
||||
elapsed = time.time() - t0
|
||||
data = json.loads(raw)
|
||||
return data, elapsed, None
|
||||
except urllib.error.HTTPError as e:
|
||||
elapsed = time.time() - t0
|
||||
try:
|
||||
data = json.loads(e.read())
|
||||
except Exception:
|
||||
data = {"error": str(e)}
|
||||
return data, elapsed, f"HTTP {e.code}"
|
||||
except Exception as e:
|
||||
elapsed = time.time() - t0
|
||||
return {}, elapsed, str(e)
|
||||
|
||||
|
||||
def parse_step_timing(log_text):
|
||||
"""从 worker.log 文本中解析步骤耗时"""
|
||||
timing = {}
|
||||
for line in log_text.splitlines():
|
||||
# 匹配 "步骤1 遮罩完成 耗时=949ms"
|
||||
m = re.search(r"步骤(\d+)\s+\S+\s+耗时=(\d+)ms", line)
|
||||
if m:
|
||||
timing[f"step{m.group(1)}_ms"] = int(m.group(2))
|
||||
# 匹配 "人脸检出 px_per_cm=30.669 图尺寸=813x967"
|
||||
if "人脸检出" in line:
|
||||
m2 = re.search(r"px_per_cm=([\d.]+)", line)
|
||||
if m2:
|
||||
timing["px_per_cm"] = float(m2.group(1))
|
||||
# 匹配 "头发分割完成"
|
||||
if "头发分割完成" in line:
|
||||
timing["hair_seg"] = True
|
||||
# 匹配 "换发型图失败"
|
||||
if "换发型图失败" in line or "换发型服务不可达" in line:
|
||||
timing["swap_error"] = line.strip()[-100:]
|
||||
# 匹配 "重绘" 相关
|
||||
if "重绘" in line and ("完成" in line or "失败" in line):
|
||||
timing["redraw_status"] = "完成" if "完成" in line else "失败"
|
||||
return timing
|
||||
|
||||
|
||||
# ── 主流程 ────────────────────────────────────────────────
|
||||
|
||||
def run_benchmark():
|
||||
images = sorted(glob.glob(os.path.join(IMG_DIR, "girl*.jpg")))
|
||||
print(f"找到 {len(images)} 张图片")
|
||||
|
||||
# 加载已有结果(支持断点续跑)
|
||||
results = []
|
||||
if os.path.exists(RESULT_JSON):
|
||||
with open(RESULT_JSON) as f:
|
||||
results = json.load(f)
|
||||
print(f"已有 {len(results)} 条记录,继续未完成的测试")
|
||||
|
||||
total_calls = len(images) * len(HAIRLINES)
|
||||
done = len(results)
|
||||
print(f"总计 {total_calls} 次调用,已完成 {done},剩余 {total_calls - done}")
|
||||
|
||||
log_offset = 0
|
||||
try:
|
||||
log_offset = subprocess.check_output(["wc", "-l", "/home/ubuntu/hair/worker.log"],
|
||||
text=True, timeout=5).split()[0]
|
||||
log_offset = int(log_offset)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for img_idx, img_path in enumerate(images):
|
||||
img_name = os.path.basename(img_path)
|
||||
|
||||
# 跳过已完成的图片
|
||||
img_results = [r for r in results if r["image"] == img_name]
|
||||
if len(img_results) >= len(HAIRLINES):
|
||||
print(f"[{img_idx+1}/{len(images)}] {img_name} 已完成,跳过")
|
||||
continue
|
||||
|
||||
for hl_id, hl_key, hl_label in HAIRLINES:
|
||||
# 跳过已完成的
|
||||
existing = [r for r in results if r["image"] == img_name and r["hairline_id"] == hl_id]
|
||||
if existing:
|
||||
continue
|
||||
|
||||
print(f"\n[{img_idx+1}/{len(images)}] {img_name} → {hl_label}({hl_id}) ...")
|
||||
|
||||
# 记录 worker.log 行数
|
||||
try:
|
||||
log_before = int(subprocess.check_output(
|
||||
["wc", "-l", "/home/ubuntu/hair/worker.log"], text=True, timeout=5).split()[0])
|
||||
except Exception:
|
||||
log_before = 0
|
||||
|
||||
# VRAM before
|
||||
vram_before, vram_free_before = get_vram()
|
||||
procs_before = get_gpu_procs()
|
||||
t_start = time.time()
|
||||
|
||||
# 调用API
|
||||
api_result, elapsed, error = call_api(img_path, hl_id)
|
||||
|
||||
t_end = time.time()
|
||||
|
||||
# VRAM after
|
||||
vram_after, vram_free_after = get_vram()
|
||||
procs_after = get_gpu_procs()
|
||||
|
||||
# 读取新日志
|
||||
try:
|
||||
log_diff = subprocess.check_output(
|
||||
["tail", "-n", "+{}".format(log_before + 1), "/home/ubuntu/hair/worker.log"],
|
||||
text=True, timeout=5)
|
||||
except Exception:
|
||||
log_diff = ""
|
||||
|
||||
step_timing = parse_step_timing(log_diff)
|
||||
|
||||
# 提取结果图片
|
||||
preview_b64 = ""
|
||||
grown_b64 = ""
|
||||
api_code = api_result.get("code", -1)
|
||||
api_msg = api_result.get("message", "")
|
||||
api_results = api_result.get("data", {}).get("results", [])
|
||||
if api_results:
|
||||
r0 = api_results[0]
|
||||
preview_b64 = r0.get("image_base64", "")
|
||||
grown_b64 = r0.get("grown_image_base64", "")
|
||||
|
||||
# 保存缩略图
|
||||
thumb_dir = os.path.join(OUT_DIR, "thumbs")
|
||||
os.makedirs(thumb_dir, exist_ok=True)
|
||||
if grown_b64:
|
||||
grown_bytes = base64.b64decode(grown_b64)
|
||||
thumb_path = os.path.join(thumb_dir, f"{img_name}_hl{hl_id}_grown.jpg")
|
||||
with open(thumb_path, "wb") as f:
|
||||
f.write(grown_bytes)
|
||||
if preview_b64:
|
||||
preview_bytes = base64.b64decode(preview_b64)
|
||||
thumb_path = os.path.join(thumb_dir, f"{img_name}_hl{hl_id}_preview.png")
|
||||
with open(thumb_path, "wb") as f:
|
||||
f.write(preview_bytes)
|
||||
|
||||
record = {
|
||||
"image": img_name,
|
||||
"image_idx": img_idx + 1,
|
||||
"hairline_id": hl_id,
|
||||
"hairline_key": hl_key,
|
||||
"hairline_label": hl_label,
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"total_time_s": round(elapsed, 2),
|
||||
"api_code": api_code,
|
||||
"api_msg": api_msg,
|
||||
"error": error,
|
||||
"has_preview": bool(preview_b64),
|
||||
"has_grown": bool(grown_b64),
|
||||
"preview_size": len(preview_b64),
|
||||
"grown_size": len(grown_b64),
|
||||
"vram_before_mb": vram_before,
|
||||
"vram_after_mb": vram_after,
|
||||
"vram_free_before_mb": vram_free_before,
|
||||
"vram_free_after_mb": vram_free_after,
|
||||
"vram_delta_mb": vram_after - vram_before,
|
||||
"procs_before": procs_before,
|
||||
"procs_after": procs_after,
|
||||
"step_timing": step_timing,
|
||||
}
|
||||
results.append(record)
|
||||
print(f" → HTTP code={api_code} time={elapsed:.1f}s vram={vram_before}→{vram_after}MB "
|
||||
f"preview={'✓' if preview_b64 else '✗'} grown={'✓' if grown_b64 else '✗'}")
|
||||
|
||||
# 保存中间结果
|
||||
with open(RESULT_JSON, "w") as f:
|
||||
json.dump(results, f, indent=2, ensure_ascii=False)
|
||||
|
||||
# 生成中间报告
|
||||
generate_html(results)
|
||||
|
||||
# 最终报告
|
||||
generate_html(results)
|
||||
print(f"\n✅ 完成!结果: {RESULT_JSON}")
|
||||
print(f"📄 报告: {REPORT_HTML}")
|
||||
print(f"📊 总调用: {len(results)}/{total_calls}")
|
||||
|
||||
|
||||
def generate_html(results):
|
||||
"""生成HTML报告"""
|
||||
# 统计
|
||||
total = len(results)
|
||||
success = sum(1 for r in results if r["has_grown"])
|
||||
failed = total - success
|
||||
times = [r["total_time_s"] for r in results if r["has_grown"]]
|
||||
avg_time = sum(times) / len(times) if times else 0
|
||||
max_time = max(times) if times else 0
|
||||
min_time = min(times) if times else 0
|
||||
|
||||
# 按发际线类型分组统计
|
||||
hl_stats = {}
|
||||
for r in results:
|
||||
if r["has_grown"]:
|
||||
hl = r["hairline_label"]
|
||||
if hl not in hl_stats:
|
||||
hl_stats[hl] = {"count": 0, "times": []}
|
||||
hl_stats[hl]["count"] += 1
|
||||
hl_stats[hl]["times"].append(r["total_time_s"])
|
||||
|
||||
# 按图片分组
|
||||
img_groups = {}
|
||||
for r in results:
|
||||
img = r["image"]
|
||||
if img not in img_groups:
|
||||
img_groups[img] = []
|
||||
img_groups[img].append(r)
|
||||
|
||||
# 生成VRAM变化数据
|
||||
vram_data = [(i, r["vram_after_mb"]) for i, r in enumerate(results)]
|
||||
|
||||
html = f"""<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>接口2 基准测试报告</title>
|
||||
<style>
|
||||
* {{ margin:0; padding:0; box-sizing:border-box; }}
|
||||
body {{ font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; background:#1a1a2e; color:#e0e0e0; padding:20px; }}
|
||||
h1 {{ text-align:center; margin-bottom:20px; color:#00d4ff; }}
|
||||
.subtitle {{ text-align:center; color:#888; margin-bottom:30px; font-size:14px; }}
|
||||
.summary {{ display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:15px; margin-bottom:30px; }}
|
||||
.card {{ background:#16213e; border-radius:12px; padding:20px; text-align:center; border:1px solid #333; }}
|
||||
.card .num {{ font-size:32px; font-weight:700; }}
|
||||
.card .label {{ font-size:12px; color:#888; margin-top:5px; }}
|
||||
.card.ok .num {{ color:#0f0; }}
|
||||
.card.err .num {{ color:#f44; }}
|
||||
.card.time .num {{ color:#00d4ff; }}
|
||||
table {{ width:100%; border-collapse:collapse; margin-bottom:30px; background:#16213e; border-radius:12px; overflow:hidden; }}
|
||||
th {{ background:#0f3460; padding:12px 8px; text-align:center; font-size:13px; color:#fff; }}
|
||||
td {{ padding:8px; text-align:center; border-bottom:1px solid #222; font-size:13px; }}
|
||||
tr:hover {{ background:#1a1a3e; }}
|
||||
.img-cell {{ text-align:left; }}
|
||||
.time-bar {{ display:inline-block; height:20px; background:linear-gradient(90deg,#0f3460,#00d4ff); border-radius:4px; vertical-align:middle; min-width:2px; }}
|
||||
.hl-badge {{ display:inline-block; padding:2px 8px; border-radius:10px; font-size:11px; font-weight:600; }}
|
||||
.hl-ellipse {{ background:#1b4332; color:#52b788; }}
|
||||
.hl-flower {{ background:#3a0ca3; color:#c77dff; }}
|
||||
.hl-heart {{ background:#6a040f; color:#ff6b6b; }}
|
||||
.hl-straight {{ background:#0077b6; color:#90e0ef; }}
|
||||
.hl-wave {{ background:#9d4edd; color:#e0aaff; }}
|
||||
.ok {{ color:#0f0; }} .fail {{ color:#f44; }}
|
||||
.vram-chart {{ margin:20px 0; }}
|
||||
.vram-bars {{ display:flex; align-items:flex-end; height:120px; gap:2px; padding:10px; background:#0d1117; border-radius:8px; }}
|
||||
.vram-bar {{ flex:1; background:linear-gradient(180deg,#00d4ff,#0f3460); border-radius:2px 2px 0 0; min-height:2px; position:relative; }}
|
||||
.vram-bar:hover::after {{ content:attr(data-val) 'MB'; position:absolute; bottom:100%; left:50%; transform:translateX(-50%); background:#333; padding:2px 6px; border-radius:4px; font-size:10px; white-space:nowrap; }}
|
||||
.section-title {{ font-size:18px; font-weight:600; margin:30px 0 15px; color:#00d4ff; border-bottom:1px solid #333; padding-bottom:10px; }}
|
||||
.hl-stats {{ display:grid; grid-template-columns:repeat(5,1fr); gap:15px; margin-bottom:20px; }}
|
||||
.hl-card {{ background:#16213e; border-radius:12px; padding:15px; text-align:center; }}
|
||||
.hl-card .avg {{ font-size:24px; font-weight:700; color:#00d4ff; }}
|
||||
.hl-card .minmax {{ font-size:11px; color:#888; margin-top:5px; }}
|
||||
.thumb {{ max-width:100px; max-height:100px; border-radius:4px; cursor:pointer; }}
|
||||
.thumb:hover {{ transform:scale(2); transition:transform 0.3s; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>📊 接口2 基准测试报告</h1>
|
||||
<div class="subtitle">生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | {total} 次调用</div>
|
||||
|
||||
<div class="summary">
|
||||
<div class="card ok"><div class="num">{success}</div><div class="label">成功</div></div>
|
||||
<div class="card err"><div class="num">{failed}</div><div class="label">失败</div></div>
|
||||
<div class="card time"><div class="num">{avg_time:.1f}s</div><div class="label">平均耗时</div></div>
|
||||
<div class="card time"><div class="num">{min_time:.1f}s</div><div class="label">最快</div></div>
|
||||
<div class="card time"><div class="num">{max_time:.1f}s</div><div class="label">最慢</div></div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
# 按发际线类型统计
|
||||
if hl_stats:
|
||||
html += '<div class="section-title">按发际线类型统计</div><div class="hl-stats">'
|
||||
for hl_label in ["椭圆形","花瓣形","心形","直线形","波浪形"]:
|
||||
if hl_label in hl_stats:
|
||||
s = hl_stats[hl_label]
|
||||
times = s["times"]
|
||||
avg = sum(times) / len(times)
|
||||
mn, mx = min(times), max(times)
|
||||
cls = hl_label
|
||||
html += f'<div class="hl-card"><div class="hl-badge hl-{{cls}}">{hl_label}</div><div class="avg">{avg:.1f}s</div><div class="minmax">{mn:.1f}~{mx:.1f}s ({s["count"]}次)</div></div>'
|
||||
else:
|
||||
html += f'<div class="hl-card"><div class="hl-badge">{hl_label}</div><div class="avg">-</div><div class="minmax">未完成</div></div>'
|
||||
html += '</div>'
|
||||
|
||||
# VRAM 变化图
|
||||
if vram_data:
|
||||
max_vram = max(v for _, v in vram_data if v > 0) or 1
|
||||
html += '<div class="section-title">显存变化</div><div class="vram-chart"><div class="vram-bars">'
|
||||
for i, (_, vram) in enumerate(vram_data):
|
||||
if vram > 0:
|
||||
h = int(vram / max_vram * 100)
|
||||
html += f'<div class="vram-bar" style="height:{h}%" data-val="{vram}" title="第{i+1}次"></div>'
|
||||
else:
|
||||
html += f'<div class="vram-bar" style="height:0%" data-val="0"></div>'
|
||||
html += '</div></div>'
|
||||
|
||||
# 详细结果表格
|
||||
html += '<div class="section-title">详细结果</div><table><thead><tr>'
|
||||
html += '<th>#</th><th>图片</th><th>发际线</th><th>总耗时</th><th>遮罩步骤</th>'
|
||||
html += '<th>显存前</th><th>显存后</th><th>显存变化</th>'
|
||||
html += '<th>预览图</th><th>生发图</th><th>状态</th>'
|
||||
html += '</tr></thead><tbody>'
|
||||
|
||||
for i, r in enumerate(results):
|
||||
hl_cls = r["hairline_key"]
|
||||
status = '<span class="ok">✓ 成功</span>' if r["has_grown"] else f'<span class="fail">✗ {r.get("error","")}</span>'
|
||||
step_ms = r.get("step_timing", {}).get("step1_ms", "")
|
||||
step_str = f"{step_ms}ms" if step_ms else "-"
|
||||
vram_d = r["vram_delta_mb"]
|
||||
vram_d_str = f'<span style="color:{"#f44" if vram_d>0 else "#0f0"}">{"+" if vram_d>=0 else ""}{vram_d}</span>'
|
||||
|
||||
# 缩略图
|
||||
thumb_grown = ""
|
||||
if r["has_grown"]:
|
||||
thumb_path = f"thumbs/{r['image']}_hl{r['hairline_id']}_grown.jpg"
|
||||
if os.path.exists(os.path.join(OUT_DIR, thumb_path)):
|
||||
thumb_grown = f'<img class="thumb" src="{thumb_path}">'
|
||||
|
||||
html += f"""<tr>
|
||||
<td>{i+1}</td>
|
||||
<td class="img-cell">{r['image']}</td>
|
||||
<td><span class="hl-badge hl-{hl_cls}">{r['hairline_label']}</span></td>
|
||||
<td><div class="time-bar" style="width:{min(r['total_time_s'],300)}px"></div> {r['total_time_s']:.1f}s</td>
|
||||
<td>{step_str}</td>
|
||||
<td>{r['vram_before_mb']}MB</td>
|
||||
<td>{r['vram_after_mb']}MB</td>
|
||||
<td>{vram_d_str}</td>
|
||||
<td>{'✓' if r['has_preview'] else '✗'}</td>
|
||||
<td>{thumb_grown if thumb_grown else ('✓' if r['has_grown'] else '✗')}</td>
|
||||
<td>{status}</td>
|
||||
</tr>"""
|
||||
|
||||
html += '</tbody></table>'
|
||||
html += '</body></html>'
|
||||
|
||||
with open(REPORT_HTML, "w", encoding="utf-8") as f:
|
||||
f.write(html)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_benchmark()
|
||||
@@ -1,201 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""接口2女性5种发型对比测试:Plan B vs Plan B+。
|
||||
|
||||
测试 hair_style=1..5(椭圆/花瓣/心形/直线/波浪),每种发型一次,记录耗时+显存+生成图。
|
||||
"""
|
||||
import json, os, time, base64, subprocess, urllib.request, urllib.error
|
||||
from datetime import datetime
|
||||
|
||||
API_BASE = "http://127.0.0.1:8187"
|
||||
TOKEN = "dev-shared-secret-2026"
|
||||
GIRL_IMG = "/home/ubuntu/hair/image/girl_img/girl13.jpg"
|
||||
PLAN_TAG = os.getenv("PLAN_TAG", "Bplus") # Bplus / B
|
||||
OUT_DIR = f"/home/ubuntu/hair/benchmark_out/iface2_female_{PLAN_TAG}"
|
||||
RESULT_JSON = os.path.join(OUT_DIR, "results.json")
|
||||
REPORT_HTML = os.path.join(OUT_DIR, "report.html")
|
||||
|
||||
HAIR_STYLE_NAMES = {
|
||||
"1": "椭圆", "2": "花瓣", "3": "心形", "4": "直线", "5": "波浪",
|
||||
}
|
||||
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def get_vram():
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
["nvidia-smi", "--query-gpu=memory.used,memory.free",
|
||||
"--format=csv,noheader,nounits"], text=True, timeout=5).strip()
|
||||
used, free = out.split(",")
|
||||
return int(used.strip()), int(free.strip())
|
||||
except Exception:
|
||||
return -1, -1
|
||||
|
||||
|
||||
def _multipart(fields, files=None):
|
||||
boundary = "----If2Test" + str(int(time.time() * 1000))
|
||||
parts = []
|
||||
for k, v in fields.items():
|
||||
parts.append(f"--{boundary}\r\n".encode())
|
||||
parts.append(f'Content-Disposition: form-data; name="{k}"\r\n\r\n'.encode())
|
||||
parts.append(str(v).encode())
|
||||
parts.append(b"\r\n")
|
||||
if files:
|
||||
for field_name, (filename, data, mime) in files.items():
|
||||
parts.append(f"--{boundary}\r\n".encode())
|
||||
parts.append(f'Content-Disposition: form-data; name="{field_name}"; filename="{filename}"\r\n'.encode())
|
||||
parts.append(f"Content-Type: {mime}\r\n\r\n".encode())
|
||||
parts.append(data)
|
||||
parts.append(b"\r\n")
|
||||
parts.append(f"--{boundary}--\r\n".encode())
|
||||
return b"".join(parts), boundary
|
||||
|
||||
|
||||
def call_iface2_female(image_path, hair_style):
|
||||
"""接口2 女性 + 指定发型(走 swapHair 路径)"""
|
||||
with open(image_path, "rb") as f:
|
||||
img_data = f.read()
|
||||
fields = {"gender": "female", "hair_style": str(hair_style),
|
||||
"prompt": "填充遮罩区域的头发"}
|
||||
body, boundary = _multipart(
|
||||
fields, {"image_file": (os.path.basename(image_path), img_data, "image/jpeg")})
|
||||
req = urllib.request.Request(f"{API_BASE}/api/v1/hair/grow", data=body, method="POST")
|
||||
req.add_header("Content-Type", f"multipart/form-data; boundary={boundary}")
|
||||
req.add_header("X-Internal-Token", TOKEN)
|
||||
t0 = time.time()
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=600) as resp:
|
||||
data = json.loads(resp.read())
|
||||
return data, time.time() - t0, None
|
||||
except Exception as e:
|
||||
return {}, time.time() - t0, str(e)
|
||||
|
||||
|
||||
def run_test():
|
||||
results = []
|
||||
print(f"接口2女性5种发型测试 — Plan={PLAN_TAG}")
|
||||
print(f"图片:{GIRL_IMG}\n")
|
||||
|
||||
for hs in range(1, 6):
|
||||
name = HAIR_STYLE_NAMES[str(hs)]
|
||||
print(f"\n[{hs}/5] hair_style={hs} ({name}) ...")
|
||||
|
||||
vram_before, vram_free_before = get_vram()
|
||||
data, elapsed, error = call_iface2_female(GIRL_IMG, hs)
|
||||
vram_after, vram_free_after = get_vram()
|
||||
|
||||
code = data.get("code", -1) if data else -1
|
||||
ok = (code == 0)
|
||||
|
||||
# 保存生成图(如果有)
|
||||
img_path = None
|
||||
if ok and data.get("data"):
|
||||
try:
|
||||
items = data["data"].get("results") or []
|
||||
if items and isinstance(items, list):
|
||||
first = items[0]
|
||||
b64 = first.get("grown_image_base64") or ""
|
||||
if b64.startswith("data:"):
|
||||
b64 = b64.split(",", 1)[1]
|
||||
if b64:
|
||||
img_path = os.path.join(OUT_DIR, f"hair_style_{hs}_{name}.jpg")
|
||||
with open(img_path, "wb") as f:
|
||||
f.write(base64.b64decode(b64))
|
||||
except Exception as e:
|
||||
print(f" 保存图片失败: {e}")
|
||||
|
||||
record = {
|
||||
"plan": PLAN_TAG,
|
||||
"hair_style": hs,
|
||||
"hair_style_name": name,
|
||||
"timestamp": datetime.now().strftime("%H:%M:%S"),
|
||||
"elapsed_s": round(elapsed, 2),
|
||||
"success": ok,
|
||||
"code": code,
|
||||
"error": error,
|
||||
"vram_before_mb": vram_before,
|
||||
"vram_after_mb": vram_after,
|
||||
"vram_delta_mb": vram_after - vram_before,
|
||||
"image_path": img_path,
|
||||
}
|
||||
results.append(record)
|
||||
|
||||
status = "✓" if ok else "✗"
|
||||
print(f" → {status} code={code} time={elapsed:.1f}s "
|
||||
f"vram={vram_before}→{vram_after}MB (Δ{vram_after-vram_before:+d}) "
|
||||
f"img={'saved' if img_path else 'none'}")
|
||||
|
||||
with open(RESULT_JSON, "w") as f:
|
||||
json.dump(results, f, indent=2, ensure_ascii=False)
|
||||
generate_html(results)
|
||||
|
||||
generate_html(results)
|
||||
print(f"\n✅ 完成!{RESULT_JSON}")
|
||||
print(f"📄 报告:{REPORT_HTML}")
|
||||
|
||||
|
||||
def generate_html(results):
|
||||
total = len(results)
|
||||
success = sum(1 for r in results if r["success"])
|
||||
times = [r["elapsed_s"] for r in results if r["success"]]
|
||||
avg_time = sum(times) / len(times) if times else 0
|
||||
|
||||
html = f"""<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="UTF-8"><title>接口2女5种发型 - Plan {PLAN_TAG}</title>
|
||||
<style>
|
||||
*{{margin:0;padding:0;box-sizing:border-box}}
|
||||
body{{font-family:sans-serif;background:#1a1a2e;color:#e0e0e0;padding:20px}}
|
||||
h1{{text-align:center;color:#00d4ff;margin-bottom:10px}}
|
||||
.subtitle{{text-align:center;color:#888;margin-bottom:30px;font-size:14px}}
|
||||
.summary{{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:15px;margin-bottom:30px}}
|
||||
.card{{background:#16213e;border-radius:12px;padding:20px;text-align:center;border:1px solid #333}}
|
||||
.card .num{{font-size:28px;font-weight:700}}
|
||||
.card .label{{font-size:12px;color:#888;margin-top:5px}}
|
||||
.card.ok .num{{color:#0f0}} .card.err .num{{color:#f44}} .card.time .num{{color:#00d4ff}}
|
||||
table{{width:100%;border-collapse:collapse;margin-bottom:30px;background:#16213e;border-radius:12px;overflow:hidden}}
|
||||
th{{background:#0f3460;padding:10px 8px;text-align:center;font-size:13px;color:#fff}}
|
||||
td{{padding:8px;text-align:center;border-bottom:1px solid #222;font-size:13px}}
|
||||
tr:hover{{background:#1a1a3e}}
|
||||
.section-title{{font-size:18px;font-weight:600;margin:30px 0 15px;color:#00d4ff;border-bottom:1px solid #333;padding-bottom:10px}}
|
||||
.ok{{color:#0f0}} .fail{{color:#f44}}
|
||||
.time-bar{{display:inline-block;height:18px;background:linear-gradient(90deg,#0f3460,#00d4ff);border-radius:3px;vertical-align:middle;min-width:2px}}
|
||||
.gallery{{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px}}
|
||||
.gallery img{{width:100%;border-radius:8px;border:1px solid #333}}
|
||||
.gallery .item{{text-align:center}}
|
||||
.gallery .cap{{margin-top:5px;font-size:12px;color:#888}}
|
||||
</style></head><body>
|
||||
<h1>📊 接口2女性5种发型测试报告</h1>
|
||||
<div class="subtitle">Plan {PLAN_TAG} | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | {total} 次调用</div>
|
||||
<div class="summary">
|
||||
<div class="card ok"><div class="num">{success}</div><div class="label">成功</div></div>
|
||||
<div class="card err"><div class="num">{total-success}</div><div class="label">失败</div></div>
|
||||
<div class="card time"><div class="num">{avg_time:.1f}s</div><div class="label">平均耗时</div></div>
|
||||
</div>
|
||||
<div class="section-title">详细结果</div>
|
||||
<table><thead><tr><th>发型</th><th>名称</th><th>耗时</th><th>显存前</th><th>显存后</th><th>Δ</th><th>状态</th></tr></thead><tbody>
|
||||
"""
|
||||
for r in results:
|
||||
status = '<span class="ok">✓</span>' if r["success"] else f'<span class="fail">✗ {str(r.get("error",""))[:30]}</span>'
|
||||
html += f'<tr><td>style {r["hair_style"]}</td><td>{r["hair_style_name"]}</td>' \
|
||||
f'<td><div class="time-bar" style="width:{min(r["elapsed_s"]*15,200)}px"></div> {r["elapsed_s"]:.1f}s</td>' \
|
||||
f'<td>{r["vram_before_mb"]}MB</td><td>{r["vram_after_mb"]}MB</td>' \
|
||||
f'<td>{r["vram_delta_mb"]:+d}</td><td>{status}</td></tr>'
|
||||
|
||||
html += '</tbody></table>'
|
||||
|
||||
# 图片画廊
|
||||
saved = [r for r in results if r.get("image_path") and os.path.isfile(r["image_path"])]
|
||||
if saved:
|
||||
html += '<div class="section-title">生成图片</div><div class="gallery">'
|
||||
for r in saved:
|
||||
rel = os.path.relpath(r["image_path"], OUT_DIR)
|
||||
html += f'<div class="item"><img src="{rel}"><div class="cap">{r["hair_style_name"]} ({r["elapsed_s"]:.1f}s)</div></div>'
|
||||
html += '</div>'
|
||||
|
||||
html += '</body></html>'
|
||||
with open(REPORT_HTML, "w", encoding="utf-8") as f:
|
||||
f.write(html)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_test()
|
||||
@@ -1,43 +0,0 @@
|
||||
nohup: ignoring input
|
||||
9B vs 4B 对比测试 — Plan=A
|
||||
图片: ['girl1.jpg', 'girl7.jpg', 'girl13.jpg']
|
||||
发型: [(1, '椭圆'), (2, '花瓣'), (3, '心形'), (4, '直线'), (5, '波浪')]
|
||||
总调用: 15
|
||||
|
||||
[warmup] 预热请求 (girl13, style=1) ...
|
||||
warmup: 25.7s
|
||||
|
||||
[img1/3] girl1.jpg style=1(椭圆) ...
|
||||
→ ✓ code=0 time=9.4s vram=26207→29449MB (Δ+3242) img=saved
|
||||
[img1/3] girl1.jpg style=2(花瓣) ...
|
||||
→ ✓ code=0 time=10.5s vram=29449→26341MB (Δ-3108) img=saved
|
||||
[img1/3] girl1.jpg style=3(心形) ...
|
||||
→ ✓ code=0 time=10.5s vram=26341→26051MB (Δ-290) img=saved
|
||||
[img1/3] girl1.jpg style=4(直线) ...
|
||||
→ ✓ code=0 time=10.4s vram=26051→26257MB (Δ+206) img=saved
|
||||
[img1/3] girl1.jpg style=5(波浪) ...
|
||||
→ ✓ code=0 time=10.8s vram=26257→26319MB (Δ+62) img=saved
|
||||
[img2/3] girl7.jpg style=1(椭圆) ...
|
||||
→ ✓ code=0 time=7.9s vram=26319→28417MB (Δ+2098) img=saved
|
||||
[img2/3] girl7.jpg style=2(花瓣) ...
|
||||
→ ✓ code=0 time=7.8s vram=28417→28397MB (Δ-20) img=saved
|
||||
[img2/3] girl7.jpg style=3(心形) ...
|
||||
→ ✓ code=0 time=7.7s vram=28397→28409MB (Δ+12) img=saved
|
||||
[img2/3] girl7.jpg style=4(直线) ...
|
||||
→ ✓ code=0 time=8.2s vram=28409→26335MB (Δ-2074) img=saved
|
||||
[img2/3] girl7.jpg style=5(波浪) ...
|
||||
→ ✓ code=0 time=7.9s vram=26335→28419MB (Δ+2084) img=saved
|
||||
[img3/3] girl13.jpg style=1(椭圆) ...
|
||||
→ ✓ code=0 time=8.9s vram=28419→28835MB (Δ+416) img=saved
|
||||
[img3/3] girl13.jpg style=2(花瓣) ...
|
||||
→ ✓ code=0 time=9.1s vram=28835→28817MB (Δ-18) img=saved
|
||||
[img3/3] girl13.jpg style=3(心形) ...
|
||||
→ ✓ code=0 time=8.8s vram=28817→28795MB (Δ-22) img=saved
|
||||
[img3/3] girl13.jpg style=4(直线) ...
|
||||
→ ✓ code=0 time=8.8s vram=28795→28845MB (Δ+50) img=saved
|
||||
[img3/3] girl13.jpg style=5(波浪) ...
|
||||
→ ✓ code=0 time=9.0s vram=28845→26291MB (Δ-2554) img=saved
|
||||
|
||||
✅ 完成!/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/results.json
|
||||
📊 成功: 15/15
|
||||
⏱ 平均: 9.06s
|
||||
|
Before Width: | Height: | Size: 219 KiB |
|
Before Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 221 KiB |
|
Before Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 156 KiB |
@@ -1,257 +0,0 @@
|
||||
[
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "14:04:32",
|
||||
"elapsed_s": 9.41,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 26207,
|
||||
"vram_after_mb": 29449,
|
||||
"vram_delta_mb": 3242,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img1_style1.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "14:04:42",
|
||||
"elapsed_s": 10.51,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 29449,
|
||||
"vram_after_mb": 26341,
|
||||
"vram_delta_mb": -3108,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img1_style2.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "14:04:53",
|
||||
"elapsed_s": 10.49,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 26341,
|
||||
"vram_after_mb": 26051,
|
||||
"vram_delta_mb": -290,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img1_style3.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "14:05:03",
|
||||
"elapsed_s": 10.45,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 26051,
|
||||
"vram_after_mb": 26257,
|
||||
"vram_delta_mb": 206,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img1_style4.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "14:05:14",
|
||||
"elapsed_s": 10.85,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 26257,
|
||||
"vram_after_mb": 26319,
|
||||
"vram_delta_mb": 62,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img1_style5.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "14:05:22",
|
||||
"elapsed_s": 7.91,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 26319,
|
||||
"vram_after_mb": 28417,
|
||||
"vram_delta_mb": 2098,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img2_style1.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "14:05:30",
|
||||
"elapsed_s": 7.81,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28417,
|
||||
"vram_after_mb": 28397,
|
||||
"vram_delta_mb": -20,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img2_style2.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "14:05:38",
|
||||
"elapsed_s": 7.74,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28397,
|
||||
"vram_after_mb": 28409,
|
||||
"vram_delta_mb": 12,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img2_style3.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "14:05:46",
|
||||
"elapsed_s": 8.17,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28409,
|
||||
"vram_after_mb": 26335,
|
||||
"vram_delta_mb": -2074,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img2_style4.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "14:05:54",
|
||||
"elapsed_s": 7.92,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 26335,
|
||||
"vram_after_mb": 28419,
|
||||
"vram_delta_mb": 2084,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img2_style5.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "14:06:03",
|
||||
"elapsed_s": 8.95,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28419,
|
||||
"vram_after_mb": 28835,
|
||||
"vram_delta_mb": 416,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img3_style1.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "14:06:12",
|
||||
"elapsed_s": 9.07,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28835,
|
||||
"vram_after_mb": 28817,
|
||||
"vram_delta_mb": -18,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img3_style2.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "14:06:21",
|
||||
"elapsed_s": 8.82,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28817,
|
||||
"vram_after_mb": 28795,
|
||||
"vram_delta_mb": -22,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img3_style3.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "14:06:30",
|
||||
"elapsed_s": 8.84,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28795,
|
||||
"vram_after_mb": 28845,
|
||||
"vram_delta_mb": 50,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img3_style4.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "A",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "14:06:39",
|
||||
"elapsed_s": 8.96,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28845,
|
||||
"vram_after_mb": 26291,
|
||||
"vram_delta_mb": -2554,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_A/img3_style5.jpg"
|
||||
}
|
||||
]
|
||||
@@ -1,43 +0,0 @@
|
||||
nohup: ignoring input
|
||||
9B vs 4B 对比测试 — Plan=Bplus
|
||||
图片: ['girl1.jpg', 'girl7.jpg', 'girl13.jpg']
|
||||
发型: [(1, '椭圆'), (2, '花瓣'), (3, '心形'), (4, '直线'), (5, '波浪')]
|
||||
总调用: 15
|
||||
|
||||
[warmup] 预热请求 (girl13, style=1) ...
|
||||
warmup: 12.1s
|
||||
|
||||
[img1/3] girl1.jpg style=1(椭圆) ...
|
||||
→ ✓ code=0 time=7.7s vram=25531→28691MB (Δ+3160) img=saved
|
||||
[img1/3] girl1.jpg style=2(花瓣) ...
|
||||
→ ✓ code=0 time=8.8s vram=28691→28655MB (Δ-36) img=saved
|
||||
[img1/3] girl1.jpg style=3(心形) ...
|
||||
→ ✓ code=0 time=9.1s vram=28655→28651MB (Δ-4) img=saved
|
||||
[img1/3] girl1.jpg style=4(直线) ...
|
||||
→ ✓ code=0 time=8.7s vram=28651→28641MB (Δ-10) img=saved
|
||||
[img1/3] girl1.jpg style=5(波浪) ...
|
||||
→ ✓ code=0 time=8.8s vram=28641→28637MB (Δ-4) img=saved
|
||||
[img2/3] girl7.jpg style=1(椭圆) ...
|
||||
→ ✓ code=0 time=7.0s vram=28637→25539MB (Δ-3098) img=saved
|
||||
[img2/3] girl7.jpg style=2(花瓣) ...
|
||||
→ ✓ code=0 time=6.7s vram=25539→27599MB (Δ+2060) img=saved
|
||||
[img2/3] girl7.jpg style=3(心形) ...
|
||||
→ ✓ code=0 time=6.7s vram=27599→27597MB (Δ-2) img=saved
|
||||
[img2/3] girl7.jpg style=4(直线) ...
|
||||
→ ✓ code=0 time=7.0s vram=27597→25533MB (Δ-2064) img=saved
|
||||
[img2/3] girl7.jpg style=5(波浪) ...
|
||||
→ ✓ code=0 time=6.7s vram=25533→27585MB (Δ+2052) img=saved
|
||||
[img3/3] girl13.jpg style=1(椭圆) ...
|
||||
→ ✓ code=0 time=7.6s vram=27585→28023MB (Δ+438) img=saved
|
||||
[img3/3] girl13.jpg style=2(花瓣) ...
|
||||
→ ✓ code=0 time=7.8s vram=28023→27997MB (Δ-26) img=saved
|
||||
[img3/3] girl13.jpg style=3(心形) ...
|
||||
→ ✓ code=0 time=7.8s vram=27997→25557MB (Δ-2440) img=saved
|
||||
[img3/3] girl13.jpg style=4(直线) ...
|
||||
→ ✓ code=0 time=7.6s vram=25557→28011MB (Δ+2454) img=saved
|
||||
[img3/3] girl13.jpg style=5(波浪) ...
|
||||
→ ✓ code=0 time=7.8s vram=28011→28017MB (Δ+6) img=saved
|
||||
|
||||
✅ 完成!/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/results.json
|
||||
📊 成功: 15/15
|
||||
⏱ 平均: 7.72s
|
||||
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 145 KiB |
@@ -1,257 +0,0 @@
|
||||
[
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "14:08:20",
|
||||
"elapsed_s": 7.69,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25531,
|
||||
"vram_after_mb": 28691,
|
||||
"vram_delta_mb": 3160,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img1_style1.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "14:08:28",
|
||||
"elapsed_s": 8.77,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28691,
|
||||
"vram_after_mb": 28655,
|
||||
"vram_delta_mb": -36,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img1_style2.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "14:08:38",
|
||||
"elapsed_s": 9.07,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28655,
|
||||
"vram_after_mb": 28651,
|
||||
"vram_delta_mb": -4,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img1_style3.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "14:08:46",
|
||||
"elapsed_s": 8.73,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28651,
|
||||
"vram_after_mb": 28641,
|
||||
"vram_delta_mb": -10,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img1_style4.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 1,
|
||||
"image_name": "girl1.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl1.jpg",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "14:08:55",
|
||||
"elapsed_s": 8.81,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28641,
|
||||
"vram_after_mb": 28637,
|
||||
"vram_delta_mb": -4,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img1_style5.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "14:09:02",
|
||||
"elapsed_s": 7.04,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28637,
|
||||
"vram_after_mb": 25539,
|
||||
"vram_delta_mb": -3098,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img2_style1.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "14:09:09",
|
||||
"elapsed_s": 6.67,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25539,
|
||||
"vram_after_mb": 27599,
|
||||
"vram_delta_mb": 2060,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img2_style2.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "14:09:16",
|
||||
"elapsed_s": 6.73,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27599,
|
||||
"vram_after_mb": 27597,
|
||||
"vram_delta_mb": -2,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img2_style3.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "14:09:23",
|
||||
"elapsed_s": 6.96,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27597,
|
||||
"vram_after_mb": 25533,
|
||||
"vram_delta_mb": -2064,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img2_style4.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 2,
|
||||
"image_name": "girl7.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl7.jpg",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "14:09:29",
|
||||
"elapsed_s": 6.74,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25533,
|
||||
"vram_after_mb": 27585,
|
||||
"vram_delta_mb": 2052,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img2_style5.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "14:09:37",
|
||||
"elapsed_s": 7.62,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27585,
|
||||
"vram_after_mb": 28023,
|
||||
"vram_delta_mb": 438,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img3_style1.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "14:09:45",
|
||||
"elapsed_s": 7.84,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28023,
|
||||
"vram_after_mb": 27997,
|
||||
"vram_delta_mb": -26,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img3_style2.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "14:09:53",
|
||||
"elapsed_s": 7.83,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27997,
|
||||
"vram_after_mb": 25557,
|
||||
"vram_delta_mb": -2440,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img3_style3.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "14:10:00",
|
||||
"elapsed_s": 7.59,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25557,
|
||||
"vram_after_mb": 28011,
|
||||
"vram_delta_mb": 2454,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img3_style4.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"image_idx": 3,
|
||||
"image_name": "girl13.jpg",
|
||||
"image_path": "/home/ubuntu/hair/image/girl_img/girl13.jpg",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "14:10:08",
|
||||
"elapsed_s": 7.77,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28011,
|
||||
"vram_after_mb": 28017,
|
||||
"vram_delta_mb": 6,
|
||||
"saved_image_path": "/home/ubuntu/hair/benchmark_out/9b_vs_4b_Bplus/img3_style5.jpg"
|
||||
}
|
||||
]
|
||||
@@ -1,292 +0,0 @@
|
||||
nohup: ignoring input
|
||||
找到 19 张图片
|
||||
总计 95 次调用,已完成 0,剩余 95
|
||||
|
||||
[1/19] girl1.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.8s vram=22353→22353MB preview=✓ grown=✓
|
||||
|
||||
[1/19] girl1.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=13.7s vram=22353→22389MB preview=✓ grown=✓
|
||||
|
||||
[1/19] girl1.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=13.6s vram=22389→22375MB preview=✓ grown=✓
|
||||
|
||||
[1/19] girl1.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=14.0s vram=22375→22359MB preview=✓ grown=✓
|
||||
|
||||
[1/19] girl1.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=13.6s vram=22359→22393MB preview=✓ grown=✓
|
||||
|
||||
[2/19] girl10.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=9.6s vram=22393→22413MB preview=✓ grown=✓
|
||||
|
||||
[2/19] girl10.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=9.8s vram=22413→22397MB preview=✓ grown=✓
|
||||
|
||||
[2/19] girl10.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=9.8s vram=22397→22391MB preview=✓ grown=✓
|
||||
|
||||
[2/19] girl10.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=9.8s vram=22391→22393MB preview=✓ grown=✓
|
||||
|
||||
[2/19] girl10.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=9.8s vram=22393→22395MB preview=✓ grown=✓
|
||||
|
||||
[3/19] girl11.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=10.0s vram=22395→22421MB preview=✓ grown=✓
|
||||
|
||||
[3/19] girl11.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=10.3s vram=22421→22393MB preview=✓ grown=✓
|
||||
|
||||
[3/19] girl11.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=10.4s vram=22393→22375MB preview=✓ grown=✓
|
||||
|
||||
[3/19] girl11.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=10.4s vram=22375→22385MB preview=✓ grown=✓
|
||||
|
||||
[3/19] girl11.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=9.9s vram=22385→22389MB preview=✓ grown=✓
|
||||
|
||||
[4/19] girl12.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=13.0s vram=22389→22389MB preview=✓ grown=✓
|
||||
|
||||
[4/19] girl12.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=12.9s vram=22389→22385MB preview=✓ grown=✓
|
||||
|
||||
[4/19] girl12.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=12.9s vram=22385→22389MB preview=✓ grown=✓
|
||||
|
||||
[4/19] girl12.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=13.0s vram=22389→22389MB preview=✓ grown=✓
|
||||
|
||||
[4/19] girl12.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=13.3s vram=22389→22409MB preview=✓ grown=✓
|
||||
|
||||
[5/19] girl13.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.5s vram=22409→22365MB preview=✓ grown=✓
|
||||
|
||||
[5/19] girl13.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.2s vram=22365→22395MB preview=✓ grown=✓
|
||||
|
||||
[5/19] girl13.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.2s vram=22395→22421MB preview=✓ grown=✓
|
||||
|
||||
[5/19] girl13.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.4s vram=22421→22409MB preview=✓ grown=✓
|
||||
|
||||
[5/19] girl13.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.2s vram=22409→22431MB preview=✓ grown=✓
|
||||
|
||||
[6/19] girl14.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.5s vram=22431→22391MB preview=✓ grown=✓
|
||||
|
||||
[6/19] girl14.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.5s vram=22391→22375MB preview=✓ grown=✓
|
||||
|
||||
[6/19] girl14.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.5s vram=22375→22409MB preview=✓ grown=✓
|
||||
|
||||
[6/19] girl14.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.5s vram=22409→22359MB preview=✓ grown=✓
|
||||
|
||||
[6/19] girl14.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.5s vram=22359→22393MB preview=✓ grown=✓
|
||||
|
||||
[7/19] girl15.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.2s vram=22393→22385MB preview=✓ grown=✓
|
||||
|
||||
[7/19] girl15.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.3s vram=22385→22387MB preview=✓ grown=✓
|
||||
|
||||
[7/19] girl15.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.4s vram=22387→22357MB preview=✓ grown=✓
|
||||
|
||||
[7/19] girl15.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.3s vram=22357→22383MB preview=✓ grown=✓
|
||||
|
||||
[7/19] girl15.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.7s vram=22383→22387MB preview=✓ grown=✓
|
||||
|
||||
[8/19] girl16.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.2s vram=22387→22377MB preview=✓ grown=✓
|
||||
|
||||
[8/19] girl16.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.2s vram=22377→22359MB preview=✓ grown=✓
|
||||
|
||||
[8/19] girl16.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.2s vram=22359→22347MB preview=✓ grown=✓
|
||||
|
||||
[8/19] girl16.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.3s vram=22347→22367MB preview=✓ grown=✓
|
||||
|
||||
[8/19] girl16.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.4s vram=22367→22399MB preview=✓ grown=✓
|
||||
|
||||
[9/19] girl17.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=13.0s vram=22399→22403MB preview=✓ grown=✓
|
||||
|
||||
[9/19] girl17.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=13.0s vram=22403→22421MB preview=✓ grown=✓
|
||||
|
||||
[9/19] girl17.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=13.1s vram=22421→22381MB preview=✓ grown=✓
|
||||
|
||||
[9/19] girl17.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=13.1s vram=22381→22419MB preview=✓ grown=✓
|
||||
|
||||
[9/19] girl17.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=13.0s vram=22419→22399MB preview=✓ grown=✓
|
||||
|
||||
[10/19] girl18.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.6s vram=22399→22419MB preview=✓ grown=✓
|
||||
|
||||
[10/19] girl18.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.2s vram=22419→22383MB preview=✓ grown=✓
|
||||
|
||||
[10/19] girl18.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.4s vram=22383→22409MB preview=✓ grown=✓
|
||||
|
||||
[10/19] girl18.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.4s vram=22409→22375MB preview=✓ grown=✓
|
||||
|
||||
[10/19] girl18.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.3s vram=22375→22413MB preview=✓ grown=✓
|
||||
|
||||
[11/19] girl19.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.1s vram=22413→22385MB preview=✓ grown=✓
|
||||
|
||||
[11/19] girl19.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.1s vram=22385→22393MB preview=✓ grown=✓
|
||||
|
||||
[11/19] girl19.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.3s vram=22393→22387MB preview=✓ grown=✓
|
||||
|
||||
[11/19] girl19.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.2s vram=22387→22415MB preview=✓ grown=✓
|
||||
|
||||
[11/19] girl19.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.2s vram=22415→22405MB preview=✓ grown=✓
|
||||
|
||||
[12/19] girl2.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=13.1s vram=22405→22395MB preview=✓ grown=✓
|
||||
|
||||
[12/19] girl2.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=12.9s vram=22395→22387MB preview=✓ grown=✓
|
||||
|
||||
[12/19] girl2.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=12.9s vram=22387→22381MB preview=✓ grown=✓
|
||||
|
||||
[12/19] girl2.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=12.9s vram=22381→22387MB preview=✓ grown=✓
|
||||
|
||||
[12/19] girl2.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=12.9s vram=22387→22309MB preview=✓ grown=✓
|
||||
|
||||
[13/19] girl3.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=9.8s vram=22309→22381MB preview=✓ grown=✓
|
||||
|
||||
[13/19] girl3.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=9.8s vram=22381→22403MB preview=✓ grown=✓
|
||||
|
||||
[13/19] girl3.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=9.9s vram=22403→22419MB preview=✓ grown=✓
|
||||
|
||||
[13/19] girl3.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=9.9s vram=22419→22401MB preview=✓ grown=✓
|
||||
|
||||
[13/19] girl3.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=9.9s vram=22401→22385MB preview=✓ grown=✓
|
||||
|
||||
[14/19] girl4.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=10.2s vram=22385→22377MB preview=✓ grown=✓
|
||||
|
||||
[14/19] girl4.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=10.5s vram=22377→22387MB preview=✓ grown=✓
|
||||
|
||||
[14/19] girl4.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=10.0s vram=22387→22365MB preview=✓ grown=✓
|
||||
|
||||
[14/19] girl4.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=9.9s vram=22365→22371MB preview=✓ grown=✓
|
||||
|
||||
[14/19] girl4.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=10.0s vram=22371→22389MB preview=✓ grown=✓
|
||||
|
||||
[15/19] girl5.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=8.5s vram=22389→23903MB preview=✓ grown=✓
|
||||
|
||||
[15/19] girl5.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=8.6s vram=23903→23929MB preview=✓ grown=✓
|
||||
|
||||
[15/19] girl5.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=8.6s vram=23929→23925MB preview=✓ grown=✓
|
||||
|
||||
[15/19] girl5.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=8.7s vram=23925→23931MB preview=✓ grown=✓
|
||||
|
||||
[15/19] girl5.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=8.7s vram=23931→23951MB preview=✓ grown=✓
|
||||
|
||||
[16/19] girl6.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=8.4s vram=23951→23729MB preview=✓ grown=✓
|
||||
|
||||
[16/19] girl6.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=8.7s vram=23729→22377MB preview=✓ grown=✓
|
||||
|
||||
[16/19] girl6.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=8.4s vram=22377→23685MB preview=✓ grown=✓
|
||||
|
||||
[16/19] girl6.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=8.3s vram=23685→23731MB preview=✓ grown=✓
|
||||
|
||||
[16/19] girl6.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=8.4s vram=23731→23713MB preview=✓ grown=✓
|
||||
|
||||
[17/19] girl7.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=9.9s vram=23713→24481MB preview=✓ grown=✓
|
||||
|
||||
[17/19] girl7.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=10.1s vram=24481→24447MB preview=✓ grown=✓
|
||||
|
||||
[17/19] girl7.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=10.0s vram=24447→24481MB preview=✓ grown=✓
|
||||
|
||||
[17/19] girl7.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=10.0s vram=24481→24469MB preview=✓ grown=✓
|
||||
|
||||
[17/19] girl7.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=10.0s vram=24469→24475MB preview=✓ grown=✓
|
||||
|
||||
[18/19] girl8.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.4s vram=24475→24861MB preview=✓ grown=✓
|
||||
|
||||
[18/19] girl8.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.5s vram=24861→24823MB preview=✓ grown=✓
|
||||
|
||||
[18/19] girl8.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.3s vram=24823→22393MB preview=✓ grown=✓
|
||||
|
||||
[18/19] girl8.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.1s vram=22393→22389MB preview=✓ grown=✓
|
||||
|
||||
[18/19] girl8.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.1s vram=22389→22365MB preview=✓ grown=✓
|
||||
|
||||
[19/19] girl9.jpg → 椭圆形(1) ...
|
||||
→ HTTP code=0 time=11.9s vram=22365→22391MB preview=✓ grown=✓
|
||||
|
||||
[19/19] girl9.jpg → 花瓣形(2) ...
|
||||
→ HTTP code=0 time=11.9s vram=22391→22375MB preview=✓ grown=✓
|
||||
|
||||
[19/19] girl9.jpg → 心形(3) ...
|
||||
→ HTTP code=0 time=11.9s vram=22375→22391MB preview=✓ grown=✓
|
||||
|
||||
[19/19] girl9.jpg → 直线形(4) ...
|
||||
→ HTTP code=0 time=11.9s vram=22391→22371MB preview=✓ grown=✓
|
||||
|
||||
[19/19] girl9.jpg → 波浪形(5) ...
|
||||
→ HTTP code=0 time=11.8s vram=22371→22373MB preview=✓ grown=✓
|
||||
|
||||
✅ 完成!结果: /home/ubuntu/hair/benchmark_out/benchmark_results.json
|
||||
📄 报告: /home/ubuntu/hair/benchmark_out/benchmark_report.html
|
||||
📊 总调用: 95/95
|
||||
@@ -1,22 +0,0 @@
|
||||
nohup: ignoring input
|
||||
接口2女性5种发型测试 — Plan=B
|
||||
图片:/home/ubuntu/hair/image/girl_img/girl13.jpg
|
||||
|
||||
|
||||
[1/5] hair_style=1 (椭圆) ...
|
||||
→ ✓ code=0 time=8.7s vram=24981→25025MB (Δ+44) img=saved
|
||||
|
||||
[2/5] hair_style=2 (花瓣) ...
|
||||
→ ✓ code=0 time=8.4s vram=25025→27451MB (Δ+2426) img=saved
|
||||
|
||||
[3/5] hair_style=3 (心形) ...
|
||||
→ ✓ code=0 time=8.4s vram=27451→27431MB (Δ-20) img=saved
|
||||
|
||||
[4/5] hair_style=4 (直线) ...
|
||||
→ ✓ code=0 time=8.5s vram=27431→27433MB (Δ+2) img=saved
|
||||
|
||||
[5/5] hair_style=5 (波浪) ...
|
||||
→ ✓ code=0 time=8.4s vram=27433→27407MB (Δ-26) img=saved
|
||||
|
||||
✅ 完成!/home/ubuntu/hair/benchmark_out/iface2_female_B/results.json
|
||||
📄 报告:/home/ubuntu/hair/benchmark_out/iface2_female_B/report.html
|
||||
|
Before Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 150 KiB |
@@ -1,34 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="UTF-8"><title>接口2女5种发型 - Plan B</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:sans-serif;background:#1a1a2e;color:#e0e0e0;padding:20px}
|
||||
h1{text-align:center;color:#00d4ff;margin-bottom:10px}
|
||||
.subtitle{text-align:center;color:#888;margin-bottom:30px;font-size:14px}
|
||||
.summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:15px;margin-bottom:30px}
|
||||
.card{background:#16213e;border-radius:12px;padding:20px;text-align:center;border:1px solid #333}
|
||||
.card .num{font-size:28px;font-weight:700}
|
||||
.card .label{font-size:12px;color:#888;margin-top:5px}
|
||||
.card.ok .num{color:#0f0} .card.err .num{color:#f44} .card.time .num{color:#00d4ff}
|
||||
table{width:100%;border-collapse:collapse;margin-bottom:30px;background:#16213e;border-radius:12px;overflow:hidden}
|
||||
th{background:#0f3460;padding:10px 8px;text-align:center;font-size:13px;color:#fff}
|
||||
td{padding:8px;text-align:center;border-bottom:1px solid #222;font-size:13px}
|
||||
tr:hover{background:#1a1a3e}
|
||||
.section-title{font-size:18px;font-weight:600;margin:30px 0 15px;color:#00d4ff;border-bottom:1px solid #333;padding-bottom:10px}
|
||||
.ok{color:#0f0} .fail{color:#f44}
|
||||
.time-bar{display:inline-block;height:18px;background:linear-gradient(90deg,#0f3460,#00d4ff);border-radius:3px;vertical-align:middle;min-width:2px}
|
||||
.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px}
|
||||
.gallery img{width:100%;border-radius:8px;border:1px solid #333}
|
||||
.gallery .item{text-align:center}
|
||||
.gallery .cap{margin-top:5px;font-size:12px;color:#888}
|
||||
</style></head><body>
|
||||
<h1>📊 接口2女性5种发型测试报告</h1>
|
||||
<div class="subtitle">Plan B | 2026-07-18 13:52:20 | 5 次调用</div>
|
||||
<div class="summary">
|
||||
<div class="card ok"><div class="num">5</div><div class="label">成功</div></div>
|
||||
<div class="card err"><div class="num">0</div><div class="label">失败</div></div>
|
||||
<div class="card time"><div class="num">8.5s</div><div class="label">平均耗时</div></div>
|
||||
</div>
|
||||
<div class="section-title">详细结果</div>
|
||||
<table><thead><tr><th>发型</th><th>名称</th><th>耗时</th><th>显存前</th><th>显存后</th><th>Δ</th><th>状态</th></tr></thead><tbody>
|
||||
<tr><td>style 1</td><td>椭圆</td><td><div class="time-bar" style="width:130.65px"></div> 8.7s</td><td>24981MB</td><td>25025MB</td><td>+44</td><td><span class="ok">✓</span></td></tr><tr><td>style 2</td><td>花瓣</td><td><div class="time-bar" style="width:125.54999999999998px"></div> 8.4s</td><td>25025MB</td><td>27451MB</td><td>+2426</td><td><span class="ok">✓</span></td></tr><tr><td>style 3</td><td>心形</td><td><div class="time-bar" style="width:125.54999999999998px"></div> 8.4s</td><td>27451MB</td><td>27431MB</td><td>-20</td><td><span class="ok">✓</span></td></tr><tr><td>style 4</td><td>直线</td><td><div class="time-bar" style="width:127.5px"></div> 8.5s</td><td>27431MB</td><td>27433MB</td><td>+2</td><td><span class="ok">✓</span></td></tr><tr><td>style 5</td><td>波浪</td><td><div class="time-bar" style="width:126.0px"></div> 8.4s</td><td>27433MB</td><td>27407MB</td><td>-26</td><td><span class="ok">✓</span></td></tr></tbody></table><div class="section-title">生成图片</div><div class="gallery"><div class="item"><img src="hair_style_1_椭圆.jpg"><div class="cap">椭圆 (8.7s)</div></div><div class="item"><img src="hair_style_2_花瓣.jpg"><div class="cap">花瓣 (8.4s)</div></div><div class="item"><img src="hair_style_3_心形.jpg"><div class="cap">心形 (8.4s)</div></div><div class="item"><img src="hair_style_4_直线.jpg"><div class="cap">直线 (8.5s)</div></div><div class="item"><img src="hair_style_5_波浪.jpg"><div class="cap">波浪 (8.4s)</div></div></div></body></html>
|
||||
@@ -1,72 +0,0 @@
|
||||
[
|
||||
{
|
||||
"plan": "B",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "13:51:46",
|
||||
"elapsed_s": 8.71,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 24981,
|
||||
"vram_after_mb": 25025,
|
||||
"vram_delta_mb": 44,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_B/hair_style_1_椭圆.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "B",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "13:51:55",
|
||||
"elapsed_s": 8.37,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25025,
|
||||
"vram_after_mb": 27451,
|
||||
"vram_delta_mb": 2426,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_B/hair_style_2_花瓣.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "B",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "13:52:03",
|
||||
"elapsed_s": 8.37,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27451,
|
||||
"vram_after_mb": 27431,
|
||||
"vram_delta_mb": -20,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_B/hair_style_3_心形.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "B",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "13:52:11",
|
||||
"elapsed_s": 8.5,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27431,
|
||||
"vram_after_mb": 27433,
|
||||
"vram_delta_mb": 2,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_B/hair_style_4_直线.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "B",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "13:52:20",
|
||||
"elapsed_s": 8.4,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 27433,
|
||||
"vram_after_mb": 27407,
|
||||
"vram_delta_mb": -26,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_B/hair_style_5_波浪.jpg"
|
||||
}
|
||||
]
|
||||
@@ -1,22 +0,0 @@
|
||||
nohup: ignoring input
|
||||
接口2女性5种发型测试 — Plan=Bplus
|
||||
图片:/home/ubuntu/hair/image/girl_img/girl13.jpg
|
||||
|
||||
|
||||
[1/5] hair_style=1 (椭圆) ...
|
||||
→ ✓ code=0 time=7.9s vram=25875→25889MB (Δ+14) img=saved
|
||||
|
||||
[2/5] hair_style=2 (花瓣) ...
|
||||
→ ✓ code=0 time=8.0s vram=25889→28337MB (Δ+2448) img=saved
|
||||
|
||||
[3/5] hair_style=3 (心形) ...
|
||||
→ ✓ code=0 time=7.8s vram=28337→28355MB (Δ+18) img=saved
|
||||
|
||||
[4/5] hair_style=4 (直线) ...
|
||||
→ ✓ code=0 time=7.6s vram=28355→28333MB (Δ-22) img=saved
|
||||
|
||||
[5/5] hair_style=5 (波浪) ...
|
||||
→ ✓ code=0 time=8.3s vram=28333→25885MB (Δ-2448) img=saved
|
||||
|
||||
✅ 完成!/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/results.json
|
||||
📄 报告:/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/report.html
|
||||
|
Before Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 142 KiB |
@@ -1,34 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN"><head><meta charset="UTF-8"><title>接口2女5种发型 - Plan Bplus</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:sans-serif;background:#1a1a2e;color:#e0e0e0;padding:20px}
|
||||
h1{text-align:center;color:#00d4ff;margin-bottom:10px}
|
||||
.subtitle{text-align:center;color:#888;margin-bottom:30px;font-size:14px}
|
||||
.summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:15px;margin-bottom:30px}
|
||||
.card{background:#16213e;border-radius:12px;padding:20px;text-align:center;border:1px solid #333}
|
||||
.card .num{font-size:28px;font-weight:700}
|
||||
.card .label{font-size:12px;color:#888;margin-top:5px}
|
||||
.card.ok .num{color:#0f0} .card.err .num{color:#f44} .card.time .num{color:#00d4ff}
|
||||
table{width:100%;border-collapse:collapse;margin-bottom:30px;background:#16213e;border-radius:12px;overflow:hidden}
|
||||
th{background:#0f3460;padding:10px 8px;text-align:center;font-size:13px;color:#fff}
|
||||
td{padding:8px;text-align:center;border-bottom:1px solid #222;font-size:13px}
|
||||
tr:hover{background:#1a1a3e}
|
||||
.section-title{font-size:18px;font-weight:600;margin:30px 0 15px;color:#00d4ff;border-bottom:1px solid #333;padding-bottom:10px}
|
||||
.ok{color:#0f0} .fail{color:#f44}
|
||||
.time-bar{display:inline-block;height:18px;background:linear-gradient(90deg,#0f3460,#00d4ff);border-radius:3px;vertical-align:middle;min-width:2px}
|
||||
.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px}
|
||||
.gallery img{width:100%;border-radius:8px;border:1px solid #333}
|
||||
.gallery .item{text-align:center}
|
||||
.gallery .cap{margin-top:5px;font-size:12px;color:#888}
|
||||
</style></head><body>
|
||||
<h1>📊 接口2女性5种发型测试报告</h1>
|
||||
<div class="subtitle">Plan Bplus | 2026-07-18 13:50:43 | 5 次调用</div>
|
||||
<div class="summary">
|
||||
<div class="card ok"><div class="num">5</div><div class="label">成功</div></div>
|
||||
<div class="card err"><div class="num">0</div><div class="label">失败</div></div>
|
||||
<div class="card time"><div class="num">7.9s</div><div class="label">平均耗时</div></div>
|
||||
</div>
|
||||
<div class="section-title">详细结果</div>
|
||||
<table><thead><tr><th>发型</th><th>名称</th><th>耗时</th><th>显存前</th><th>显存后</th><th>Δ</th><th>状态</th></tr></thead><tbody>
|
||||
<tr><td>style 1</td><td>椭圆</td><td><div class="time-bar" style="width:119.10000000000001px"></div> 7.9s</td><td>25875MB</td><td>25889MB</td><td>+14</td><td><span class="ok">✓</span></td></tr><tr><td>style 2</td><td>花瓣</td><td><div class="time-bar" style="width:120.6px"></div> 8.0s</td><td>25889MB</td><td>28337MB</td><td>+2448</td><td><span class="ok">✓</span></td></tr><tr><td>style 3</td><td>心形</td><td><div class="time-bar" style="width:116.55px"></div> 7.8s</td><td>28337MB</td><td>28355MB</td><td>+18</td><td><span class="ok">✓</span></td></tr><tr><td>style 4</td><td>直线</td><td><div class="time-bar" style="width:114.6px"></div> 7.6s</td><td>28355MB</td><td>28333MB</td><td>-22</td><td><span class="ok">✓</span></td></tr><tr><td>style 5</td><td>波浪</td><td><div class="time-bar" style="width:123.89999999999999px"></div> 8.3s</td><td>28333MB</td><td>25885MB</td><td>-2448</td><td><span class="ok">✓</span></td></tr></tbody></table><div class="section-title">生成图片</div><div class="gallery"><div class="item"><img src="hair_style_1_椭圆.jpg"><div class="cap">椭圆 (7.9s)</div></div><div class="item"><img src="hair_style_2_花瓣.jpg"><div class="cap">花瓣 (8.0s)</div></div><div class="item"><img src="hair_style_3_心形.jpg"><div class="cap">心形 (7.8s)</div></div><div class="item"><img src="hair_style_4_直线.jpg"><div class="cap">直线 (7.6s)</div></div><div class="item"><img src="hair_style_5_波浪.jpg"><div class="cap">波浪 (8.3s)</div></div></div></body></html>
|
||||
@@ -1,72 +0,0 @@
|
||||
[
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"hair_style": 1,
|
||||
"hair_style_name": "椭圆",
|
||||
"timestamp": "13:50:11",
|
||||
"elapsed_s": 7.94,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25875,
|
||||
"vram_after_mb": 25889,
|
||||
"vram_delta_mb": 14,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/hair_style_1_椭圆.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"hair_style": 2,
|
||||
"hair_style_name": "花瓣",
|
||||
"timestamp": "13:50:19",
|
||||
"elapsed_s": 8.04,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25889,
|
||||
"vram_after_mb": 28337,
|
||||
"vram_delta_mb": 2448,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/hair_style_2_花瓣.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"hair_style": 3,
|
||||
"hair_style_name": "心形",
|
||||
"timestamp": "13:50:27",
|
||||
"elapsed_s": 7.77,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28337,
|
||||
"vram_after_mb": 28355,
|
||||
"vram_delta_mb": 18,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/hair_style_3_心形.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"hair_style": 4,
|
||||
"hair_style_name": "直线",
|
||||
"timestamp": "13:50:35",
|
||||
"elapsed_s": 7.64,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28355,
|
||||
"vram_after_mb": 28333,
|
||||
"vram_delta_mb": -22,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/hair_style_4_直线.jpg"
|
||||
},
|
||||
{
|
||||
"plan": "Bplus",
|
||||
"hair_style": 5,
|
||||
"hair_style_name": "波浪",
|
||||
"timestamp": "13:50:43",
|
||||
"elapsed_s": 8.26,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28333,
|
||||
"vram_after_mb": 25885,
|
||||
"vram_delta_mb": -2448,
|
||||
"image_path": "/home/ubuntu/hair/benchmark_out/iface2_female_Bplus/hair_style_5_波浪.jpg"
|
||||
}
|
||||
]
|
||||
@@ -1,562 +0,0 @@
|
||||
[
|
||||
{
|
||||
"round": 1,
|
||||
"test_id": "iface1",
|
||||
"test_name": "接口1-测量",
|
||||
"timestamp": "13:36:27",
|
||||
"elapsed_s": 0.37,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25303,
|
||||
"vram_after_mb": 25425,
|
||||
"vram_free_before_mb": 6818,
|
||||
"vram_free_after_mb": 6696,
|
||||
"vram_delta_mb": 122,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 12524,
|
||||
"298802": 1015
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 12524,
|
||||
"298802": 1137
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 1,
|
||||
"test_id": "iface2f",
|
||||
"test_name": "接口2-女-椭圆",
|
||||
"timestamp": "13:36:35",
|
||||
"elapsed_s": 7.54,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25425,
|
||||
"vram_after_mb": 25887,
|
||||
"vram_free_before_mb": 6696,
|
||||
"vram_free_after_mb": 6234,
|
||||
"vram_delta_mb": 462,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 12524,
|
||||
"298802": 1137
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 12492,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 1,
|
||||
"test_id": "iface2m",
|
||||
"test_name": "接口2-男-椭圆",
|
||||
"timestamp": "13:36:39",
|
||||
"elapsed_s": 4.11,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25887,
|
||||
"vram_after_mb": 28383,
|
||||
"vram_free_before_mb": 6234,
|
||||
"vram_free_after_mb": 3738,
|
||||
"vram_delta_mb": 2496,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 12492,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 1,
|
||||
"test_id": "iface3",
|
||||
"test_name": "接口3-B端生发",
|
||||
"timestamp": "13:36:42",
|
||||
"elapsed_s": 3.12,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28383,
|
||||
"vram_after_mb": 28415,
|
||||
"vram_free_before_mb": 3738,
|
||||
"vram_free_after_mb": 3706,
|
||||
"vram_delta_mb": 32,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 15020,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 2,
|
||||
"test_id": "iface1",
|
||||
"test_name": "接口1-测量",
|
||||
"timestamp": "13:36:42",
|
||||
"elapsed_s": 0.08,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28415,
|
||||
"vram_after_mb": 28415,
|
||||
"vram_free_before_mb": 3706,
|
||||
"vram_free_after_mb": 3706,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 15020,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 15020,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 2,
|
||||
"test_id": "iface2f",
|
||||
"test_name": "接口2-女-椭圆",
|
||||
"timestamp": "13:36:50",
|
||||
"elapsed_s": 7.51,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28415,
|
||||
"vram_after_mb": 28353,
|
||||
"vram_free_before_mb": 3706,
|
||||
"vram_free_after_mb": 3768,
|
||||
"vram_delta_mb": -62,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8522,
|
||||
"271640": 15020,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 2,
|
||||
"test_id": "iface2m",
|
||||
"test_name": "接口2-男-椭圆",
|
||||
"timestamp": "13:36:54",
|
||||
"elapsed_s": 4.0,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28353,
|
||||
"vram_after_mb": 28353,
|
||||
"vram_free_before_mb": 3768,
|
||||
"vram_free_after_mb": 3768,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 2,
|
||||
"test_id": "iface3",
|
||||
"test_name": "接口3-B端生发",
|
||||
"timestamp": "13:36:57",
|
||||
"elapsed_s": 3.27,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28353,
|
||||
"vram_after_mb": 28353,
|
||||
"vram_free_before_mb": 3768,
|
||||
"vram_free_after_mb": 3768,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 3,
|
||||
"test_id": "iface1",
|
||||
"test_name": "接口1-测量",
|
||||
"timestamp": "13:36:58",
|
||||
"elapsed_s": 0.07,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28353,
|
||||
"vram_after_mb": 28353,
|
||||
"vram_free_before_mb": 3768,
|
||||
"vram_free_after_mb": 3768,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 3,
|
||||
"test_id": "iface2f",
|
||||
"test_name": "接口2-女-椭圆",
|
||||
"timestamp": "13:37:05",
|
||||
"elapsed_s": 7.63,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28353,
|
||||
"vram_after_mb": 25855,
|
||||
"vram_free_before_mb": 3768,
|
||||
"vram_free_after_mb": 6266,
|
||||
"vram_delta_mb": -2498,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8492,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 12492,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 3,
|
||||
"test_id": "iface2m",
|
||||
"test_name": "接口2-男-椭圆",
|
||||
"timestamp": "13:37:09",
|
||||
"elapsed_s": 4.1,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25855,
|
||||
"vram_after_mb": 28351,
|
||||
"vram_free_before_mb": 6266,
|
||||
"vram_free_after_mb": 3770,
|
||||
"vram_delta_mb": 2496,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 12492,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 3,
|
||||
"test_id": "iface3",
|
||||
"test_name": "接口3-B端生发",
|
||||
"timestamp": "13:37:13",
|
||||
"elapsed_s": 3.13,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28351,
|
||||
"vram_after_mb": 28351,
|
||||
"vram_free_before_mb": 3770,
|
||||
"vram_free_after_mb": 3770,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 4,
|
||||
"test_id": "iface1",
|
||||
"test_name": "接口1-测量",
|
||||
"timestamp": "13:37:13",
|
||||
"elapsed_s": 0.07,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28351,
|
||||
"vram_after_mb": 28351,
|
||||
"vram_free_before_mb": 3770,
|
||||
"vram_free_after_mb": 3770,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 4,
|
||||
"test_id": "iface2f",
|
||||
"test_name": "接口2-女-椭圆",
|
||||
"timestamp": "13:37:20",
|
||||
"elapsed_s": 7.32,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28351,
|
||||
"vram_after_mb": 28337,
|
||||
"vram_free_before_mb": 3770,
|
||||
"vram_free_after_mb": 3784,
|
||||
"vram_delta_mb": -14,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 4,
|
||||
"test_id": "iface2m",
|
||||
"test_name": "接口2-男-椭圆",
|
||||
"timestamp": "13:37:24",
|
||||
"elapsed_s": 4.21,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28337,
|
||||
"vram_after_mb": 28337,
|
||||
"vram_free_before_mb": 3784,
|
||||
"vram_free_after_mb": 3784,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 4,
|
||||
"test_id": "iface3",
|
||||
"test_name": "接口3-B端生发",
|
||||
"timestamp": "13:37:28",
|
||||
"elapsed_s": 3.18,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28337,
|
||||
"vram_after_mb": 28337,
|
||||
"vram_free_before_mb": 3784,
|
||||
"vram_free_after_mb": 3784,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 5,
|
||||
"test_id": "iface1",
|
||||
"test_name": "接口1-测量",
|
||||
"timestamp": "13:37:28",
|
||||
"elapsed_s": 0.08,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28337,
|
||||
"vram_after_mb": 28337,
|
||||
"vram_free_before_mb": 3784,
|
||||
"vram_free_after_mb": 3784,
|
||||
"vram_delta_mb": 0,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": false
|
||||
},
|
||||
{
|
||||
"round": 5,
|
||||
"test_id": "iface2f",
|
||||
"test_name": "接口2-女-椭圆",
|
||||
"timestamp": "13:37:35",
|
||||
"elapsed_s": 7.43,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28337,
|
||||
"vram_after_mb": 25855,
|
||||
"vram_free_before_mb": 3784,
|
||||
"vram_free_after_mb": 6266,
|
||||
"vram_delta_mb": -2482,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8476,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 12492,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 5,
|
||||
"test_id": "iface2m",
|
||||
"test_name": "接口2-男-椭圆",
|
||||
"timestamp": "13:37:39",
|
||||
"elapsed_s": 4.07,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 25855,
|
||||
"vram_after_mb": 28351,
|
||||
"vram_free_before_mb": 6266,
|
||||
"vram_free_after_mb": 3770,
|
||||
"vram_delta_mb": 2496,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 12492,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
},
|
||||
{
|
||||
"round": 5,
|
||||
"test_id": "iface3",
|
||||
"test_name": "接口3-B端生发",
|
||||
"timestamp": "13:37:43",
|
||||
"elapsed_s": 3.11,
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"error": null,
|
||||
"vram_before_mb": 28351,
|
||||
"vram_after_mb": 28383,
|
||||
"vram_free_before_mb": 3770,
|
||||
"vram_free_after_mb": 3738,
|
||||
"vram_delta_mb": 32,
|
||||
"procs_before": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 14988,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_after": {
|
||||
"858": 3242,
|
||||
"24879": 8490,
|
||||
"271640": 15020,
|
||||
"298802": 1585
|
||||
},
|
||||
"procs_changed": true
|
||||
}
|
||||
]
|
||||
@@ -1,87 +0,0 @@
|
||||
nohup: ignoring input
|
||||
轮换测试:4 个接口 × 5 轮 = 20 次调用
|
||||
测试图片:/home/ubuntu/hair/image/girl_img/girl13.jpg
|
||||
|
||||
|
||||
============================================================
|
||||
第 1/5 轮
|
||||
============================================================
|
||||
|
||||
[1/5] 接口1-测量 ...
|
||||
→ ✓ code=0 time=0.4s vram=25303→25425MB (Δ+122) ⚠模型换出!
|
||||
|
||||
[1/5] 接口2-女-椭圆 ...
|
||||
→ ✓ code=0 time=7.5s vram=25425→25887MB (Δ+462) ⚠模型换出!
|
||||
|
||||
[1/5] 接口2-男-椭圆 ...
|
||||
→ ✓ code=0 time=4.1s vram=25887→28383MB (Δ+2496) ⚠模型换出!
|
||||
|
||||
[1/5] 接口3-B端生发 ...
|
||||
→ ✓ code=0 time=3.1s vram=28383→28415MB (Δ+32) ⚠模型换出!
|
||||
|
||||
============================================================
|
||||
第 2/5 轮
|
||||
============================================================
|
||||
|
||||
[2/5] 接口1-测量 ...
|
||||
→ ✓ code=0 time=0.1s vram=28415→28415MB (Δ+0)
|
||||
|
||||
[2/5] 接口2-女-椭圆 ...
|
||||
→ ✓ code=0 time=7.5s vram=28415→28353MB (Δ-62) ⚠模型换出!
|
||||
|
||||
[2/5] 接口2-男-椭圆 ...
|
||||
→ ✓ code=0 time=4.0s vram=28353→28353MB (Δ+0)
|
||||
|
||||
[2/5] 接口3-B端生发 ...
|
||||
→ ✓ code=0 time=3.3s vram=28353→28353MB (Δ+0)
|
||||
|
||||
============================================================
|
||||
第 3/5 轮
|
||||
============================================================
|
||||
|
||||
[3/5] 接口1-测量 ...
|
||||
→ ✓ code=0 time=0.1s vram=28353→28353MB (Δ+0)
|
||||
|
||||
[3/5] 接口2-女-椭圆 ...
|
||||
→ ✓ code=0 time=7.6s vram=28353→25855MB (Δ-2498) ⚠模型换出!
|
||||
|
||||
[3/5] 接口2-男-椭圆 ...
|
||||
→ ✓ code=0 time=4.1s vram=25855→28351MB (Δ+2496) ⚠模型换出!
|
||||
|
||||
[3/5] 接口3-B端生发 ...
|
||||
→ ✓ code=0 time=3.1s vram=28351→28351MB (Δ+0)
|
||||
|
||||
============================================================
|
||||
第 4/5 轮
|
||||
============================================================
|
||||
|
||||
[4/5] 接口1-测量 ...
|
||||
→ ✓ code=0 time=0.1s vram=28351→28351MB (Δ+0)
|
||||
|
||||
[4/5] 接口2-女-椭圆 ...
|
||||
→ ✓ code=0 time=7.3s vram=28351→28337MB (Δ-14) ⚠模型换出!
|
||||
|
||||
[4/5] 接口2-男-椭圆 ...
|
||||
→ ✓ code=0 time=4.2s vram=28337→28337MB (Δ+0)
|
||||
|
||||
[4/5] 接口3-B端生发 ...
|
||||
→ ✓ code=0 time=3.2s vram=28337→28337MB (Δ+0)
|
||||
|
||||
============================================================
|
||||
第 5/5 轮
|
||||
============================================================
|
||||
|
||||
[5/5] 接口1-测量 ...
|
||||
→ ✓ code=0 time=0.1s vram=28337→28337MB (Δ+0)
|
||||
|
||||
[5/5] 接口2-女-椭圆 ...
|
||||
→ ✓ code=0 time=7.4s vram=28337→25855MB (Δ-2482) ⚠模型换出!
|
||||
|
||||
[5/5] 接口2-男-椭圆 ...
|
||||
→ ✓ code=0 time=4.1s vram=25855→28351MB (Δ+2496) ⚠模型换出!
|
||||
|
||||
[5/5] 接口3-B端生发 ...
|
||||
→ ✓ code=0 time=3.1s vram=28351→28383MB (Δ+32) ⚠模型换出!
|
||||
|
||||
✅ 完成!/home/ubuntu/hair/benchmark_out/rotation/rotation_results.json
|
||||
📄 报告:/home/ubuntu/hair/benchmark_out/rotation/rotation_report.html
|
||||
|
Before Width: | Height: | Size: 213 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |