Spaces:
Running
Running
Update app.py
#1
by
BEfunnuga
- opened
app.py
CHANGED
@@ -20,9 +20,10 @@ client = Client(
|
|
20 |
|
21 |
def generate_outfit(model_image, garment_image, n_samples=1, n_steps=20, image_scale=2, seed=-1):
|
22 |
if model_image is None or garment_image is None:
|
|
|
23 |
return None, "Please upload both model and garment images"
|
24 |
-
|
25 |
-
max_retries = 3
|
26 |
for attempt in range(max_retries):
|
27 |
try:
|
28 |
# Use the client to predict
|
@@ -35,117 +36,132 @@ def generate_outfit(model_image, garment_image, n_samples=1, n_steps=20, image_s
|
|
35 |
seed=seed,
|
36 |
api_name="/process_hd"
|
37 |
)
|
38 |
-
|
39 |
-
#
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
except Exception as e:
|
53 |
error_msg = str(e)
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
if attempt < max_retries - 1:
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
61 |
else:
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
# Create Gradio interface
|
65 |
with gr.Blocks() as demo:
|
66 |
gr.Markdown("""
|
67 |
## Outfit Diffusion - Try On Virtual Outfits
|
68 |
|
69 |
-
⚠️ **Note**: This demo uses free GPU
|
70 |
-
-
|
71 |
-
-
|
72 |
-
-
|
73 |
|
74 |
-
|
75 |
""")
|
76 |
|
77 |
with gr.Row():
|
78 |
-
with gr.Column():
|
79 |
model_image = gr.Image(
|
80 |
-
label="
|
81 |
type="filepath",
|
82 |
-
height=
|
83 |
-
|
84 |
)
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
"https://levihsu-ootdiffusion.hf.space/file=/tmp/gradio/0089171df270f4532eec3d80a8f36cc8218c6840/01008_00.jpg"
|
90 |
-
]
|
91 |
-
gr.Examples(examples=model_examples, inputs=model_image)
|
92 |
|
93 |
garment_image = gr.Image(
|
94 |
-
label="
|
95 |
type="filepath",
|
96 |
-
height=
|
97 |
)
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
with gr.Column():
|
110 |
-
output_image = gr.Image(label="Generated Output")
|
111 |
-
error_text = gr.Markdown() # Add error display
|
112 |
-
|
113 |
with gr.Row():
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
image_scale = gr.Slider(
|
130 |
-
label="Scale (lower = faster, try 1-2)",
|
131 |
-
minimum=1,
|
132 |
-
maximum=5,
|
133 |
-
step=1,
|
134 |
-
value=1 # Reduced default
|
135 |
-
)
|
136 |
-
seed = gr.Number(
|
137 |
-
label="Random Seed (-1 for random)",
|
138 |
-
value=-1
|
139 |
-
)
|
140 |
-
|
141 |
-
generate_button = gr.Button("Generate Outfit")
|
142 |
|
143 |
# Set up the action for the button
|
144 |
generate_button.click(
|
145 |
fn=generate_outfit,
|
146 |
inputs=[model_image, garment_image, n_samples, n_steps, image_scale, seed],
|
147 |
-
outputs=[output_image, error_text]
|
148 |
)
|
149 |
|
150 |
-
# Launch the app
|
151 |
-
demo.launch()
|
|
|
20 |
|
21 |
def generate_outfit(model_image, garment_image, n_samples=1, n_steps=20, image_scale=2, seed=-1):
|
22 |
if model_image is None or garment_image is None:
|
23 |
+
# Return None for the image output and the error message for the text output
|
24 |
return None, "Please upload both model and garment images"
|
25 |
+
|
26 |
+
max_retries = 3 # You might want to adjust retries, but 3 is reasonable
|
27 |
for attempt in range(max_retries):
|
28 |
try:
|
29 |
# Use the client to predict
|
|
|
36 |
seed=seed,
|
37 |
api_name="/process_hd"
|
38 |
)
|
39 |
+
|
40 |
+
# --- Improved Result Handling ---
|
41 |
+
output_image_path = None
|
42 |
+
if isinstance(result, (list, tuple)) and len(result) > 0:
|
43 |
+
# Often results are tuples/lists; assume the image path is the first element
|
44 |
+
potential_path = result[0]
|
45 |
+
if isinstance(potential_path, str) and os.path.exists(potential_path): # Check if it looks like a valid path returned by the client
|
46 |
+
output_image_path = potential_path
|
47 |
+
elif isinstance(potential_path, dict) and 'image' in potential_path: # Handle dict case
|
48 |
+
output_image_path = potential_path['image']
|
49 |
+
|
50 |
+
elif isinstance(result, dict) and 'image' in result:
|
51 |
+
output_image_path = result['image']
|
52 |
+
elif isinstance(result, str) and os.path.exists(result): # Handle direct string path case
|
53 |
+
output_image_path = result
|
54 |
+
|
55 |
+
if output_image_path:
|
56 |
+
# Return the image path and None for the error message
|
57 |
+
return output_image_path, None
|
58 |
+
else:
|
59 |
+
# Log the unexpected result format for debugging if needed
|
60 |
+
print(f"Warning: Unexpected result format from API: {result}")
|
61 |
+
# Return None for image, and an informative error
|
62 |
+
return None, f"API returned unexpected format: {type(result)}"
|
63 |
+
# --- End Improved Result Handling ---
|
64 |
+
|
65 |
except Exception as e:
|
66 |
error_msg = str(e)
|
67 |
+
# Check for quota error specifically
|
68 |
+
if "exceeded your GPU quota" in error_msg or "queue is full" in error_msg.lower():
|
69 |
+
# Try to extract wait time, provide default if not found
|
70 |
+
wait_time_match = re.search(r'retry in (\d+:\d+:\d+|\d+\.?\d*\s*s)', error_msg) # Handle seconds too
|
71 |
+
wait_time_str = "an unknown period (try again in 5-10 mins)"
|
72 |
+
wait_seconds = 300 # Default 5 mins
|
73 |
+
|
74 |
+
if wait_time_match:
|
75 |
+
wait_time_str = wait_time_match.group(1)
|
76 |
+
try:
|
77 |
+
if 's' in wait_time_str:
|
78 |
+
wait_seconds = int(float(wait_time_str.replace('s','').strip()))
|
79 |
+
else:
|
80 |
+
# Convert HH:MM:SS to seconds
|
81 |
+
parts = list(map(int, wait_time_str.split(':')))
|
82 |
+
wait_seconds = sum(p * 60**i for i, p in enumerate(reversed(parts)))
|
83 |
+
except ValueError:
|
84 |
+
pass # Keep default wait_seconds
|
85 |
+
|
86 |
+
# Only sleep if it's not the last attempt
|
87 |
if attempt < max_retries - 1:
|
88 |
+
print(f"GPU/Queue issue detected. Waiting {wait_seconds} seconds before retry {attempt + 2}/{max_retries}...")
|
89 |
+
time.sleep(wait_seconds + 2) # Add a small buffer
|
90 |
+
continue # Go to the next attempt
|
91 |
+
else:
|
92 |
+
# Return None for image, and the specific quota error on last attempt
|
93 |
+
return None, f"GPU quota exceeded or queue full. Please wait ~{wait_time_str} before trying again."
|
94 |
else:
|
95 |
+
# For any other exception, return None for image and the general error message
|
96 |
+
print(f"An unexpected error occurred: {error_msg}") # Log the full error server-side
|
97 |
+
# Return a user-friendly error and None for the image path
|
98 |
+
return None, f"An error occurred processing the request. Details: {error_msg}"
|
99 |
+
|
100 |
+
# If all retries fail (e.g., due to persistent quota issues)
|
101 |
+
return None, "Failed to generate outfit after multiple retries due to server issues."
|
102 |
+
|
103 |
|
104 |
# Create Gradio interface
|
105 |
with gr.Blocks() as demo:
|
106 |
gr.Markdown("""
|
107 |
## Outfit Diffusion - Try On Virtual Outfits
|
108 |
|
109 |
+
⚠️ **Note**: This demo uses a free, shared GPU resource which has limits. Errors can occur due to high demand or temporary issues on the service.
|
110 |
+
- **Try lower settings:** Use Steps (e.g., 10-20) and Scale (e.g., 1-3) for faster processing and lower resource use.
|
111 |
+
- **Be patient:** If you get quota/queue errors, wait the suggested time before retrying.
|
112 |
+
- **Check the Space:** You can visit the [OOTDiffusion Space](https://huggingface.co/spaces/levihsu/OOTDiffusion) directly to check its status.
|
113 |
|
|
|
114 |
""")
|
115 |
|
116 |
with gr.Row():
|
117 |
+
with gr.Column(scale=1):
|
118 |
model_image = gr.Image(
|
119 |
+
label="Model Image (Person)",
|
120 |
type="filepath",
|
121 |
+
height=400 # Adjusted height slightly
|
|
|
122 |
)
|
123 |
+
# (Keep examples)
|
124 |
+
model_examples = [...]
|
125 |
+
gr.Examples(examples=model_examples, inputs=model_image, label="Model Examples")
|
126 |
+
|
|
|
|
|
|
|
127 |
|
128 |
garment_image = gr.Image(
|
129 |
+
label="Garment Image (Clothing)",
|
130 |
type="filepath",
|
131 |
+
height=400 # Adjusted height slightly
|
132 |
)
|
133 |
+
# (Keep examples)
|
134 |
+
garment_examples = [...]
|
135 |
+
gr.Examples(examples=garment_examples, inputs=garment_image, label="Garment Examples")
|
136 |
+
|
137 |
+
|
138 |
+
with gr.Column(scale=1): # Give equal space initially
|
139 |
+
output_image = gr.Image(label="Generated Output", height=400) # Match height
|
140 |
+
error_text = gr.Markdown(value="") # Display errors here, start empty
|
141 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
with gr.Row():
|
143 |
+
# Group controls together
|
144 |
+
n_samples = gr.Slider(
|
145 |
+
label="Number of Samples", minimum=1, maximum=4, step=1, value=1 # Max 4 recommended by space
|
146 |
+
)
|
147 |
+
n_steps = gr.Slider(
|
148 |
+
label="Steps", minimum=10, maximum=40, step=1, value=20 # Adjusted default/range
|
149 |
+
)
|
150 |
+
image_scale = gr.Slider(
|
151 |
+
label="Guidance Scale", minimum=1.0, maximum=5.0, step=0.5, value=2.0 # Adjusted default/range
|
152 |
+
)
|
153 |
+
seed = gr.Number(
|
154 |
+
label="Seed (-1 for random)", value=-1, precision=0 # Ensure integer seed
|
155 |
+
)
|
156 |
+
|
157 |
+
generate_button = gr.Button("Generate Outfit", variant="primary") # Make button stand out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
# Set up the action for the button
|
160 |
generate_button.click(
|
161 |
fn=generate_outfit,
|
162 |
inputs=[model_image, garment_image, n_samples, n_steps, image_scale, seed],
|
163 |
+
outputs=[output_image, error_text] # Map outputs correctly
|
164 |
)
|
165 |
|
166 |
+
# Launch the app with error visibility enabled
|
167 |
+
demo.launch(show_error=True, debug=True) # Added debug=True for potentially more local logs too
|