Files
change_cloth/http_app.py
T
2025-07-13 23:53:40 +08:00

311 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import uuid
import requests
from flask import Flask, request, jsonify
from urllib.parse import urlparse
import json
import base64
import time
from PIL import Image
from datetime import datetime
from volcenginesdkarkruntime import Ark
import shutil
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_FOLDER = os.path.join(APP_ROOT, 'static')
app = Flask(__name__)
client = Ark(
# 此为默认路径,您可根据业务所在地域进行配置
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 从环境变量中获取您的 API Key。此为默认方式,您可根据需要进行修改
# api_key=os.environ.get("ARK_API_KEY"),
api_key='14fc0280-fc65-462d-ac2d-50178c0212e3'
)
def GetPicDesc(img_url):
response = client.chat.completions.create(
# 指定您创建的方舟推理接入点 ID,此处已帮您修改为您的推理接入点 ID
model="doubao-1.5-vision-pro-250328",
messages=[
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": img_url
},
},
{"type": "text", "text": "图片是一件服装的照片,返回为json格式, 第一个字段'服装长度', 图片中的服装穿到正常人身上的长度会覆盖到人体的哪个部位, 只要答案, 选项有(胸、腰、跨、大腿、膝盖、小腿、脚踝、拖地、难以辨认). 第二个字段'衣袖',只要答案,选项有(短袖、长袖)"},
],
}
],
)
text = response.choices[0].message.content
print(text)
return text
def change(human_name, cloth_name, c_width, c_height, cloth_url):
json_str = GetPicDesc(cloth_url)
json_data = json.loads(json_str)
cloth_len = json_data['服装长度']
cloth_short = True
if '长袖' in json_data['衣袖']:
cloth_short = False
if cloth_len == '难以辨认':
return None, "get image type error"
queue = requests.get("http://localhost:8188/queue").json()
if queue["queue_running"] or queue["queue_pending"]:
return None, "cur gpu is busy"
with open('/home/szlc/code/ComfyUI/change_cloth/change_new.json', 'r', encoding='utf-8') as file:
prompt_text = file.read()
prompt = json.loads(prompt_text)
prompt["96"]["inputs"]["cloth_len"] = cloth_len
prompt["96"]["inputs"]["cloth_short"] = cloth_short
# prompt["99"]["inputs"]["width"] = int((c_width/c_height) * 1024)
#input cloth img
prompt["22"]["inputs"]["image"] = cloth_name
#input human img
prompt["61"]["inputs"]["image"] = human_name
#out put name
out_img_name = str(uuid.uuid4())[:8]
prompt["102"]["inputs"]["filename_prefix"] = out_img_name
p = {"prompt": prompt}
data = json.dumps(p).encode('utf-8')
response = requests.post("http://localhost:8188/prompt", data=data)
prompt_id = response.json()["prompt_id"]
# 2. 轮询队列,直到任务完成
while True:
queue = requests.get("http://localhost:8188/queue").json()
# print(queue)
if not queue["queue_running"] and not queue["queue_pending"]:
break # 队列为空,任务已完成
time.sleep(0.5) # 避免频繁请求
# 3. 从历史记录中获取结果
history = requests.get("http://localhost:8188/history").json()
# print("History:", history)
outputs = history[prompt_id]["outputs"]
for out in outputs:
if 'images' in outputs[out]:
for out_img in outputs[out]['images']:
if 'filename' in out_img:
out_img_file_name = out_img['filename']
if out_img_name in out_img_file_name:
return out_img_file_name, "success"
return None, "can not find output image"
def save_base64_image(base64_str, prefix):
"""
将base64字符串保存为图片文件
:param base64_str: 带有类型标识的base64字符串
:param prefix: 文件名前缀
:return: 保存的文件路径
"""
try:
# 分离base64头部和实际数据
header, data = base64_str.split(',', 1)
# 从头部获取文件扩展名
file_ext = ''
if 'image/png' in header:
file_ext = '.png'
elif 'image/jpeg' in header:
file_ext = '.jpg'
elif 'image/jpg' in header:
file_ext = '.jpg'
elif 'image/gif' in header:
file_ext = '.gif'
else:
file_ext = '.png' # 默认使用png
# 生成唯一文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
unique_id = str(uuid.uuid4())[:8]
filename = f"{prefix}_{timestamp}_{unique_id}{file_ext}"
filepath = os.path.join('/home/szlc/code/ComfyUI/change_cloth/static/imgs', filename)
# 解码并保存图片
with open(filepath, 'wb') as f:
f.write(base64.b64decode(data))
input_filepath = os.path.join('/home/szlc/code/ComfyUI/input', filename)
# 解码并保存图片
with open(input_filepath, 'wb') as f:
f.write(base64.b64decode(data))
return filename
except Exception as e:
print(f"Error saving image: {str(e)}")
return None
def get_image_dimensions(image_path):
try:
with Image.open(image_path) as img:
width, height = img.size
return width, height
except Exception as e:
print(f"Error: {e}")
return None
def image_to_base64(file_path, mime_type=None):
if mime_type is None:
extension = file_path.split('.')[-1].lower()
mime_types = {
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif',
'webp': 'image/webp',
'bmp': 'image/bmp'
}
mime_type = mime_types.get(extension, 'application/octet-stream')
# 读取文件内容并编码为Base64
with open(file_path, 'rb') as image_file:
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
# 组合成Data URI格式
return f"data:{mime_type};base64,{encoded_string}"
def process_change_cloth(human_filename, cloth_filename, output_format, img_url):
w,h = get_image_dimensions(f'/home/szlc/code/ComfyUI/input/{human_filename}')
out_put_name, msg = change(human_filename, cloth_filename, w, h, img_url)
if out_put_name == None:
print(f'Failed to change cloth {msg}')
return jsonify({"ret":-1, 'msg': f'Failed to change cloth {msg}'}), 200
image = Image.open(f'/home/szlc/code/ComfyUI/output/{out_put_name}')
jpg_name = out_put_name.replace(".png", ".jpg")
jpg_path_name = f'/home/szlc/code/ComfyUI/change_cloth/static/imgs/{jpg_name}'
image.save(jpg_path_name, quality=95)
if 'base64' in output_format:
return jsonify({
"ret":0,
"msg":"success",
"data":image_to_base64(jpg_path_name)
})
else:
return jsonify({
"ret":0,
"msg":"success",
"url":f"http://112.126.94.241:18888/static/imgs/{jpg_name}"
})
@app.route('/change_cloth_base64', methods=['POST'])
def change_cloth_base64():
# 获取参数
data = request.get_json()
if not data:
return jsonify({"ret":-1,'msg': 'No JSON data provided'}), 400
human_img = data.get('human_img')
cloth_img = data.get('cloth_img')
output_format = data.get('output_format')
if not human_img or not cloth_img:
return jsonify({"ret":-1, 'msg': 'Both human_img and cloth_img are required'}), 400
try:
# 保存人像图片
human_filename = save_base64_image(human_img, 'human')
if not human_filename:
return jsonify({"ret":-1, 'msg': 'Failed to save human image'}), 500
# 保存服装图片
cloth_filename = save_base64_image(cloth_img, 'cloth')
if not cloth_filename:
return jsonify({"ret":-1, 'msg': 'Failed to save cloth image'}), 500
img_url = f"http://112.126.94.241:18888/static/imgs/{cloth_filename}"
return process_change_cloth(human_filename, cloth_filename, output_format, img_url)
except Exception as e:
return jsonify({"ret":-1, 'error': str(e)}), 500
def get_file_extension(url_or_filename):
"""从 URL 或文件名中提取扩展名(如 .jpg、.png"""
# 处理 URL 情况(如 https://example.com/image.jpg?width=200
if url_or_filename.startswith(('http://', 'https://')):
parsed = urlparse(url_or_filename)
path = parsed.path
else:
path = url_or_filename
# 提取扩展名(转换为小写,去掉问号后的参数)
ext = os.path.splitext(path)[1].lower().split('?')[0]
return ext if ext else '.png' # 默认 PNG(如果无法提取)
def save_image_from_url(image_url):
"""从 URL 下载图片并保留原始格式"""
try:
response = requests.get(image_url, stream=True)
response.raise_for_status()
# 获取原始图片格式
ext = get_file_extension(image_url)
filename = f"{uuid.uuid4()}{ext}"
filepath = os.path.join('/home/szlc/code/ComfyUI/change_cloth/static/imgs', filename)
with open(filepath, "wb") as f:
for chunk in response.iter_content(1024):
f.write(chunk)
input_filepath = os.path.join('/home/szlc/code/ComfyUI/input', filename)
shutil.copy(filepath, input_filepath)
return filename
except Exception as e:
print(f"Error saving image from URL: {e}")
return None
@app.route('/change_cloth', methods=['POST'])
def change_cloth():
"""从 URL 下载图片"""
data = request.json
human_url = data.get("human_url")
if not human_url:
return jsonify({"error": "Missing 'human_url' parameter"}), 400
human_filename = save_image_from_url(human_url)
if not human_filename:
return jsonify({"error": "Failed to download or save human image"}), 500
cloth_url = data.get("cloth_url")
if not cloth_url:
return jsonify({"error": "Missing 'cloth_url' parameter"}), 400
cloth_filename = save_image_from_url(cloth_url)
if not cloth_filename:
return jsonify({"error": "Failed to download or save image"}), 500
output_format = data.get('output_format')
return process_change_cloth(human_filename, cloth_filename, output_format, cloth_url)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8888, debug=True)