Defter77 commited on
Commit
ee2f3a1
·
verified ·
1 Parent(s): f4987a4

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +254 -0
app.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import time
5
+ import requests
6
+ import gradio as gr
7
+ import numpy as np
8
+ from PIL import Image
9
+ import io
10
+ import base64
11
+ import spaces
12
+
13
+ # ComfyUI API endpoint
14
+ COMFY_API = "http://127.0.0.1:8188/api"
15
+ WORKFLOW_PATH = "/app/workflows/Workflow_12_11.json"
16
+
17
+ # Load the workflow template
18
+ try:
19
+ with open(WORKFLOW_PATH, "r") as f:
20
+ workflow_template = json.load(f)
21
+ print(f"Loaded workflow template from {WORKFLOW_PATH}")
22
+ except Exception as e:
23
+ print(f"Error loading workflow template: {str(e)}")
24
+ workflow_template = {}
25
+
26
+ def queue_prompt(prompt):
27
+ """Send a prompt to ComfyUI for processing"""
28
+ p = {"prompt": prompt}
29
+ try:
30
+ response = requests.post(f"{COMFY_API}/prompt", json=p)
31
+ return response.json()
32
+ except Exception as e:
33
+ print(f"Error queuing prompt: {str(e)}")
34
+ return {"error": str(e)}
35
+
36
+ def get_image(filename, subfolder, folder_type):
37
+ """Get an image from ComfyUI's output folder"""
38
+ try:
39
+ response = requests.get(f"{COMFY_API}/view?filename={filename}&subfolder={subfolder}&type={folder_type}")
40
+ return Image.open(io.BytesIO(response.content))
41
+ except Exception as e:
42
+ print(f"Error getting image {filename}: {str(e)}")
43
+ return None
44
+
45
+ def upload_image(image, filename):
46
+ """Upload an image to ComfyUI's input folder"""
47
+ try:
48
+ if isinstance(image, str): # Base64 string
49
+ image_data = base64.b64decode(image.split(",")[1])
50
+ files = {"image": (filename, image_data)}
51
+ else: # PIL Image or numpy array
52
+ if isinstance(image, np.ndarray):
53
+ image = Image.fromarray(image)
54
+
55
+ img_byte_arr = io.BytesIO()
56
+ image.save(img_byte_arr, format='PNG')
57
+ img_byte_arr.seek(0)
58
+ files = {"image": (filename, img_byte_arr.getvalue())}
59
+
60
+ response = requests.post(f"{COMFY_API}/upload/image", files=files)
61
+ return response.json()
62
+ except Exception as e:
63
+ print(f"Error uploading image: {str(e)}")
64
+ return {"error": str(e)}
65
+
66
+ def check_progress(prompt_id):
67
+ """Check the progress of a ComfyUI prompt"""
68
+ try:
69
+ response = requests.get(f"{COMFY_API}/history/{prompt_id}")
70
+ return response.json()
71
+ except Exception as e:
72
+ print(f"Error checking progress: {str(e)}")
73
+ return {"error": str(e)}
74
+
75
+ @spaces.GPU
76
+ def generate_avatar(player_image, pose_image, shirt_image, player_name, team_name, age_gender_bg, shirt_color, style):
77
+ """Generate a football player avatar using ComfyUI workflow"""
78
+ # Upload images to ComfyUI
79
+ player_upload = upload_image(player_image, "player.png")
80
+ pose_upload = upload_image(pose_image, "pose.png")
81
+ shirt_upload = upload_image(shirt_image, "shirt.png")
82
+
83
+ if "error" in player_upload or "error" in pose_upload or "error" in shirt_upload:
84
+ return None, f"Error uploading images: {player_upload.get('error', '')} {pose_upload.get('error', '')} {shirt_upload.get('error', '')}"
85
+
86
+ # Create a copy of the workflow template
87
+ workflow = workflow_template.copy()
88
+
89
+ # Update workflow nodes with our parameters
90
+ # Player image node
91
+ workflow["391"]["inputs"]["image"] = player_upload["name"]
92
+
93
+ # Pose image node
94
+ workflow["310"]["inputs"]["image"] = pose_upload["name"]
95
+
96
+ # Shirt image node
97
+ workflow["636"]["inputs"]["image"] = shirt_upload["name"]
98
+
99
+ # Player name node
100
+ workflow["471"]["inputs"]["string"] = f"_{player_name}"
101
+
102
+ # Team name node
103
+ workflow["667"]["inputs"]["string"] = team_name
104
+
105
+ # Age, gender, background prompt node
106
+ workflow["420"]["inputs"]["string"] = age_gender_bg
107
+
108
+ # Shirt color node
109
+ workflow["528"]["inputs"]["string"] = f"({shirt_color}:1.2) blank t-shirt, black shorts, "
110
+
111
+ # Style node
112
+ workflow["422"]["inputs"]["string"] = style
113
+
114
+ # Queue the prompt in ComfyUI
115
+ prompt_response = queue_prompt(workflow)
116
+
117
+ if "error" in prompt_response:
118
+ return None, f"Error queuing prompt: {prompt_response['error']}"
119
+
120
+ prompt_id = prompt_response["prompt_id"]
121
+
122
+ # Wait for the processing to complete
123
+ status = "Generating avatar..."
124
+ retries = 0
125
+ max_retries = 60 # 5 minutes timeout
126
+
127
+ while retries < max_retries:
128
+ time.sleep(5)
129
+ progress = check_progress(prompt_id)
130
+
131
+ if "error" in progress:
132
+ retries += 1
133
+ continue
134
+
135
+ if prompt_id in progress and len(progress[prompt_id]["outputs"]) > 0:
136
+ # Get the output image
137
+ for node_id, output in progress[prompt_id]["outputs"].items():
138
+ if node_id == "308" or node_id == "679": # Save Image nodes
139
+ image_filename = output.get("images", [{}])[0].get("filename", "")
140
+ if image_filename:
141
+ result_image = get_image(image_filename, "", "output")
142
+ masked_filename = output.get("images", [{}])[0].get("filename", "").replace(".png", "_Masked.png")
143
+ masked_image = get_image(masked_filename, "", "output")
144
+
145
+ # Return the masked image if available, otherwise the regular image
146
+ return masked_image if masked_image else result_image, "Avatar generated successfully!"
147
+
148
+ return None, "Completed, but couldn't find output image."
149
+
150
+ retries += 1
151
+ status = f"Generating avatar... (attempt {retries}/{max_retries})"
152
+
153
+ return None, "Timed out waiting for the avatar generation to complete."
154
+
155
+ def create_interface():
156
+ """Create the Gradio interface for the avatar generator"""
157
+ with gr.Blocks(title="Football Player Avatar Generator") as demo:
158
+ gr.Markdown("# Football Player Avatar Generator")
159
+ gr.Markdown("Create stylized football player avatars from photos")
160
+
161
+ with gr.Row():
162
+ with gr.Column():
163
+ player_image = gr.Image(label="Upload Player Photo", type="pil")
164
+
165
+ with gr.Row():
166
+ pose_image = gr.Image(label="Select Pose Template", type="pil")
167
+ shirt_image = gr.Image(label="Select Shirt Template", type="pil")
168
+
169
+ player_name = gr.Textbox(label="Player Name", value="Player")
170
+ team_name = gr.Textbox(label="Team Name", value="Kurjet")
171
+
172
+ age_gender_options = [
173
+ "9 year old boy with on light grey studio background, upper body portrait",
174
+ "10 year old boy with on light grey studio background, upper body portrait",
175
+ "adult man with on light grey studio background, upper body portrait",
176
+ "adult woman with on light grey studio background, upper body portrait"
177
+ ]
178
+ age_gender_bg = gr.Dropdown(label="Age, Gender & Background", choices=age_gender_options, value=age_gender_options[0])
179
+
180
+ shirt_color_options = ["black", "red", "blue", "green", "yellow", "white"]
181
+ shirt_color = gr.Dropdown(label="Shirt Color", choices=shirt_color_options, value="black")
182
+
183
+ style_options = [
184
+ "3d pixar character portrait, award winning, 3d animation, octane rendering",
185
+ "digital painting, detailed, concept art, smooth, sharp focus, illustration, trending on artstation",
186
+ "cartoon drawing, hand drawn, pencil on paper, sketch art",
187
+ "watercolor painting, beautiful, smooth, sharp focus, colorful, professional"
188
+ ]
189
+ style = gr.Dropdown(label="Art Style", choices=style_options, value=style_options[0])
190
+
191
+ generate_button = gr.Button("Generate Avatar", variant="primary")
192
+
193
+ with gr.Column():
194
+ output_image = gr.Image(label="Generated Avatar")
195
+ status_text = gr.Textbox(label="Status", interactive=False)
196
+
197
+ # Load default images for pose and shirt
198
+ try:
199
+ default_pose = Image.open("/app/ComfyUI/input/pose4.jpg")
200
+ default_shirt = Image.open("/app/ComfyUI/input/paita2.jpg")
201
+ pose_image.value = default_pose
202
+ shirt_image.value = default_shirt
203
+ except Exception as e:
204
+ print(f"Error loading default images: {str(e)}")
205
+
206
+ # Set up the button click event
207
+ generate_button.click(
208
+ fn=generate_avatar,
209
+ inputs=[player_image, pose_image, shirt_image, player_name, team_name, age_gender_bg, shirt_color, style],
210
+ outputs=[output_image, status_text]
211
+ )
212
+
213
+ # Add examples
214
+ if os.path.exists("/app/ComfyUI/input"):
215
+ example_images = []
216
+ for filename in os.listdir("/app/ComfyUI/input"):
217
+ if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
218
+ example_images.append(os.path.join("/app/ComfyUI/input", filename))
219
+
220
+ if example_images:
221
+ gr.Examples(
222
+ examples=[[img] for img in example_images[:3]],
223
+ inputs=[player_image]
224
+ )
225
+
226
+ return demo
227
+
228
+ # Check for ComfyUI server and launch the app
229
+ if __name__ == "__main__":
230
+ # Check if ComfyUI is running
231
+ retry_count = 0
232
+ max_retries = 5
233
+ comfy_running = False
234
+
235
+ while retry_count < max_retries and not comfy_running:
236
+ try:
237
+ response = requests.get(f"{COMFY_API}/system_stats")
238
+ if response.status_code == 200:
239
+ print("ComfyUI is running, starting Gradio interface...")
240
+ comfy_running = True
241
+ break
242
+ except:
243
+ pass
244
+
245
+ retry_count += 1
246
+ print(f"Waiting for ComfyUI to start... (attempt {retry_count}/{max_retries})")
247
+ time.sleep(10)
248
+
249
+ if not comfy_running:
250
+ print("WARNING: Could not connect to ComfyUI server. The application may not function correctly.")
251
+
252
+ # Create and launch the interface
253
+ demo = create_interface()
254
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False)