初始化换发型项目:3个微服务代码 + 部署脚本

包含:
- hair_service_sd: 换发型/换发色算法服务 (端口 8801)
- photo_service: LoRA 训练调度服务 (端口 32678)
- stable-diffusion-webui: SD WebUI 推理服务 (端口 57860)
- kohya_ss_home: 训练环境代码
- meidaojia: 监控测试脚本
- setup.sh: 一键部署脚本 (conda环境恢复 + 配置生成 + 完整性检查)
- start_all_services.sh: 启动3个服务
- configure.ini.template: 路径模板化 (BASE_DIR自动推导)
- conda_envs/py310.yml: py310 环境定义

大文件 (weights/, models/, data/, conda_envs/*.tar.gz 等) 通过 .gitignore 排除,
由网盘单独上传。
This commit is contained in:
colomi
2026-07-11 18:11:49 +08:00
commit 0eb61f3e60
628 changed files with 120882 additions and 0 deletions
@@ -0,0 +1,86 @@
import os
import torch
from seg.networks.deeplabv3_plus import get_deeplabv3_plus
import numpy as np
import cv2
import time
from utils import landmark_processor
def label_to_mask(label_np):
label_np = label_np.astype(np.int32)[:, :, np.newaxis]
mask = np.zeros((label_np.shape[0], label_np.shape[1], 3), dtype=np.uint8)
for id, color in enumerate(label_map):
index = (label_np == id).all(axis=2)
mask[index] = color
return mask
label_map = [
[0, 0, 0], #
[128, 128, 128],
[255, 255, 255],
]
class Evaluator(object):
def __init__(self, gpu_id, output_img_size, nclass, seg_model_path=None):
self.device = torch.device('cuda:{}'.format(gpu_id) if gpu_id is not None else 'cpu')
# print("gpu_id: ", gpu_id)
# create network
self.model = get_deeplabv3_plus(backbone='xception', nclass=nclass)
model_path = os.path.join(seg_model_path)
self.model.load_state_dict(torch.load(model_path, map_location=lambda storage, loc: storage))
# print("seg device: ", self.model.device)
self.model.to(self.device)
self.model.eval()
# images = torch.randn((1, 3, 512, 512)).to(self.device)
# torch.onnx.export(self.model, images,
# "deeplabv3_hair512_360_0520_wl.onnx",
# verbose=True,
# opset_version=11,
# input_names=['data'],
# do_constant_folding=True,
# output_names=['output'])
# exit()
self.output_img_size = output_img_size
self.nclass = nclass
def process_data(self, img):
img = (img.astype(np.float32) / 255).transpose((2, 0, 1))
img = torch.from_numpy(img).unsqueeze(0)
return img
def eval(self, img, pts1k):
orig_h, orig_w, _ = img.shape
M1 = landmark_processor.get_transform_mat_hair(pts1k, self.output_img_size, ratio=0.28, h_ratio=0.3)
crop_img = cv2.warpAffine(img, M1, (self.output_img_size, self.output_img_size), flags=cv2.INTER_LANCZOS4)
crop_img = self.process_data(crop_img)
crop_img = crop_img.to(self.device)
with torch.no_grad():
# torch.cuda.synchronize()
outputs = self.model(crop_img)
pred = torch.argmax(outputs[0], 1)
pred = pred[0].detach().cpu().numpy()
predict = pred.astype(np.float32)
pred_mask = label_to_mask(predict)
M1_invert = cv2.invertAffineTransform(M1)
img_pred = cv2.warpAffine(pred_mask, M1_invert, (orig_w, orig_h), flags=cv2.INTER_CUBIC) #flags=cv2.INTER_NEAREST
orig_mask = img_pred.copy()
# show_concat = np.concatenate((img, orig_mask), axis=1)
# cv2.imshow("show_concat", show_concat)
# cv2.waitKey()
return orig_mask