新增功能: - inpaint_mask.py: mask区域重绘服务(enhance/pure_inpaint两种模式) 严格只在mask区做SD inpainting,发丝自然化 - /inpaint 页面 + /api/inpaint 接口:画板手绘mask + 提示词编辑 + denoising可调 - enhance_hair.webui_img2img: 新增denoising_strength参数(原硬编码0.35) 羽化贴回优化(hair_swap_manual.py 步骤⑥): - feather_px(羽化范围)+ feather_alpha(羽化强度)拆分为两个独立参数 - 改为只羽化边缘(mask内部保持硬切,仅边缘带渐变) - 新增黑底羽化对比图(纯黑背景凸显边缘过渡) 其他改动: - OSS/COS密钥脱敏:改为可选import,未设环境变量时不崩溃 - manual页面:发型列表改为本次训练的8个(含hair_flow) - enhance二次增强:重绘区改为「原图头发∪手绘mask」并外扩10%+减发际线带3cm - 发型清单文档更新:179→180个可用发型(+hair_flow) 涉及文件: - 新增: inpaint_mask.py, inpaint.html - 修改: app.py, manual.html, hair_swap_manual.py, enhance_hair.py - 修改: oss_module.py, upload_oss.py, cos_module.py(密钥脱敏) - 文档: HAIRSTYLES_AVAILABLE.md, hairstyles_available.csv
65 lines
2.6 KiB
Python
65 lines
2.6 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""mask 区域重绘(inpainting)服务
|
||
|
||
两种模式(底层都是 webui img2img inpainting,严格只在mask区重绘):
|
||
1. enhance: 用 enhance_hair.webui_img2img(默认提示词=发丝增强,denoising默认0.35)
|
||
2. pure_inpaint: 纯SD inpainting(默认提示词=自然头发,denoising默认0.5)
|
||
|
||
严格只重绘 mask 区域:inpainting_fill=1(mask外保留原图)
|
||
"""
|
||
import cv2
|
||
import numpy as np
|
||
from utils import enhance_hair
|
||
|
||
|
||
def inpaint_mask(img, mask, prompt="", denoising_strength=0.5, mode="enhance"):
|
||
"""在 mask 区域做 SD inpainting 重绘。
|
||
|
||
参数:
|
||
img: 输入图 BGR
|
||
mask: 灰度mask,白色(255)=重绘区,与img同尺寸
|
||
prompt: 提示词(空则用模式默认值)
|
||
denoising_strength: 重绘强度 0~1
|
||
mode: "enhance" 或 "pure_inpaint"
|
||
|
||
返回:
|
||
result: 重绘后的图(mask区已重绘,其余保留原图)
|
||
info: 本次参数说明
|
||
"""
|
||
h, w = img.shape[:2]
|
||
|
||
# 归一化 mask(保证 0/255,尺寸一致)
|
||
if mask.shape[:2] != (h, w):
|
||
mask = cv2.resize(mask, (w, h), interpolation=cv2.INTER_NEAREST)
|
||
if mask.ndim == 3:
|
||
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
|
||
_, mask_bin = cv2.threshold(mask, 30, 255, cv2.THRESH_BINARY)
|
||
|
||
# 模式默认值
|
||
if not prompt:
|
||
if mode == "enhance":
|
||
prompt = "high quality, detailed natural hair strands, realistic hair texture, sharp focus, photorealistic"
|
||
else:
|
||
prompt = "natural realistic hair, soft hair strands, photorealistic, high quality, detailed"
|
||
|
||
# 统计 mask 区域占比
|
||
mask_ratio = float((mask_bin > 0).sum()) / mask_bin.size * 100
|
||
|
||
# 调用 enhance_hair.webui_img2img(底层是 inpainting,inpainting_fill=1 严格只在mask区重绘)
|
||
result = enhance_hair.webui_img2img(
|
||
img, mask_bin, prompt=prompt,
|
||
denoising_strength=denoising_strength
|
||
)
|
||
|
||
# webui 可能调整尺寸(调整到8的倍数),resize 回原图尺寸
|
||
if result.shape[:2] != (h, w):
|
||
result = cv2.resize(result, (w, h), interpolation=cv2.INTER_LANCZOS4)
|
||
|
||
# 双重保险:强制 mask 外区域用原图(虽然 inpainting_fill=1 已保证,再加一层确保严格)
|
||
mask_3c = (mask_bin > 0)[..., None]
|
||
result = np.where(mask_3c, result, img).astype(np.uint8)
|
||
|
||
info = (f"模式={mode},提示词=\"{prompt[:50]}...\",denoising={denoising_strength},"
|
||
f"mask区域={mask_ratio:.1f}%。严格只重绘mask区,其余保留原图。")
|
||
return result, mask_bin, info
|