Commit
·
2d28e96
1
Parent(s):
eb2b831
update UI and limit the image size
Browse files
app.py
CHANGED
|
@@ -185,6 +185,54 @@ def initialize_services():
|
|
| 185 |
import traceback
|
| 186 |
return f"❌ Failed to initialize services: {str(e)}\n{traceback.format_exc()}"
|
| 187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
@spaces.GPU(duration=120)
|
| 189 |
def process_image_upload(image, session_state, progress=gr.Progress()):
|
| 190 |
"""Process uploaded image and run hand reconstruction"""
|
|
@@ -205,16 +253,7 @@ def process_image_upload(image, session_state, progress=gr.Progress()):
|
|
| 205 |
time.sleep(2)
|
| 206 |
|
| 207 |
if hand_reconstructor is None:
|
| 208 |
-
return ("
|
| 209 |
-
gr.update(interactive=False),
|
| 210 |
-
None,
|
| 211 |
-
False,
|
| 212 |
-
False,
|
| 213 |
-
session_state)
|
| 214 |
-
|
| 215 |
-
# Skip processing if image is None (intermediate state during replacement)
|
| 216 |
-
if image is None:
|
| 217 |
-
return ("Waiting for image upload...",
|
| 218 |
gr.update(interactive=False),
|
| 219 |
None,
|
| 220 |
False,
|
|
@@ -875,7 +914,7 @@ def create_gradio_interface():
|
|
| 875 |
# Use only change event to handle all image updates (upload, drag-and-drop, example selection)
|
| 876 |
# This prevents duplicate processing that occurs when both upload and change events fire
|
| 877 |
input_image.change(
|
| 878 |
-
fn=
|
| 879 |
inputs=[input_image, session_state],
|
| 880 |
outputs=[recon_status, generate_btn, hand_data, detected_left, detected_right, session_state],
|
| 881 |
show_progress='full' # Show progress bar for reconstruction
|
|
|
|
| 185 |
import traceback
|
| 186 |
return f"❌ Failed to initialize services: {str(e)}\n{traceback.format_exc()}"
|
| 187 |
|
| 188 |
+
|
| 189 |
+
def validate_image_dimensions(image):
|
| 190 |
+
"""Validate image dimensions before GPU allocation.
|
| 191 |
+
Returns (is_valid, message)
|
| 192 |
+
"""
|
| 193 |
+
if image is None:
|
| 194 |
+
return True, "" # Allow None to pass through
|
| 195 |
+
|
| 196 |
+
# Handle PIL Image or numpy array
|
| 197 |
+
if isinstance(image, np.ndarray):
|
| 198 |
+
img_pil = Image.fromarray(image)
|
| 199 |
+
else:
|
| 200 |
+
img_pil = image
|
| 201 |
+
|
| 202 |
+
# Check dimensions: width must be >= height (landscape orientation)
|
| 203 |
+
width, height = img_pil.size
|
| 204 |
+
if width < height:
|
| 205 |
+
error_msg = f"❌ Please upload a landscape image (width ≥ height).\nCurrent image: {width}x{height} (portrait orientation)"
|
| 206 |
+
return False, error_msg
|
| 207 |
+
|
| 208 |
+
return True, ""
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def validate_and_process_wrapper(image, session_state, progress=gr.Progress()):
|
| 212 |
+
"""Wrapper function to validate image before GPU allocation"""
|
| 213 |
+
# Skip processing if image is None (intermediate state during replacement)
|
| 214 |
+
if image is None:
|
| 215 |
+
return ("Waiting for image upload...",
|
| 216 |
+
gr.update(interactive=False),
|
| 217 |
+
None,
|
| 218 |
+
False,
|
| 219 |
+
False,
|
| 220 |
+
session_state)
|
| 221 |
+
|
| 222 |
+
# Validate image dimensions BEFORE GPU allocation
|
| 223 |
+
is_valid, error_msg = validate_image_dimensions(image)
|
| 224 |
+
if not is_valid:
|
| 225 |
+
return (error_msg,
|
| 226 |
+
gr.update(interactive=False),
|
| 227 |
+
None,
|
| 228 |
+
False,
|
| 229 |
+
False,
|
| 230 |
+
session_state)
|
| 231 |
+
|
| 232 |
+
# If validation passes, proceed with GPU-intensive processing
|
| 233 |
+
return process_image_upload(image, session_state, progress)
|
| 234 |
+
|
| 235 |
+
|
| 236 |
@spaces.GPU(duration=120)
|
| 237 |
def process_image_upload(image, session_state, progress=gr.Progress()):
|
| 238 |
"""Process uploaded image and run hand reconstruction"""
|
|
|
|
| 253 |
time.sleep(2)
|
| 254 |
|
| 255 |
if hand_reconstructor is None:
|
| 256 |
+
return ("Services not initialized. Please wait for initialization to complete.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
gr.update(interactive=False),
|
| 258 |
None,
|
| 259 |
False,
|
|
|
|
| 914 |
# Use only change event to handle all image updates (upload, drag-and-drop, example selection)
|
| 915 |
# This prevents duplicate processing that occurs when both upload and change events fire
|
| 916 |
input_image.change(
|
| 917 |
+
fn=validate_and_process_wrapper,
|
| 918 |
inputs=[input_image, session_state],
|
| 919 |
outputs=[recon_status, generate_btn, hand_data, detected_left, detected_right, session_state],
|
| 920 |
show_progress='full' # Show progress bar for reconstruction
|