anvilinteractiv commited on
Commit
0133a3b
·
verified ·
1 Parent(s): a5c10ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -46
app.py CHANGED
@@ -16,10 +16,11 @@ from fastapi.security import APIKeyHeader
16
  from fastapi.staticfiles import StaticFiles
17
  from pydantic import BaseModel
18
  import uvicorn
 
19
 
20
  # Install additional dependencies
21
  subprocess.run("pip install spandrel==0.4.1 --no-deps", shell=True, check=True)
22
- subprocess.run("pip install fastapi uvicorn", shell=True, check=True)
23
 
24
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
25
  DTYPE = torch.float16
@@ -59,7 +60,7 @@ app.mount("/files", StaticFiles(directory=TMP_DIR), name="files")
59
 
60
  # API key authentication
61
  api_key_header = APIKeyHeader(name="X-API-Key")
62
- VALID_API_KEY = os.getenv("POLYGENIX_API_KEY", "your-secret-api-key") # Set in Hugging Face Space secrets
63
 
64
  async def verify_api_key(api_key: str = Depends(api_key_header)):
65
  if api_key != VALID_API_KEY:
@@ -74,6 +75,37 @@ class GenerateRequest(BaseModel):
74
  simplify: bool = True
75
  target_face_num: int = DEFAULT_FACE_NUMBER
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  HEADER = """
78
  # 🌌 PolyGenixAI: Craft 3D Worlds with Cosmic Precision
79
  ## Unleash Infinite Creativity with AI-Powered 3D Generation by AnvilInteractive Solutions
@@ -184,9 +216,8 @@ mv_adapter_pipe = prepare_pipeline(
184
  dtype=torch.float16,
185
  )
186
  birefnet = AutoModelForImageSegmentation.from_pretrained(
187
- "ZhengPeng7/BiRefNet", trust_remote_code=True
188
- )
189
- birefnet.to(DEVICE)
190
  transform_image = transforms.Compose(
191
  [
192
  transforms.Resize((1024, 1024)),
@@ -199,7 +230,7 @@ remove_bg_fn = lambda x: remove_bg(x, birefnet, transform_image, DEVICE)
199
  if not os.path.exists("checkpoints/RealESRGAN_x2plus.pth"):
200
  hf_hub_download("dtarnow/UPscaler", filename="RealESRGAN_x2plus.pth", local_dir="checkpoints")
201
  if not os.path.exists("checkpoints/big-lama.pt"):
202
- subprocess.run("wget -P checkpoints/ https://github.com/Sanster/models/releases/download/add_big_lama/big-lama.pt", shell=True, check=True)
203
 
204
  def start_session(req: gr.Request):
205
  save_dir = os.path.join(TMP_DIR, str(req.session_hash))
@@ -253,7 +284,6 @@ def run_full(image: str, req: gr.Request):
253
  torch.cuda.empty_cache()
254
 
255
  height, width = 768, 768
256
- # Prepare cameras
257
  cameras = get_orthogonal_camera(
258
  elevation_deg=[0, 0, 0, 0, 89.99, -89.99],
259
  distance=[1.8] * NUM_VIEWS,
@@ -337,31 +367,6 @@ def run_full(image: str, req: gr.Request):
337
 
338
  return image_seg, mesh_path, textured_glb_path
339
 
340
- # FastAPI endpoint for generating 3D models
341
- @app.post("/api/generate")
342
- async def generate_3d_model(request: GenerateRequest, image: UploadFile = File(...), api_key: str = Depends(verify_api_key)):
343
- try:
344
- # Save uploaded image to temporary directory
345
- session_hash = get_random_hex()
346
- save_dir = os.path.join(TMP_DIR, session_hash)
347
- os.makedirs(save_dir, exist_ok=True)
348
- image_path = os.path.join(save_dir, f"input_{get_random_hex()}.png")
349
- with open(image_path, "wb") as f:
350
- f.write(await image.read())
351
-
352
- # Run the full pipeline
353
- image_seg, mesh_path, textured_glb_path = run_full(image_path, req=None)
354
-
355
- # Return the file URL for the textured GLB
356
- file_url = f"/files/{session_hash}/{os.path.basename(textured_glb_path)}"
357
- return {"file_url": file_url}
358
- except Exception as e:
359
- raise HTTPException(status_code=500, detail=str(e))
360
- finally:
361
- # Clean up temporary directory
362
- if os.path.exists(save_dir):
363
- shutil.rmtree(save_dir)
364
-
365
  @spaces.GPU()
366
  @torch.no_grad()
367
  def run_segmentation(image: str):
@@ -406,7 +411,6 @@ def image_to_3d(
406
  @torch.no_grad()
407
  def run_texture(image: Image, mesh_path: str, seed: int, req: gr.Request):
408
  height, width = 768, 768
409
- # Prepare cameras
410
  cameras = get_orthogonal_camera(
411
  elevation_deg=[0, 0, 0, 0, 89.99, -89.99],
412
  distance=[1.8] * NUM_VIEWS,
@@ -491,14 +495,9 @@ def run_texture(image: Image, mesh_path: str, seed: int, req: gr.Request):
491
 
492
  return textured_glb_path
493
 
494
- # Gradio interface (unchanged)
495
  with gr.Blocks(title="PolyGenixAI", css="body { background-color: #1A1A1A; } .gr-panel { background-color: #2D2D2D; }") as demo:
496
  gr.Markdown(HEADER)
497
-
498
- @app.get("/api/test")
499
- async def test_endpoint():
500
- return {"message": "FastAPI is running"}
501
-
502
  with gr.Tabs(elem_classes="gr-tab"):
503
  with gr.Tab("Create 3D Model"):
504
  with gr.Row():
@@ -551,12 +550,10 @@ with gr.Blocks(title="PolyGenixAI", css="body { background-color: #1A1A1A; } .gr
551
  )
552
  gen_button = gr.Button("Generate 3D Model", variant="primary", elem_classes="gr-button-primary")
553
  gen_texture_button = gr.Button("Apply Texture", variant="secondary", interactive=False, elem_classes="gr-button-secondary")
554
-
555
  with gr.Column(scale=1):
556
  model_output = gr.Model3D(label="3D Model Preview", interactive=False, height=400, elem_classes="gr-panel")
557
  textured_model_output = gr.Model3D(label="Textured 3D Model", interactive=False, height=400, elem_classes="gr-panel")
558
  download_button = gr.Button("Download GLB", variant="secondary", elem_classes="gr-button-secondary")
559
-
560
  with gr.Tab("Cosmic Gallery"):
561
  gr.Markdown("### Discover Stellar Creations")
562
  gr.Examples(
@@ -570,7 +567,6 @@ with gr.Blocks(title="PolyGenixAI", css="body { background-color: #1A1A1A; } .gr
570
  cache_examples=True,
571
  )
572
  gr.Markdown("Connect with creators in our <a href='https://www.anvilinteractive.com/community' style='color: #A78BFA; text-decoration: none;'>PolyGenixAI Cosmic Community</a>!")
573
-
574
  gen_button.click(
575
  run_segmentation,
576
  inputs=[image_prompts],
@@ -591,16 +587,25 @@ with gr.Blocks(title="PolyGenixAI", css="body { background-color: #1A1A1A; } .gr
591
  ],
592
  outputs=[model_output]
593
  ).then(lambda: gr.Button(interactive=True), outputs=[gen_texture_button])
594
-
595
  gen_texture_button.click(
596
  run_texture,
597
  inputs=[image_prompts, model_output, seed],
598
  outputs=[textured_model_output]
599
  )
600
-
601
  demo.load(start_session)
602
  demo.unload(end_session)
603
 
604
- # Run both Gradio and FastAPI
 
 
 
 
 
 
 
 
 
 
 
605
  if __name__ == "__main__":
606
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
16
  from fastapi.staticfiles import StaticFiles
17
  from pydantic import BaseModel
18
  import uvicorn
19
+ import asyncio
20
 
21
  # Install additional dependencies
22
  subprocess.run("pip install spandrel==0.4.1 --no-deps", shell=True, check=True)
23
+ subprocess.run("pip install fastapi==0.116.1 uvicorn==0.31.0", shell=True, check=True)
24
 
25
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
26
  DTYPE = torch.float16
 
60
 
61
  # API key authentication
62
  api_key_header = APIKeyHeader(name="X-API-Key")
63
+ VALID_API_KEY = os.getenv("POLYGENIX_API_KEY", "your-secret-api-key")
64
 
65
  async def verify_api_key(api_key: str = Depends(api_key_header)):
66
  if api_key != VALID_API_KEY:
 
75
  simplify: bool = True
76
  target_face_num: int = DEFAULT_FACE_NUMBER
77
 
78
+ # Test endpoint
79
+ @app.get("/api/test")
80
+ async def test_endpoint():
81
+ return {"message": "FastAPI is running"}
82
+
83
+ # FastAPI endpoint for generating 3D models
84
+ @app.post("/api/generate")
85
+ async def generate_3d_model(request: GenerateRequest, image: UploadFile = File(...), api_key: str = Depends(verify_api_key)):
86
+ try:
87
+ # Save uploaded image to temporary directory
88
+ session_hash = get_random_hex()
89
+ save_dir = os.path.join(TMP_DIR, session_hash)
90
+ os.makedirs(save_dir, exist_ok=True)
91
+ image_path = os.path.join(save_dir, f"input_{get_random_hex()}.png")
92
+ with open(image_path, "wb") as f:
93
+ f.write(await image.read())
94
+
95
+ # Run the full pipeline
96
+ image_seg, mesh_path, textured_glb_path = run_full(image_path, req=None)
97
+
98
+ # Return the file URL for the textured GLB
99
+ file_url = f"/files/{session_hash}/{os.path.basename(textured_glb_path)}"
100
+ return {"file_url": file_url}
101
+ except Exception as e:
102
+ raise HTTPException(status_code=500, detail=str(e))
103
+ finally:
104
+ # Clean up temporary directory
105
+ if os.path.exists(save_dir):
106
+ shutil.rmtree(save_dir)
107
+
108
+ # Gradio-related functions (unchanged)
109
  HEADER = """
