diff --git a/app.py b/app.py index f2542b3..e9b356d 100644 --- a/app.py +++ b/app.py @@ -960,6 +960,8 @@ async def face_features( `female`:1=ellipse,2=flower,3=heart,4=straight,5=wave;`male`:1=ellipse,2=inverse_arc,3=m,4=straight。 - 可选 `use_mask` / `prompt`:同接口2 的生发控制参数。 注:生发黑模板固定取 `hairline_texture_black/`(middle 档),即三档叠图分别用各自贴图、但生发目标固定 middle。 +- 可选 `generate_grow_image`(默认 `true`):是否生成生发效果图(ComfyUI 生发,全流程最耗时)。 + `false` 时跳过生发,各发型 `grown_image_*` 恒为 `null`,仅返回三档发际线叠图与中心点,大幅降低耗时。 **返回说明**: @@ -1038,6 +1040,7 @@ async def hairline_generate( 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的文本"), + generate_grow_image: bool = Form(default=True, description="是否生成生发效果图(ComfyUI 生发,最耗时)。默认 true 出图;false 时跳过生发,各发型 grown_image 恒为 null,仅返回三档发际线叠图与中心点"), ): if gender not in ("male", "female"): return err(1004, "gender 必填且只能为 male / female") @@ -1061,7 +1064,8 @@ async def hairline_generate( from hairline.service import generate_hairline_pngs res = await run_in_threadpool( - generate_hairline_pngs, image, gender, hair_styles, use_mask, prompt) + generate_hairline_pngs, image, gender, hair_styles, use_mask, prompt, + generate_grow_image=generate_grow_image) if res is None: return err(1001, "无法识别人像") diff --git a/hairline/service.py b/hairline/service.py index ed47300..6af259a 100644 --- a/hairline/service.py +++ b/hairline/service.py @@ -323,13 +323,16 @@ def _grow_from_texture(image_bgr: np.ndarray, ctx: dict, white_path: str | None, def generate_hairline_pngs(image_bgr: np.ndarray, gender: str, hair_styles: list[int], use_mask: bool = True, - prompt: str | None = None): + prompt: str | None = None, + generate_grow_image: bool = True): """接口5:对选中发型返回 middle/high/low 三档发际线透明叠图 + 生发图(同接口2)。 入参同接口2:先选 gender,再多选 hair_styles(必填,1-indexed 按贴图排序)。 每个选中发型返回三档叠图(middle/high/low,RGBA 透明层只含发际线曲线)与一张生发图; 三档贴图同名,生发黑模板固定取自 hairline_texture_black/(middle),故生发目标固定 middle 档。 use_mask/prompt:同接口2 的生发参数。 + generate_grow_image(默认 True):是否生成生发图(ComfyUI,最耗时)。False 时跳过生发, + 各发型 grown_png 恒为 None,可大幅降低耗时(仅留三档发际线叠图与中心点)。 Returns: {"images":[{hairline_type,order,overlays:{middle,high,low}((H,W,4) RGBA 透明层),grown_png}], "best_centers":{"middle":(x,y),"high":(x,y),"low":(x,y)}};无人脸 None。 best_centers 取首个选中发型三档各自的发际线中点。 @@ -351,8 +354,9 @@ def generate_hairline_pngs(image_bgr: np.ndarray, gender: str, tex_by_level = {lv: get_texture_map(lv)[gender] for lv in _TEXTURE_DIRS} # use_mask=False:干净原图+空遮罩与贴图无关,只跑一次 ComfyUI,选中项复用 + # generate_grow_image=False:完全跳过生发(最耗时),grown_png 恒为 None shared_grown = None - if not use_mask: + if generate_grow_image and not use_mask: shared_grown = _grow_from_texture(image_bgr, ctx, None, use_mask=False, prompt=prompt) def _center_of(overlay): @@ -371,9 +375,13 @@ def generate_hairline_pngs(image_bgr: np.ndarray, gender: str, for lv in _TEXTURE_DIRS: white = load_texture_rgba(tex_by_level[lv][s - 1][1]) overlays[lv] = build_overlay_layer(h, w, ctx["points"], ext_faces, uv, white) - # 生发:固定 middle 黑模板 - grown_png = shared_grown if not use_mask else \ - _grow_from_texture(image_bgr, ctx, mid_path, use_mask=True, prompt=prompt) + # 生发:固定 middle 黑模板(generate_grow_image=False 时跳过,恒 None) + if not generate_grow_image: + grown_png = None + elif not use_mask: + grown_png = shared_grown + else: + grown_png = _grow_from_texture(image_bgr, ctx, mid_path, use_mask=True, prompt=prompt) images.append({"hairline_type": key, "order": s, "overlays": overlays, "grown_png": grown_png}) # best_centers:首个选中发型三档(middle/high/low)发际线中点