akhaliq HF Staff commited on
Commit
2c2a833
Β·
verified Β·
1 Parent(s): 4a8fe64

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +272 -0
app.py ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ SAM 3D Body Gradio App - ZeroGPU Compatible
3
+ This app handles all dependencies and provides a user-friendly interface for 3D body estimation.
4
+ Optimized for Hugging Face Spaces with ZeroGPU support.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import subprocess
10
+ import importlib.util
11
+
12
+ def check_and_install_package(package_name, import_name=None, pip_name=None):
13
+ """Check if a package is installed, if not, install it."""
14
+ if import_name is None:
15
+ import_name = package_name
16
+ if pip_name is None:
17
+ pip_name = package_name
18
+
19
+ spec = importlib.util.find_spec(import_name)
20
+ if spec is None:
21
+ print(f"Installing {package_name}...")
22
+ subprocess.check_call([sys.executable, "-m", "pip", "install", pip_name, "-q"])
23
+ print(f"βœ“ {package_name} installed successfully")
24
+ return True
25
+
26
+ # Install core dependencies
27
+ print("Checking and installing dependencies...")
28
+ check_and_install_package("gradio")
29
+ check_and_install_package("spaces") # ZeroGPU support
30
+ check_and_install_package("torch", pip_name="torch torchvision torchaudio")
31
+ check_and_install_package("pytorch_lightning", "pytorch_lightning")
32
+ check_and_install_package("cv2", "cv2", "opencv-python")
33
+ check_and_install_package("numpy")
34
+ check_and_install_package("PIL", "PIL", "Pillow")
35
+ check_and_install_package("huggingface_hub")
36
+
37
+ # Install additional dependencies
38
+ additional_deps = [
39
+ "pyrender", "yacs", "scikit-image", "einops", "timm", "dill",
40
+ "pandas", "rich", "hydra-core", "pyrootutils", "webdataset",
41
+ "networkx==3.2.1", "roma", "joblib", "seaborn", "loguru",
42
+ "pycocotools", "fvcore"
43
+ ]
44
+
45
+ for dep in additional_deps:
46
+ try:
47
+ pkg_name = dep.split("==")[0].replace("-", "_")
48
+ check_and_install_package(pkg_name, pip_name=dep)
49
+ except:
50
+ pass
51
+
52
+ print("Core dependencies installed!")
53
+
54
+ import gradio as gr
55
+ import cv2
56
+ import numpy as np
57
+ from PIL import Image
58
+ import torch
59
+ import spaces # ZeroGPU decorator
60
+ from huggingface_hub import hf_hub_download, login
61
+ import warnings
62
+ warnings.filterwarnings('ignore')
63
+
64
+ class SAM3DBodyEstimator:
65
+ """Wrapper class for SAM 3D Body estimation with ZeroGPU support."""
66
+
67
+ def __init__(self, hf_repo_id="facebook/sam-3d-body-dinov3"):
68
+ self.hf_repo_id = hf_repo_id
69
+ self.model = None
70
+ self.faces = None
71
+ self.initialized = False
72
+
73
+ def setup(self, hf_token=None):
74
+ """Setup the SAM 3D Body model (CPU operations only)."""
75
+ try:
76
+ if hf_token:
77
+ login(token=hf_token)
78
+ print("βœ“ Logged in to Hugging Face")
79
+
80
+ # Try to import the SAM 3D Body utilities
81
+ try:
82
+ from notebook.utils import setup_sam_3d_body
83
+ # Initialize model on CPU first, will move to GPU during inference
84
+ self.model = setup_sam_3d_body(hf_repo_id=self.hf_repo_id)
85
+ self.faces = self.model.faces
86
+ self.initialized = True
87
+ return "βœ“ Model loaded successfully! Ready for GPU inference."
88
+ except ImportError:
89
+ return "⚠️ SAM 3D Body package not found. Please install manually or provide installation path."
90
+ except Exception as e:
91
+ return f"❌ Error loading model: {str(e)}\n\nPlease ensure you have access to the Hugging Face repo and are authenticated."
92
+
93
+ except Exception as e:
94
+ return f"❌ Setup error: {str(e)}"
95
+
96
+ @spaces.GPU(duration=120) # ZeroGPU decorator with 120s timeout
97
+ def process_image(self, image):
98
+ """Process an image and return 3D body estimation (GPU accelerated)."""
99
+ if not self.initialized:
100
+ return None, "❌ Model not initialized. Please setup first with your HF token."
101
+
102
+ try:
103
+ # Ensure model is on GPU
104
+ if hasattr(self.model, 'to'):
105
+ self.model.to('cuda')
106
+
107
+ # Convert PIL to BGR
108
+ img_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
109
+
110
+ # Process image (GPU operations happen here)
111
+ img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
112
+ outputs = self.model.process_one_image(img_rgb)
113
+
114
+ # Visualize results
115
+ try:
116
+ from tools.vis_utils import visualize_sample_together
117
+ rend_img = visualize_sample_together(img_bgr, outputs, self.faces)
118
+ result_img = Image.fromarray(cv2.cvtColor(rend_img.astype(np.uint8), cv2.COLOR_BGR2RGB))
119
+
120
+ # GPU is automatically released after this function completes
121
+ return result_img, "βœ“ Processing completed successfully!"
122
+ except ImportError:
123
+ # Fallback visualization if vis_utils not available
124
+ return image, "⚠️ Visualization utilities not found. Model processed but cannot render 3D output."
125
+
126
+ except Exception as e:
127
+ return None, f"❌ Processing error: {str(e)}"
128
+ finally:
129
+ # Clean up GPU memory
130
+ if torch.cuda.is_available():
131
+ torch.cuda.empty_cache()
132
+
133
+ # Initialize estimator
134
+ estimator = SAM3DBodyEstimator()
135
+
136
+ def setup_model(hf_token, model_choice):
137
+ """Setup the SAM 3D Body model with HF token."""
138
+ repo_ids = {
139
+ "DINOv3 (Recommended)": "facebook/sam-3d-body-dinov3",
140
+ "ViT-H": "facebook/sam-3d-body-vith"
141
+ }
142
+ estimator.hf_repo_id = repo_ids[model_choice]
143
+ return estimator.setup(hf_token)
144
+
145
+ def process_uploaded_image(image):
146
+ """Process uploaded image through SAM 3D Body (GPU allocated dynamically)."""
147
+ if image is None:
148
+ return None, "❌ Please upload an image first."
149
+ return estimator.process_image(image)
150
+
151
+ # Create Gradio interface
152
+ with gr.Blocks(title="SAM 3D Body Estimator", theme=gr.themes.Soft()) as demo:
153
+ gr.Markdown("""
154
+ # 🎯 SAM 3D Body Estimator (ZeroGPU)
155
+
156
+ Generate 3D body meshes from single images using Meta's SAM 3D Body model.
157
+ **Powered by Hugging Face Spaces ZeroGPU** - Dynamic GPU allocation for efficient inference!
158
+
159
+ ### πŸ“‹ Setup Instructions:
160
+ 1. Get access to the model on [Hugging Face](https://huggingface.co/facebook/sam-3d-body-dinov3)
161
+ 2. Create a [Hugging Face token](https://huggingface.co/settings/tokens) with read access
162
+ 3. Enter your token below and click "Initialize Model"
163
+ 4. Upload an image and click "Process Image"
164
+
165
+ ⚠️ **Note**: You need approved access to the SAM 3D Body repos on Hugging Face.
166
+
167
+ ### ⚑ ZeroGPU Features:
168
+ - **Dynamic GPU Allocation**: H200 GPU allocated only during inference
169
+ - **Free GPU Access**: Available to all users with daily quotas
170
+ - **PRO Benefits**: PRO users get 7x more quota (25 min/day vs 3.5 min/day)
171
+ """)
172
+
173
+ with gr.Row():
174
+ with gr.Column(scale=1):
175
+ gr.Markdown("### πŸ”§ Model Setup")
176
+ hf_token_input = gr.Textbox(
177
+ label="Hugging Face Token",
178
+ placeholder="hf_...",
179
+ type="password",
180
+ info="Your HF token with read access"
181
+ )
182
+ model_choice = gr.Radio(
183
+ choices=["DINOv3 (Recommended)", "ViT-H"],
184
+ value="DINOv3 (Recommended)",
185
+ label="Model Selection"
186
+ )
187
+ setup_btn = gr.Button("πŸš€ Initialize Model", variant="primary")
188
+ setup_status = gr.Textbox(label="Setup Status", interactive=False)
189
+
190
+ gr.Markdown("### πŸ“Έ Upload Image")
191
+ input_image = gr.Image(
192
+ label="Input Image",
193
+ type="pil",
194
+ sources=["upload", "webcam"]
195
+ )
196
+ process_btn = gr.Button("▢️ Process Image (GPU)", variant="primary")
197
+ process_status = gr.Textbox(label="Processing Status", interactive=False)
198
+
199
+ with gr.Column(scale=1):
200
+ gr.Markdown("### 🎨 Results")
201
+ output_image = gr.Image(label="3D Body Estimation", type="pil")
202
+
203
+ gr.Markdown("""
204
+ ### πŸ’‘ Tips:
205
+ - Use clear, full-body images for best results
206
+ - Ensure good lighting and minimal occlusion
207
+ - Person should be facing the camera
208
+ - High resolution images work better
209
+ - Processing time: ~30-60 seconds per image
210
+
211
+ ### πŸ“Š GPU Usage:
212
+ - **Duration**: Up to 120 seconds per inference
213
+ - **VRAM**: 70GB H200 GPU available
214
+ - **Queue**: Priority based on account tier
215
+ """)
216
+
217
+ gr.Markdown("""
218
+ ---
219
+ ### πŸ“š Additional Information
220
+
221
+ **Model Details:**
222
+ - Paper: [SAM 3D Body](https://arxiv.org/abs/your-paper-link)
223
+ - GitHub: [facebook/sam-3d-body](https://github.com/facebookresearch/sam-3d-body)
224
+
225
+ **ZeroGPU Daily Quotas:**
226
+ - Unauthenticated: 2 minutes
227
+ - Free account: 3.5 minutes
228
+ - PRO account: 25 minutes (7x more!)
229
+ - Enterprise: 45 minutes
230
+
231
+ **System Requirements:**
232
+ - Python 3.10.13+
233
+ - PyTorch 2.1.0+
234
+ - Gradio 4+
235
+ - ZeroGPU Space (H200 GPU)
236
+
237
+ **Troubleshooting:**
238
+ - If model fails to load, ensure you have access to the HF repo
239
+ - GPU allocation is dynamic - wait for your turn in queue
240
+ - Check your daily quota if processing fails
241
+ - Clear browser cache if interface doesn't load properly
242
+
243
+ **About ZeroGPU:**
244
+ This Space uses ZeroGPU, which dynamically allocates NVIDIA H200 GPUs only during inference.
245
+ This maximizes efficiency and allows free GPU access for AI demos!
246
+ """)
247
+
248
+ # Event handlers
249
+ setup_btn.click(
250
+ fn=setup_model,
251
+ inputs=[hf_token_input, model_choice],
252
+ outputs=setup_status
253
+ )
254
+
255
+ process_btn.click(
256
+ fn=process_uploaded_image,
257
+ inputs=input_image,
258
+ outputs=[output_image, process_status]
259
+ )
260
+
261
+ # Launch the app
262
+ if __name__ == "__main__":
263
+ print("\n" + "="*60)
264
+ print("πŸš€ Starting SAM 3D Body Gradio App (ZeroGPU)")
265
+ print("="*60 + "\n")
266
+
267
+ demo.launch(
268
+ server_name="0.0.0.0",
269
+ server_port=7860,
270
+ share=False,
271
+ show_error=True
272
+ )