接口5:改为多选发型 + 每发型返回 middle/high/low 三档叠图(去掉 hairline_level 入参)
- 去掉 hairline_level 入参;middle/high/low 三档都返回
- 入参改为同接口2:gender + hair_style(逗号分隔多选,必填),缺失/越界返回 1007
- 每个选中发型返回 image_{middle,high,low}_base64 三档叠图 + grown_image_base64 生发图,
按发型分组;order = 发型序号,含 hairline_type
- 生发黑模板仍固定 middle(hairline_texture_black/),每发型 1 张生发图
- best_hairline_center_point 取首个选中发型的 middle 档
- 同步更新测试页(三档并排展示)、integration.html、stub_worker、接口文档/实现说明、test_api
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+27
-21
@@ -223,20 +223,22 @@ def _grow_from_texture(image_bgr: np.ndarray, ctx: dict, white_path: str | None,
|
||||
return None
|
||||
|
||||
|
||||
def generate_hairline_pngs(image_bgr: np.ndarray, gender: str, hairline_level: str = "middle",
|
||||
hair_styles: list[int] | None = None, use_mask: bool = True,
|
||||
def generate_hairline_pngs(image_bgr: np.ndarray, gender: str,
|
||||
hair_styles: list[int], use_mask: bool = True,
|
||||
prompt: str | None = None):
|
||||
"""接口5:该性别全部发际线叠图(同接口2预览) + 最佳(order1)发际线曲线的面部中间点,
|
||||
并对 hair_styles 选中的类型生发(同接口2)。
|
||||
"""接口5:对选中发型返回 middle/high/low 三档发际线叠图 + 生发图(同接口2)。
|
||||
|
||||
hairline_level:middle(默认)/high/low,选用不同档位的发际线贴图(仅影响叠图)。
|
||||
hair_styles(1-indexed 列表,按贴图排序):指定对哪些类型生发;None/[] 时不生发。
|
||||
生发黑模板固定取自 hairline_texture_black/(middle),与 hairline_level 无关。
|
||||
入参同接口2:先选 gender,再多选 hair_styles(必填,1-indexed 按贴图排序)。
|
||||
每个选中发型返回三档叠图(middle/high/low)与一张生发图;三档贴图同名,
|
||||
生发黑模板固定取自 hairline_texture_black/(middle),故生发目标固定 middle 档。
|
||||
use_mask/prompt:同接口2 的生发参数。
|
||||
Returns: {"images":[{hairline_type,order,image_bgr,grown_png}], "best_center":(x,y)};无人脸 None。
|
||||
Returns: {"images":[{hairline_type,order,overlays:{middle,high,low}(BGR),grown_png}],
|
||||
"best_center":(x,y)};无人脸 None。best_center 取首个选中发型的 middle 档。
|
||||
"""
|
||||
if gender not in ("male", "female"):
|
||||
raise ValueError(f"gender 必须是 male/female,收到 {gender!r}")
|
||||
if not hair_styles:
|
||||
raise ValueError("hair_styles 必填且不能为空")
|
||||
ctx = extract_context(image_bgr)
|
||||
if ctx is None:
|
||||
return None
|
||||
@@ -246,25 +248,29 @@ def generate_hairline_pngs(image_bgr: np.ndarray, gender: str, hairline_level: s
|
||||
# 面部中轴 x = 眉心(9/151 中点)
|
||||
face_cx = float((lm[9, 0] + lm[151, 0]) / 2 * w)
|
||||
|
||||
textures = get_texture_map(hairline_level)[gender]
|
||||
grow_set = set(hair_styles or [])
|
||||
# 三档贴图表(同性别、同 key 顺序,因三个文件夹同名)
|
||||
tex_by_level = {lv: get_texture_map(lv)[gender] for lv in _TEXTURE_DIRS}
|
||||
|
||||
# use_mask=False:干净原图+空遮罩与贴图无关,只跑一次 ComfyUI,选中项复用
|
||||
shared_grown = None
|
||||
if grow_set and not use_mask:
|
||||
if not use_mask:
|
||||
shared_grown = _grow_from_texture(image_bgr, ctx, None, use_mask=False, prompt=prompt)
|
||||
|
||||
images, best_center = [], None
|
||||
for order, (key, path) in enumerate(textures, start=1):
|
||||
white = load_texture_rgba(path)
|
||||
preview = render_hairline_overlay(image_bgr, ctx["points"], ext_faces, uv, white)
|
||||
grown_png = None
|
||||
if order in grow_set:
|
||||
grown_png = shared_grown if not use_mask else \
|
||||
_grow_from_texture(image_bgr, ctx, path, use_mask=True, prompt=prompt)
|
||||
images.append({"hairline_type": key, "order": order,
|
||||
"image_bgr": preview, "grown_png": grown_png})
|
||||
if order == 1: # 最佳发际线曲线的中点(面部中轴处的发际线 y)
|
||||
for s in hair_styles: # s = 1-indexed 发型序号
|
||||
key, mid_path = tex_by_level["middle"][s - 1]
|
||||
overlays = {}
|
||||
for lv in _TEXTURE_DIRS:
|
||||
white = load_texture_rgba(tex_by_level[lv][s - 1][1])
|
||||
overlays[lv] = render_hairline_overlay(image_bgr, 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)
|
||||
images.append({"hairline_type": key, "order": s,
|
||||
"overlays": overlays, "grown_png": grown_png})
|
||||
# best_center:首个选中发型的 middle 档发际线中点(面部中轴处的发际线 y)
|
||||
if best_center is None:
|
||||
white = load_texture_rgba(mid_path)
|
||||
overlay = build_overlay_layer(h, w, ctx["points"], ext_faces, uv, white)
|
||||
ys, xs = np.where(overlay[:, :, 3] > 40)
|
||||
if xs.size:
|
||||
|
||||
Reference in New Issue
Block a user