110
  # 🌌 PolyGenixAI: Craft 3D Worlds with Cosmic Precision
111
  ## Unleash Infinite Creativity with AI-Powered 3D Generation by AnvilInteractive Solutions
 
216
  dtype=torch.float16,
217
  )
218
  birefnet = AutoModelForImageSegmentation.from_pretrained(
219
+ "ZhengPeng7/BiRefNet", trust_remote_code=True
220
+ ).to(DEVICE)
 
221
  transform_image = transforms.Compose(
222
  [
223
  transforms.Resize((1024, 1024)),
 
230
  if not os.path.exists("checkpoints/RealESRGAN_x2plus.pth"):
231
  hf_hub_download("dtarnow/UPscaler", filename="RealESRGAN_x2plus.pth", local_dir="checkpoints")
232
  if not os.path.exists("checkpoints/big-lama.pt"):
233
+ hf_hub_download("Sanster/models", filename="big-lama.pt", local_dir="checkpoints")
234
 
235
  def start_session(req: gr.Request):
236
  save_dir = os.path.join(TMP_DIR, str(req.session_hash))
 
284
  torch.cuda.empty_cache()
285
 
286
  height, width = 768, 768
 
287
  cameras = get_orthogonal_camera(
288
  elevation_deg=[0, 0, 0, 0, 89.99, -89.99],
289
  distance=[1.8] * NUM_VIEWS,
 
367
 
368
  return image_seg, mesh_path, textured_glb_path
369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  @spaces.GPU()
371
  @torch.no_grad()
372
  def run_segmentation(image: str):
 
411
  @torch.no_grad()
412
  def run_texture(image: Image, mesh_path: str, seed: int, req: gr.Request):
413
  height, width = 768, 768
 
414
  cameras = get_orthogonal_camera(
415
  elevation_deg=[0, 0, 0, 0, 89.99, -89.99],
416
  distance=[1.8] * NUM_VIEWS,
 
495
 
496
  return textured_glb_path
497
 
498
+ # Gradio interface
499
  with gr.Blocks(title="PolyGenixAI", css="body { background-color: #1A1A1A; } .gr-panel { background-color: #2D2D2D; }") as demo:
500
  gr.Markdown(HEADER)
 
 
 
 
 
501
  with gr.Tabs(elem_classes="gr-tab"):
502
  with gr.Tab("Create 3D Model"):
503
  with gr.Row():
 
550
  )
551
  gen_button = gr.Button("Generate 3D Model", variant="primary", elem_classes="gr-button-primary")
552
  gen_texture_button = gr.Button("Apply Texture", variant="secondary", interactive=False, elem_classes="gr-button-secondary")
 
553
  with gr.Column(scale=1):
554
  model_output = gr.Model3D(label="3D Model Preview", interactive=False, height=400, elem_classes="gr-panel")
555
  textured_model_output = gr.Model3D(label="Textured 3D Model", interactive=False, height=400, elem_classes="gr-panel")
556
  download_button = gr.Button("Download GLB", variant="secondary", elem_classes="gr-button-secondary")
 
557
  with gr.Tab("Cosmic Gallery"):
558
  gr.Markdown("### Discover Stellar Creations")
559
  gr.Examples(
 
567
  cache_examples=True,
568
  )
569
  gr.Markdown("Connect with creators in our <a href='https://www.anvilinteractive.com/community' style='color: #A78BFA; text-decoration: none;'>PolyGenixAI Cosmic Community</a>!")
 
570
  gen_button.click(
571
  run_segmentation,
572
  inputs=[image_prompts],
 
587
  ],
588
  outputs=[model_output]
589
  ).then(lambda: gr.Button(interactive=True), outputs=[gen_texture_button])
 
590
  gen_texture_button.click(
591
  run_texture,
592
  inputs=[image_prompts, model_output, seed],
593
  outputs=[textured_model_output]
594
  )
 
595
  demo.load(start_session)
596
  demo.unload(end_session)
597
 
598
+ # Run FastAPI and Gradio concurrently
599
+ async def run_servers():
600
+ # Start FastAPI with Uvicorn
601
+ config = uvicorn.Config(app=app, host="0.0.0.0", port=8000)
602
+ server = uvicorn.Server(config)
603
+ fastapi_task = asyncio.create_task(server.serve())
604
+
605
+ # Start Gradio
606
+ demo.launch(server_name="0.0.0.0", server_port=7860)
607
+
608
+ await fastapi_task
609
+
610
  if __name__ == "__main__":
611
+ asyncio.run(run_servers())