Files
colomi 0eb61f3e60 初始化换发型项目: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 排除,
由网盘单独上传。
2026-07-11 18:11:49 +08:00

326 lines
12 KiB
Python

import pickle
import sys
import cv2
from PIL import Image
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import numpy as np
# define shader code
vertex_code='''
uniform float scale;
attribute vec2 position;
attribute vec4 color;
varying vec4 v_color;
attribute vec2 TexCoordIn;
varying vec2 TexCoordOut;
void main()
{
gl_Position = vec4(position*scale, 0.0, 1.0);
v_color = color;
TexCoordOut = TexCoordIn;
}'''
fragment_code='''
varying vec4 v_color;
varying vec2 TexCoordOut;
uniform sampler2D Texture;
uniform vec2 originPosition;
uniform vec2 targetPosition;
vec2 curveWarp(vec2 textureCoord, vec2 originPosition, vec2 targetPosition, float radius)
{
vec2 offset = vec2(0.0);
vec2 result = vec2(0.0);
vec2 direction = targetPosition - originPosition;
float infect = distance(textureCoord, originPosition)/radius;
infect = 1.0 - infect;
infect = clamp(infect, 0.0, 1.0);
offset = direction * infect;
result = textureCoord - offset;
return result;
}
void main()
{
vec2 coordinate = vec2(0.0);
float radius = 0.5;
coordinate = curveWarp(TexCoordOut,originPosition,targetPosition,radius);
gl_FragColor = v_color*0.000000000001 + texture2D(Texture, coordinate);
}'''
#define useful function
def display():
glClear(GL_COLOR_BUFFER_BIT)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
glutSwapBuffers()
def reshape(width,height):
glViewport(0, 0, width, height)
#step1 init the context
def init(img_path):
image = Image.open(img_path)
glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutCreateWindow('Hello world!')
glutReshapeWindow(image.width,image.height)
glutReshapeFunc(reshape)
glutDisplayFunc(display)
return image
#step 2
def initShaderProgram():
program = glCreateProgram()
vertex = glCreateShader(GL_VERTEX_SHADER)
fragment = glCreateShader(GL_FRAGMENT_SHADER)
# Set shaders source
glShaderSource(vertex, vertex_code)
glShaderSource(fragment, fragment_code)
# Compile shaders
glCompileShader(vertex)
glCompileShader(fragment)
fragSuccess = glGetShaderiv(fragment, GL_COMPILE_STATUS)
vertSuccess = glGetShaderiv(vertex, GL_COMPILE_STATUS)
print("vertext shader compile success [%s]" % (vertSuccess,))
print("fragment shader compile success [%s]" % (fragSuccess,))
if vertSuccess == 0:
print(glGetShaderInfoLog(vertex))
sys.exit(0)
if fragSuccess == 0:
print(glGetShaderInfoLog(fragment))
sys.exit(0)
glAttachShader(program, vertex)
glAttachShader(program, fragment)
glLinkProgram(program)
linksucc=glGetProgramiv(program, GL_LINK_STATUS)
print("link program success [%s]" % (linksucc,))
glUseProgram(program)
return program
#step 3.1 optional setup texture
def getTextureFromFile(image_file):
#convert file to bytes
image = image_file.transpose(Image.FLIP_TOP_BOTTOM)
image = image.convert("RGBA")
byteImage =np.array(list(image.getdata()), np.uint8)
#setup texture
texIndex=glGenTextures(1)
glEnable( GL_TEXTURE_2D )
glBindTexture(GL_TEXTURE_2D,texIndex)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
#make the texture the default
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texIndex, 0)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image.width,image.height,0,GL_RGBA,GL_UNSIGNED_BYTE,byteImage)
return texIndex
#step 4.1 optional get the image from BufferFrame
def saveImageFromFBO(width, height, output_img_path):
glReadBuffer(GL_COLOR_ATTACHMENT0)
glPixelStorei(GL_PACK_ALIGNMENT, 1)
data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE)
image = Image.new("RGB", (width, height), (0, 0, 0))
image.frombytes(data)
image = image.transpose(Image.FLIP_TOP_BOTTOM)
image.save(output_img_path)
#step 4 optional if need to OSR generate a BufferFrame
def setupSelfDefineFBO(program, image, data, output_img_path):
fbWidth, fbHeight = image.width, image.height
# Setup framebuffer
framebuffer = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer)
# # Setup colorbuffer
# colorbuffer = glGenRenderbuffers(1)
# glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer)
# glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, fbWidth, fbHeight)
# glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer)
# Setup depthbuffer
depthbuffer = glGenRenderbuffers (1)
glBindRenderbuffer (GL_RENDERBUFFER,depthbuffer)
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, image.width, image.height)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer)
#first init VBO, then other parameters
buffer = glGenBuffers(1) # Request a buffer slot from GPU
glBindBuffer(GL_ARRAY_BUFFER, buffer) # Make this buffer the default one
glBufferData(GL_ARRAY_BUFFER, data.nbytes, data, GL_DYNAMIC_DRAW) # Upload data
# Create texture to render to
# glBufferData(GL_FRAMEBUFFER, data.nbytes, data, GL_DYNAMIC_DRAW)
loc = glGetAttribLocation(program, "position") #get the index of the attribute in program
glEnableVertexAttribArray(loc) #allow this attribute decide by index can be use
stride = data.strides[0] #define how to read buffer
offset = ctypes.c_void_p(0) #define the offset where the data begin in buffer
glVertexAttribPointer(loc, 2, GL_FLOAT, False, stride, offset)
offset = ctypes.c_void_p(data.dtype["position"].itemsize)
loc = glGetAttribLocation(program, "color")
glEnableVertexAttribArray(loc)
glVertexAttribPointer(loc, 4, GL_FLOAT, False, stride, offset)
#setup other parameters
loc = glGetUniformLocation(program, "scale")
glUniform1f(loc, 1.0)
# originPosition = glGetUniformLocation(program, "originPosition")
# glUniform2f(originPosition, 0.5, 0.5)
#
# targetPosition = glGetUniformLocation(program, "targetPosition")
# glUniform2f(targetPosition, 0.47, 0.47)
# # glUniform2f(targetPosition, 0.5, 0.5)
# following code to bind uniform texture if needed
aTexture = getTextureFromFile(image)
glViewport(0, 0, fbWidth, fbHeight)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, aTexture)
loc = glGetUniformLocation(program, "Texture")
glUniform1i(loc, 0)
loc = glGetAttribLocation(program, "TexCoordIn")
glEnableVertexAttribArray(loc)
offset=ctypes.c_void_p(data.dtype["color"].itemsize+8)
glVertexAttribPointer(loc, 2, GL_FLOAT, False, stride, offset)
status = glCheckFramebufferStatus (GL_FRAMEBUFFER)
if status != GL_FRAMEBUFFER_COMPLETE:
print( "Error in framebuffer activation")
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
saveImageFromFBO(fbWidth, fbHeight, output_img_path)
glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE)
glDeleteTextures([aTexture])
glDeleteFramebuffers(1, [framebuffer])
print('save image from FBO success')
def pt_in_img(pt, img_w, img_h):
if pt[0] < 0 or pt[1] < 0 or pt[0] >= img_w or pt[1] >= img_h:
return False
else:
return True
def demo_test():
input_img_path = "../test_data/pics/female003.jpg"
output_img_path = "../tmp.png"
###### define vertex and color array
# data = np.zeros(4, dtype=[("position", np.float32, 2), ("color", np.float32, 4), ("textureCoord", np.float32, 2)])
# data['color'] = [(1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1)]
# # data['position'] = [(-1, -1), (-1, 1), (1, -1), (1, 1)]
# data['position'] = [(-1, -1), (-1, 1), (0, -1), (0, 1)]
# # data['textureCoord'] = [(0, 0), (0, 1), (1, 0), (1, 1)]
# data['textureCoord'] = [(0, 0), (0, 1), (1, 0), (0.5, 1)]
data = np.zeros(8, dtype=[("position", np.float32, 2), ("color", np.float32, 4), ("textureCoord", np.float32, 2)])
data['color'] = [(1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1)]
data['position'] = [(-1, -1), (-1, +1), (0, -1), (0, +1), (0, -1), (0, +1), (+1, -1), (+1, +1)]
# data['textureCoord'] = [(0, 0), (0, 1), (0.5, 0), (0.5, 1), (0.5, 0), (0.5, 1), (1, 0), (1, 1)]
mid_x = 0.6
data['textureCoord'] = [(0, 0), (0, 1), (mid_x, 0), (mid_x, 1), (mid_x, 0), (mid_x, 1), (1, 0), (1, 1)]
# data = np.zeros(3, dtype=[("position", np.float32, 2), ("color", np.float32, 4), ("textureCoord", np.float32, 2)])
# data['color'] = [(1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1)]
# data['position'] = [(-1, -1), (-1, +1), (1, -1)]
# # data['position'] = [(-1, -1), (1, 1), (1, -1)]
# data['textureCoord'] = [(0, 0), (0, 1), (0.5, 0)]
# # data['textureCoord'] = [(0, 0), (1, 1), (1, 0)]
# data = np.zeros(6, dtype=[("position", np.float32, 2), ("color", np.float32, 4), ("textureCoord", np.float32, 2)])
# data['color'] = [(1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1), (1, 1, 0, 1)]
# data['position'] = [(-1, -1), (-1, +1), (0, -1), (0, +1), (1, -1), (1, 1)]
# # data['textureCoord'] = [(0, 0), (0, 1), (0.5, 0), (0.5, 1), (1, 0), (1, 1)]
# data['textureCoord'] = [(0, 0), (0, 1), (0.5, 0), (0.5, 1), (1, 0), (1, 1)]
# mid_x = 0.4
# data['textureCoord'] = [(0, 0), (0, 1), (mid_x, 0), (mid_x, 1), (1, 0), (1, 1)]
image = init(input_img_path)
program = initShaderProgram()
setupSelfDefineFBO(program, image, data, output_img_path)
def demo_warp_pt137():
input_img_path = "../test_data/pics/female003.jpg"
output_img_path = "../tmp.png"
import pickle
with open("../test_render.pkl", "rb") as fp:
info = pickle.load(fp)
vertice = info["vertice"]
dst_vertice = info["dst_vertice"]
faces = info["faces"]
color_list = []
position_list = []
textureCoord_list = []
img = cv2.imread(input_img_path)
img_h, img_w, _ = img.shape
for i in range(len(faces)):
# print("index: ", faces[i])
pt1 = vertice[faces[i][0]]
pt2 = vertice[faces[i][1]]
pt3 = vertice[faces[i][2]]
dst_pt1 = dst_vertice[faces[i][0]]
dst_pt2 = dst_vertice[faces[i][1]]
dst_pt3 = dst_vertice[faces[i][2]]
# if pt1[0] != dst_pt1[0]:
# print("use warp!")
if pt_in_img(pt1, img_w, img_h) and pt_in_img(pt2, img_w, img_h) and pt_in_img(pt3, img_w, img_h):
color_list.append((1, 1, 0, 1))
color_list.append((1, 1, 0, 1))
color_list.append((1, 1, 0, 1))
position_list.append((dst_pt1[0] * 2 / img_w - 1, dst_pt1[1] * 2 / img_h - 1))
position_list.append((dst_pt2[0] * 2 / img_w - 1, dst_pt2[1] * 2 / img_h - 1))
position_list.append((dst_pt3[0] * 2 / img_w - 1, dst_pt3[1] * 2 / img_h - 1))
textureCoord_list.append((pt1[0] / img_w, pt1[1] / img_h))
textureCoord_list.append((pt2[0] / img_w, pt2[1] / img_h))
textureCoord_list.append((pt3[0] / img_w, pt3[1] / img_h))
data = np.zeros(len(color_list),
dtype=[("position", np.float32, 2), ("color", np.float32, 4), ("textureCoord", np.float32, 2)])
data['color'] = color_list
data['position'] = position_list
data['textureCoord'] = textureCoord_list
image = init(input_img_path)
program = initShaderProgram()
setupSelfDefineFBO(program, image, data, output_img_path)
if __name__ == '__main__':
demo_test()
# demo_warp_pt137()