- 端点 POST /api/v1/hairline/grow(app.py,纯新增,不影响接口1-5) - 编排模块 face_analysis/hairline_grow.py:复用接口9 遮罩 → HTTP 调 change_hair(8801) → 按遮罩贴回 - 双生成后端 gen_backend:swaphair(换发型LoRA) / hairgrow(区域生发inpaint) - swap_mode:ext_mask(接口9遮罩作换发型遮罩) / as_is;融合 feather/alpha_gradient/seamless - 参数全在测试页可调;可视化按算法文档4步:最终遮罩→生成全帧→严格贴回→接缝融合 - 附启停脚本 scripts/restart_if11_backends.sh、算法文档、测试图 注:change_hair 侧 swapHair 的 ext_mask/denoising_strength 改造在 change_hair 仓库,向后兼容。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
91 lines
3.4 KiB
Bash
Executable File
91 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 接口11(发际线生发)所需的 change_hair 后端服务启停脚本。
|
||
#
|
||
# webui(57860) + photo_service(32678) + hair_service_sd(8801)
|
||
# —— 不需要 ComfyUI。
|
||
#
|
||
# hair_service_sd 会被【强制重启】以加载接口11 的 ext_mask 改动;
|
||
# webui / photo_service 仅在未运行时才拉起(已在跑则不动,避免 webui 重新加载模型)。
|
||
#
|
||
# 用法:
|
||
# bash scripts/restart_if11_backends.sh # 确保三个服务就绪(强制重启 8801)
|
||
# bash scripts/restart_if11_backends.sh status # 只看状态
|
||
set -u
|
||
|
||
PROJ="/home/xsl/change_hair/project"
|
||
LOGDIR="$PROJ/logs"
|
||
PIDD="$LOGDIR/pids"
|
||
PY_SD="/home/xsl/miniconda3/envs/sdwebui/bin/python"
|
||
PY_PHOTO="/home/xsl/miniconda3/envs/py310/bin/python"
|
||
PY_HAIR="/home/xsl/miniconda3/envs/my_hair/bin/python"
|
||
mkdir -p "$LOGDIR" "$PIDD"
|
||
|
||
export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1
|
||
export CUDA_VISIBLE_DEVICES=0
|
||
export APP_WORKER_ID=1
|
||
|
||
port_up() { ss -ltn 2>/dev/null | grep -q ":$1 "; }
|
||
|
||
wait_port() { # $1=port $2=label $3=timeout_s
|
||
local p="$1" label="$2" to="${3:-90}" i=0
|
||
echo -n " 等待 $label (端口 $p) "
|
||
while [ "$i" -lt "$to" ]; do
|
||
if port_up "$p"; then echo " ✓ 就绪"; return 0; fi
|
||
echo -n "."; sleep 2; i=$((i+2))
|
||
done
|
||
echo " ✗ 超时(看日志:$LOGDIR/*.log)"; return 1
|
||
}
|
||
|
||
status() {
|
||
echo "=== 服务状态 $(date '+%H:%M:%S') ==="
|
||
for pair in "webui:57860" "photo_service:32678" "hair_service_sd:8801"; do
|
||
local name="${pair%%:*}" port="${pair##*:}"
|
||
if port_up "$port"; then echo " ✓ $name (端口 $port 就绪)"; else echo " ✗ $name (端口 $port 未监听)"; fi
|
||
done
|
||
echo " worker 8187: $(curl -s -m3 http://127.0.0.1:8187/health 2>/dev/null || echo '未响应')"
|
||
}
|
||
|
||
if [ "${1:-}" = "status" ]; then status; exit 0; fi
|
||
|
||
# 1) webui —— 仅未运行时启动(模型加载慢,别乱重启)
|
||
if pgrep -f "webui.py.*57860" >/dev/null; then
|
||
echo "webui 已在运行,跳过"
|
||
else
|
||
echo "启动 webui (57860)..."
|
||
( cd "$PROJ/onediff/stable-diffusion-webui" && \
|
||
HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 \
|
||
nohup "$PY_SD" webui.py --api --listen --xformers --port 57860 > "$LOGDIR/webui.log" 2>&1 & \
|
||
echo $! > "$PIDD/webui.pid" )
|
||
echo " webui PID=$(cat "$PIDD/webui.pid" 2>/dev/null)"
|
||
fi
|
||
|
||
# 2) photo_service —— 仅未运行时启动
|
||
if pgrep -f "lora_train_service_1.py" >/dev/null; then
|
||
echo "photo_service 已在运行,跳过"
|
||
else
|
||
echo "启动 photo_service (32678)..."
|
||
( cd "$PROJ/photo_service" && \
|
||
nohup "$PY_PHOTO" -u lora_train_service_1.py > "$LOGDIR/photo_service.log" 2>&1 & \
|
||
echo $! > "$PIDD/photo_service.pid" )
|
||
echo " photo_service PID=$(cat "$PIDD/photo_service.pid" 2>/dev/null)"
|
||
fi
|
||
|
||
# 3) hair_service_sd —— 强制重启(加载接口11 的 ext_mask 改动)
|
||
echo "强制重启 hair_service_sd (8801)..."
|
||
pkill -f "run_copy_cost_colorb64" 2>/dev/null
|
||
sleep 2
|
||
( cd "$PROJ/hair_service_sd" && \
|
||
nohup "$PY_HAIR" run_copy_cost_colorb64.py > "$LOGDIR/hair_service_if11.log" 2>&1 & \
|
||
echo $! > "$PIDD/hair_service.pid" )
|
||
echo " hair_service_sd PID=$(cat "$PIDD/hair_service.pid" 2>/dev/null)"
|
||
|
||
echo "--- 等待就绪 ---"
|
||
wait_port 57860 webui 180
|
||
wait_port 32678 photo_service 60
|
||
wait_port 8801 hair_service_sd 120
|
||
echo
|
||
status
|
||
echo
|
||
echo "提示:hair_service_sd 端口就绪后,模型可能还需几秒;日志出现 '[HAIR_INIT] All init done' 即完全可用:"
|
||
echo " tail -f $LOGDIR/hair_service_if11.log"
|