Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -46,7 +46,17 @@ def resize_image(path, max_size=512):
|
|
| 46 |
return tmp.name
|
| 47 |
|
| 48 |
# ββ Run SHARP ββ
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
def run_sharp(image_path):
|
| 51 |
if image_path is None:
|
| 52 |
return None, "β Please upload a photo first."
|
|
@@ -56,7 +66,7 @@ def run_sharp(image_path):
|
|
| 56 |
resized = resize_image(image_path, 512)
|
| 57 |
result = subprocess.run(
|
| 58 |
["sharp", "predict", "-i", resized, "-o", out_dir],
|
| 59 |
-
capture_output=True, text=True, timeout=
|
| 60 |
)
|
| 61 |
ply_files = [f for f in os.listdir(out_dir) if f.endswith(".ply")]
|
| 62 |
if not ply_files:
|
|
@@ -64,7 +74,7 @@ def run_sharp(image_path):
|
|
| 64 |
return None, f"SHARP failed:\n{err}"
|
| 65 |
return os.path.join(out_dir, ply_files[0]), "β Done β 3D scene loading below β"
|
| 66 |
except subprocess.TimeoutExpired:
|
| 67 |
-
return None, "β Timed out.
|
| 68 |
except FileNotFoundError:
|
| 69 |
return None, "β SHARP not found yet β wait 1 minute and try again."
|
| 70 |
except Exception as e:
|
|
@@ -429,8 +439,10 @@ with gr.Blocks(css=CSS, title="SplatWeb") as demo:
|
|
| 429 |
- Any size photo β app auto-resizes to 512px before processing
|
| 430 |
- Clear, well-lit subject gives the best 3D quality
|
| 431 |
- Works on: objects, rooms, food, people, landscapes
|
| 432 |
-
- **
|
| 433 |
-
- **
|
|
|
|
|
|
|
| 434 |
""")
|
| 435 |
|
| 436 |
btn1 = gr.Button("β¦ Build My 3D Scene", variant="primary", size="lg")
|
|
@@ -505,7 +517,10 @@ with gr.Blocks(css=CSS, title="SplatWeb") as demo:
|
|
| 505 |
def handle_single(img):
|
| 506 |
if img is None:
|
| 507 |
return "β Please upload a photo first.", gr.update(value="", visible=False)
|
| 508 |
-
|
|
|
|
|
|
|
|
|
|
| 509 |
if ply:
|
| 510 |
script = make_load_script(ply)
|
| 511 |
return status, gr.update(value=script, visible=True)
|
|
@@ -515,11 +530,17 @@ with gr.Blocks(css=CSS, title="SplatWeb") as demo:
|
|
| 515 |
if a is None or b is None:
|
| 516 |
return "β Please upload BOTH photos.", gr.update(visible=False)
|
| 517 |
|
| 518 |
-
|
|
|
|
|
|
|
|
|
|
| 519 |
if not ply1:
|
| 520 |
return f"β Angle 1 failed:\n{s1}", gr.update(visible=False)
|
| 521 |
|
| 522 |
-
|
|
|
|
|
|
|
|
|
|
| 523 |
if not ply2:
|
| 524 |
return f"β Angle 1 done.\nβ Angle 2 failed:\n{s2}", gr.update(visible=False)
|
| 525 |
|
|
|
|
| 46 |
return tmp.name
|
| 47 |
|
| 48 |
# ββ Run SHARP ββ
|
| 49 |
+
# NOTE on duration: HuggingFace's free-tier ZeroGPU accounts get a 5-minute
|
| 50 |
+
# (300s) TOTAL daily quota. Requesting a duration at or above that cap makes
|
| 51 |
+
# the platform reject the call outright with "requested GPU duration is
|
| 52 |
+
# larger than the maximum allowed" (an "illegal duration" error) β it fails
|
| 53 |
+
# instantly, before your function even runs, and retrying won't help.
|
| 54 |
+
# Keeping this comfortably under the cap lets a free/unauthenticated user
|
| 55 |
+
# actually get a few conversions in per day instead of burning the whole
|
| 56 |
+
# quota (or being rejected) on a single call.
|
| 57 |
+
GPU_DURATION = 90
|
| 58 |
+
|
| 59 |
+
@spaces.GPU(duration=GPU_DURATION)
|
| 60 |
def run_sharp(image_path):
|
| 61 |
if image_path is None:
|
| 62 |
return None, "β Please upload a photo first."
|
|
|
|
| 66 |
resized = resize_image(image_path, 512)
|
| 67 |
result = subprocess.run(
|
| 68 |
["sharp", "predict", "-i", resized, "-o", out_dir],
|
| 69 |
+
capture_output=True, text=True, timeout=GPU_DURATION - 15
|
| 70 |
)
|
| 71 |
ply_files = [f for f in os.listdir(out_dir) if f.endswith(".ply")]
|
| 72 |
if not ply_files:
|
|
|
|
| 74 |
return None, f"SHARP failed:\n{err}"
|
| 75 |
return os.path.join(out_dir, ply_files[0]), "β Done β 3D scene loading below β"
|
| 76 |
except subprocess.TimeoutExpired:
|
| 77 |
+
return None, "β Timed out inside the GPU window. Try a smaller/simpler photo, or increase GPU_DURATION near the top of app.py if you have more quota (PRO/Team/Enterprise)."
|
| 78 |
except FileNotFoundError:
|
| 79 |
return None, "β SHARP not found yet β wait 1 minute and try again."
|
| 80 |
except Exception as e:
|
|
|
|
| 439 |
- Any size photo β app auto-resizes to 512px before processing
|
| 440 |
- Clear, well-lit subject gives the best 3D quality
|
| 441 |
- Works on: objects, rooms, food, people, landscapes
|
| 442 |
+
- **ZeroGPU hardware must be selected in your Space's Settings β Hardware** (it isn't automatic just because it's free now)
|
| 443 |
+
- **Free HF account:** 5 min of GPU time per day total (~3 conversions at current settings) β resets 24h after your first run
|
| 444 |
+
- **Not signed in:** only 2 min/day β sign in to a free HF account for more
|
| 445 |
+
- **PRO/Team/Enterprise:** much larger daily quota, plus pay-as-you-go
|
| 446 |
""")
|
| 447 |
|
| 448 |
btn1 = gr.Button("β¦ Build My 3D Scene", variant="primary", size="lg")
|
|
|
|
| 517 |
def handle_single(img):
|
| 518 |
if img is None:
|
| 519 |
return "β Please upload a photo first.", gr.update(value="", visible=False)
|
| 520 |
+
try:
|
| 521 |
+
ply, status = run_sharp(img)
|
| 522 |
+
except Exception as e:
|
| 523 |
+
return f"β GPU rejected the request: {str(e)}\n(If this mentions quota/duration, you've hit your daily free ZeroGPU limit β wait for it to reset, or sign in with a HF account for a bigger quota.)", gr.update(value="", visible=False)
|
| 524 |
if ply:
|
| 525 |
script = make_load_script(ply)
|
| 526 |
return status, gr.update(value=script, visible=True)
|
|
|
|
| 530 |
if a is None or b is None:
|
| 531 |
return "β Please upload BOTH photos.", gr.update(visible=False)
|
| 532 |
|
| 533 |
+
try:
|
| 534 |
+
ply1, s1 = run_sharp(a)
|
| 535 |
+
except Exception as e:
|
| 536 |
+
return f"β GPU rejected angle 1: {str(e)}", gr.update(visible=False)
|
| 537 |
if not ply1:
|
| 538 |
return f"β Angle 1 failed:\n{s1}", gr.update(visible=False)
|
| 539 |
|
| 540 |
+
try:
|
| 541 |
+
ply2, s2 = run_sharp(b)
|
| 542 |
+
except Exception as e:
|
| 543 |
+
return f"β Angle 1 done.\nβ GPU rejected angle 2: {str(e)}", gr.update(visible=False)
|
| 544 |
if not ply2:
|
| 545 |
return f"β Angle 1 done.\nβ Angle 2 failed:\n{s2}", gr.update(visible=False)
|
| 546 |
|