初始化换发型项目: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
+169
View File
@@ -0,0 +1,169 @@
import gradio as gr
import os,re
import numpy as np
import requests
import cv2
import base64
import json
from io import BytesIO
from PIL import Image
api_service_url = 'http://127.0.0.1:1234'
# api_service_url = 'http://i-2.gpushare.com:53412'
class ChangeFaceGui():
def __init__(self):
self.template_list = self.get_template_list()
self.user_dict = self.get_user_dict()
# self.tmp_dir = './tmp'
# if not os.path.exists(self.tmp_dir): os.makedirs(self.tmp_dir)
self.user_img_list = []
# 获取户图片
for item in self.user_dict:
response = requests.get(item['face_img_url'])
image_data = BytesIO(response.content)
user_face_img = cv2.imdecode(np.frombuffer(image_data.read(), np.uint8), cv2.IMREAD_COLOR)
self.user_img_list.append(user_face_img)
item['face_img'] = user_face_img
# img_path = f'{self.tmp_dir}/{item["user_id"]}.jpg'
# if not os.path.exists(img_path):
# cv2.imwrite(f'{self.tmp_dir}/{item["user_id"]}.jpg', user_face_img)
#请求得到模板图片的url
def get_template_list(self):
url = f"{api_service_url}/template/list"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print('请求模板照片成功!!')
return(response.json()['data'])
#请求得到用户图片及ID
def get_user_dict(self):
url = f"{api_service_url}/user/list"
payload = {}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
user_dict = response.json()['data']
print('请求用户照片成功!!')
return(user_dict)
#获取用户ID
def get_user_id(self, user_img):
user_small_img = cv2.resize(user_img, (100, 100))
mse = []
for item in self.user_dict:
user_face_img = item['face_img']
# cv2.imwrite(f'{self.tmp_dir}/{item["user_id"]}_list.jpg', user_face_img)
user_face_img = cv2.resize(user_face_img, (100, 100))
# 计算均方误差
mse.append(np.mean((user_small_img - user_face_img) ** 2))
# 找到均方差最小值对应的ID
user_id = mse.index(min(mse))
user_id = self.user_dict[user_id]['user_id']
print('用户ID:', user_id)
return user_id
#虚拟试穿模块,输入是模特图和衣服图,输出是虚拟试穿的结果
def take_photo(self, template_img, user_img):
# if not os.path.exists(self.tmp_dir):os.makedirs(self.tmp_dir)
if template_img is None or user_img is None:
return None
# 使用 Pillow 加载图像
template_img = Image.open(template_img)
user_img = Image.open(user_img)
# 将 Pillow 图像转换为 OpenCV 格式(BGR)
template_img = cv2.cvtColor(np.array(template_img), cv2.COLOR_RGB2BGR)
user_img = cv2.cvtColor(np.array(user_img), cv2.COLOR_RGB2BGR)
# 将模板图片转换为base64格式
retval, template_bytes = cv2.imencode('.jpg', template_img)
encoded_image = base64.b64encode(template_bytes).decode('utf-8')
user_id = self.get_user_id(user_img)
url = f"{api_service_url}/user/generate"
payload = json.dumps({
"user_id": user_id,
"base_img": encoded_image
})
headers = {
'Content-Type': 'application/json'
}
print('请求api_service.py发送请求!!')
response = requests.request("POST", url, headers=headers, data=payload)
print('请求api_service.py发送请求成功!!')
if response.status_code != 200:
raise RuntimeError(f"Failed to send request to API service. Status code: {response.status_code}")
ret_image_b64 = response.json().get('generate_photo_b64')
if ret_image_b64 is None:
raise RuntimeError(f"ret image failed!")
image_array = np.frombuffer(base64.b64decode(ret_image_b64), np.uint8)
result_image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
result_image = cv2.cvtColor(result_image, cv2.COLOR_BGR2RGB)
return result_image
def start_gui(self):
user_img_list = []
for item in self.user_img_list:
img = cv2.cvtColor(item, cv2.COLOR_BGR2RGB)
user_img_list.append(img)
with gr.Blocks() as demo:
with gr.Row():
gr.Markdown("# 数字力场效果展示")
# 换脸
with gr.Tab("数字写真"):
with gr.Row():
gr.Markdown("# 数字写真")
with gr.Row():
with gr.Column():
#选择模板
template_img = gr.Image(label="模版", sources='upload', min_width=384, width=384, height=384, type="filepath", value=self.template_list[0],interactive=True)
example_template = gr.Examples(
inputs=template_img,
examples_per_page=12,
examples= self.template_list)
with gr.Column():
# 选择用户
user_img = gr.Image(label="用户", sources='upload', min_width=384, width=384, height=384, type="filepath", value= user_img_list[0],interactive=False)
example_user = gr.Examples(
inputs=user_img,
examples_per_page=12,
examples=user_img_list)
with gr.Column():
output_img = gr.Image(label="结果展示", type="numpy", height=576, width=384)
with gr.Column():
run_button = gr.Button(value="提交")
run_button.click(self.take_photo, inputs=[template_img, user_img], outputs=[output_img])
# #换衣服
# with gr.Tab("换衣"):
# with gr.Row():
# gr.Markdown("# 换衣")
# text_button = gr.Button("提交")
# # 换发型
# with gr.Tab("换发型"):
# with gr.Row():
# gr.Markdown("# 换发型")
# text_button = gr.Button("提交")
demo.launch(server_name='0.0.0.0', server_port=8080)
if __name__ == '__main__':
demo = ChangeFaceGui()
demo.start_gui()