修改发型为最终发型

This commit is contained in:
xsl
2026-07-16 00:22:54 +08:00
parent a208fe88ec
commit 12f34c44f2
3 changed files with 87 additions and 7 deletions
+65
View File
@@ -20,11 +20,22 @@ from .render import load_ext_mesh, load_texture_rgba, render_hairline_overlay, b
from .mask import build_inpaint_mask, compose_comfy_rgba, mask_from_curve
from .marker_detect import detect_marker_hairline, path_to_curve_mask
import base64
import io
import logging
logger = logging.getLogger("hair.worker")
# 接口2 女性发型 key → change_hair hair_idchang_*)映射:换发型+Flux-2 整帧重绘用。
# 与接口12 final 的 5 型一一对应。
_FEMALE_KEY_TO_CHANG = {
"ellipse": "chang_tuoyuan", # 椭圆
"flower": "chang_huaban", # 花瓣
"heart": "chang_xinxing", # 心形
"straight": "chang_zhixian", # 直线
"wave": "chang_bolang", # 波浪
}
_REPO = os.path.dirname(os.path.dirname(__file__))
_TEXTURE_DIR = os.path.join(_REPO, "hairline_texture")
_BLACK_TEXTURE_DIR = os.path.join(_REPO, "hairline_texture_black")
@@ -202,6 +213,60 @@ def generate_grow_results(image_bgr: np.ndarray, gender: str, use_mask: bool = T
return results
def generate_grow_results_swap(image_bgr: np.ndarray, hair_styles: list[int] | None,
redraw_defaults: dict):
"""接口2 女性专用:发际线透明叠图(同 generate_grow_results+ 换发型+Flux-2 整帧重绘图。
与 generate_grow_results 的差异仅在 grown 图的来源:这里对每个选中发型把 female key 映射到
change_hair 的 chang_* hair_id,调 face_analysis.hairline_grow.generate_hairline_redraw
(= 接口12 final 管线,参数用 redraw_defaults),取 `redraw_full`(整帧重绘)作为生发图。
overlay 仍是发际线曲线透明层(与 generate_grow_results 完全一致)。
Returns: list[dict] {"hairline_type","order","overlay","grown_png"(jpg bytes 或 None)}
无人脸返回 None。单个发型换发型/重绘失败时 grown_png=None,不抛异常。
"""
from face_analysis.hairline_grow import generate_hairline_redraw, NoFaceError
ctx = extract_context(image_bgr)
if ctx is None:
return None
uv, ext_faces = load_ext_mesh()
textures = get_texture_map()["female"] # [(key, path), ...] 已排序
if hair_styles is not None:
items = [(s, textures[s - 1]) for s in hair_styles]
else:
items = list(enumerate(textures, start=1))
results = []
h, w = image_bgr.shape[:2]
for order, (key, white_path) in items:
white = load_texture_rgba(white_path)
overlay = build_overlay_layer(h, w, ctx["points"], ext_faces, uv, white)
grown_png = None
chang_id = _FEMALE_KEY_TO_CHANG.get(key)
if chang_id is None:
logger.warning("接口2 换发型:female key=%s 无对应 chang_id,跳过生发图", key)
else:
try:
data = generate_hairline_redraw(image_bgr, chang_id, **redraw_defaults)
b64 = (data.get("steps") or {}).get("redraw_full_base64") or ""
if b64.startswith("data:"):
b64 = b64.split(",", 1)[1]
grown_png = base64.b64decode(b64) if b64 else None
if grown_png is None:
logger.warning("接口2 换发型:type=%s 整帧重绘为空(可能 ComfyUI 未生效)", key)
except NoFaceError:
logger.warning("接口2 换发型:type=%s 未检出人脸", key)
except Exception as e: # noqa: BLE001 单张失败不拖垮整请求
logger.warning("接口2 换发型图失败 type=%s%s", key, e)
results.append({"hairline_type": key, "order": order,
"overlay": overlay, "grown_png": grown_png})
return results
def _grow_from_texture(image_bgr: np.ndarray, ctx: dict, white_path: str | None,
use_mask: bool, prompt: str | None):
"""对单个发际线做生发(ComfyUI)。黑模板固定取 hairline_texture_black/middle),