Spaces:
mashroo
/
Running on Zero

YoussefAnso commited on
Commit
8e3405b
·
1 Parent(s): b492be8

Enhance app.py with improved error handling, compatibility fixes, and streamlined image processing functions. Update Gradio interface for better user experience, including clearer background choice options and refined button functionality.

Browse files
Files changed (1) hide show
  1. app.py +78 -41
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # Not ready to use yet
2
  import spaces
3
  import argparse
4
  import numpy as np
@@ -36,7 +36,7 @@ def init_model():
36
  help="config for stage2",
37
  )
38
  parser.add_argument("--device", type=str, default="cuda")
39
- args = parser.parse_args()
40
 
41
  # Download model files
42
  crm_path = hf_hub_download(repo_id="Zhengyi/CRM", filename="CRM.pth")
@@ -73,6 +73,7 @@ def init_model():
73
  # Global variables to store model and pipeline
74
  model = None
75
  pipeline = None
 
76
 
77
  @spaces.GPU
78
  def get_model():
@@ -84,7 +85,6 @@ def get_model():
84
 
85
  rembg_session = rembg.new_session()
86
 
87
-
88
  def expand_to_square(image, bg_color=(0, 0, 0, 0)):
89
  # expand image to 1:1
90
  width, height = image.size
@@ -111,7 +111,7 @@ def remove_background(
111
  do_remove = True
112
  if image.mode == "RGBA" and image.getextrema()[3][0] < 255:
113
  # explain why current do not rm bg
114
- print("alhpa channl not enpty, skip remove background, using alpha channel as mask")
115
  background = Image.new("RGBA", image.size, (0, 0, 0, 0))
116
  image = Image.alpha_composite(background, image)
117
  do_remove = False
@@ -121,7 +121,7 @@ def remove_background(
121
  return image
122
 
123
  def do_resize_content(original_image: Image, scale_rate):
124
- # resize image content wile retain the original image size
125
  if scale_rate != 1:
126
  # Calculate the new size after rescaling
127
  new_size = tuple(int(dim * scale_rate) for dim in original_image.size)
@@ -147,30 +147,35 @@ def add_random_background(image, color):
147
  return Image.alpha_composite(background, image)
148
 
149
  @spaces.GPU
150
- def preprocess_image(input_image, background_choice, foreground_ratio, back_groud_color):
151
  """Preprocess the input image"""
152
  try:
153
- # Get model and pipeline when needed
154
- model, pipeline = get_model()
 
 
 
 
 
155
 
156
- # Convert to numpy array
157
- np_image = np.array(input_image)
 
158
 
159
  # Process background
160
- if background_choice == "Remove Background":
161
- np_image = rembg.remove(np_image, session=rembg_session)
162
  elif background_choice == "Custom Background":
163
- np_image = add_random_background(np_image, back_groud_color)
164
 
165
  # Resize content if needed
166
  if foreground_ratio != 1.0:
167
- np_image = do_resize_content(Image.fromarray(np_image), foreground_ratio)
168
- np_image = np.array(np_image)
169
 
170
- return Image.fromarray(np_image)
171
  except Exception as e:
172
  print(f"Error in preprocess_image: {str(e)}")
173
- raise e
174
 
175
  @spaces.GPU
176
  def gen_image(processed_image, seed, scale, step):
@@ -179,26 +184,51 @@ def gen_image(processed_image, seed, scale, step):
179
  # Get model and pipeline when needed
180
  model, pipeline = get_model()
181
 
 
 
 
 
182
  # Convert to numpy array
183
- np_image = np.array(processed_image)
 
 
 
184
 
185
  # Set random seed
186
- torch.manual_seed(seed)
187
- np.random.seed(seed)
188
 
189
  # Generate images
190
  np_imgs, np_xyzs = pipeline.generate(
191
  np_image,
192
- guidance_scale=scale,
193
- num_inference_steps=step
194
  )
195
 
196
  # Generate 3D model
197
  glb_path = generate3d(model, np_imgs, np_xyzs, args.device)
 
198
  return Image.fromarray(np_imgs), Image.fromarray(np_xyzs), glb_path
199
  except Exception as e:
200
  print(f"Error in gen_image: {str(e)}")
201
- raise e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
 
203
  _DESCRIPTION = '''
204
  * Our [official implementation](https://github.com/thu-ml/CRM) uses UV texture instead of vertex color. It has better texture than this online demo.
@@ -206,7 +236,8 @@ _DESCRIPTION = '''
206
  * If you find the output unsatisfying, try using different seeds:)
207
  '''
208
 
209
- with gr.Blocks() as demo:
 
210
  gr.Markdown("# CRM: Single Image to 3D Textured Mesh with Convolutional Reconstruction Model")
211
  gr.Markdown(_DESCRIPTION)
212
 
@@ -215,21 +246,23 @@ with gr.Blocks() as demo:
215
  with gr.Row():
216
  image_input = gr.Image(
217
  label="Image input",
218
- type="pil"
 
219
  )
220
  processed_image = gr.Image(
221
  label="Processed Image",
222
- type="pil"
 
223
  )
224
 
225
  with gr.Row():
226
  with gr.Column():
227
  background_choice = gr.Radio(
228
- choices=["Alpha as mask", "Auto Remove background"],
229
  value="Auto Remove background",
230
  label="Background choice"
231
  )
232
- back_groud_color = gr.ColorPicker(
233
  label="Background Color",
234
  value="#7F7F7F"
235
  )
@@ -261,12 +294,14 @@ with gr.Blocks() as demo:
261
  precision=0
262
  )
263
 
264
- text_button = gr.Button("Generate 3D shape")
265
 
266
- gr.Examples(
267
- examples=[[os.path.join("examples", i)] for i in os.listdir("examples")],
268
- inputs=[image_input]
269
- )
 
 
270
 
271
  with gr.Column():
272
  image_output = gr.Image(label="Output RGB image")
@@ -274,24 +309,20 @@ with gr.Blocks() as demo:
274
  output_model = gr.Model3D(label="Output GLB")
275
  gr.Markdown("Note: Ensure that the input image is correctly pre-processed into a grey background, otherwise the results will be unpredictable.")
276
 
277
- def process_and_generate(image, bg_choice, fg_ratio, bg_color, seed_val, guidance, steps):
278
- if image is None:
279
- raise gr.Error("No image uploaded!")
280
- processed = preprocess_image(image, bg_choice, fg_ratio, bg_color)
281
- return gen_image(processed, seed_val, guidance, steps)
282
-
283
  text_button.click(
284
  fn=process_and_generate,
285
  inputs=[
286
  image_input,
287
  background_choice,
288
  foreground_ratio,
289
- back_groud_color,
290
  seed,
291
  guidance_scale,
292
  step
293
  ],
294
  outputs=[
 
295
  image_output,
296
  xyz_output,
297
  output_model
@@ -300,4 +331,10 @@ with gr.Blocks() as demo:
300
  )
301
 
302
  if __name__ == "__main__":
303
- demo.queue().launch()
 
 
 
 
 
 
 
1
+ # Fixed version with proper error handling and compatibility
2
  import spaces
3
  import argparse
4
  import numpy as np
 
36
  help="config for stage2",
37
  )
38
  parser.add_argument("--device", type=str, default="cuda")
39
+ args = parser.parse_args(args=[]) # Fix: provide empty args list
40
 
41
  # Download model files
42
  crm_path = hf_hub_download(repo_id="Zhengyi/CRM", filename="CRM.pth")
 
73
  # Global variables to store model and pipeline
74
  model = None
75
  pipeline = None
76
+ args = None
77
 
78
  @spaces.GPU
79
  def get_model():
 
85
 
86
  rembg_session = rembg.new_session()
87
 
 
88
  def expand_to_square(image, bg_color=(0, 0, 0, 0)):
89
  # expand image to 1:1
90
  width, height = image.size
 
111
  do_remove = True
112
  if image.mode == "RGBA" and image.getextrema()[3][0] < 255:
113
  # explain why current do not rm bg
114
+ print("alpha channel not empty, skip remove background, using alpha channel as mask")
115
  background = Image.new("RGBA", image.size, (0, 0, 0, 0))
116
  image = Image.alpha_composite(background, image)
117
  do_remove = False
 
121
  return image
122
 
123
  def do_resize_content(original_image: Image, scale_rate):
124
+ # resize image content while retaining the original image size
125
  if scale_rate != 1:
126
  # Calculate the new size after rescaling
127
  new_size = tuple(int(dim * scale_rate) for dim in original_image.size)
 
147
  return Image.alpha_composite(background, image)
148
 
149
  @spaces.GPU
150
+ def preprocess_image(input_image, background_choice, foreground_ratio, back_ground_color):
151
  """Preprocess the input image"""
152
  try:
153
+ # Check if image is provided
154
+ if input_image is None:
155
+ raise gr.Error("No image uploaded!")
156
+
157
+ # Convert to PIL Image if needed
158
+ if isinstance(input_image, np.ndarray):
159
+ input_image = Image.fromarray(input_image)
160
 
161
+ # Ensure RGBA mode
162
+ if input_image.mode != "RGBA":
163
+ input_image = input_image.convert("RGBA")
164
 
165
  # Process background
166
+ if background_choice == "Auto Remove background":
167
+ input_image = remove_background(input_image, rembg_session)
168
  elif background_choice == "Custom Background":
169
+ input_image = add_random_background(input_image, back_ground_color)
170
 
171
  # Resize content if needed
172
  if foreground_ratio != 1.0:
173
+ input_image = do_resize_content(input_image, foreground_ratio)
 
174
 
175
+ return input_image
176
  except Exception as e:
177
  print(f"Error in preprocess_image: {str(e)}")
178
+ raise gr.Error(f"Preprocessing failed: {str(e)}")
179
 
180
  @spaces.GPU
181
  def gen_image(processed_image, seed, scale, step):
 
184
  # Get model and pipeline when needed
185
  model, pipeline = get_model()
186
 
187
+ # Check if image is provided
188
+ if processed_image is None:
189
+ raise gr.Error("No processed image provided!")
190
+
191
  # Convert to numpy array
192
+ if isinstance(processed_image, Image.Image):
193
+ np_image = np.array(processed_image)
194
+ else:
195
+ np_image = processed_image
196
 
197
  # Set random seed
198
+ torch.manual_seed(int(seed))
199
+ np.random.seed(int(seed))
200
 
201
  # Generate images
202
  np_imgs, np_xyzs = pipeline.generate(
203
  np_image,
204
+ guidance_scale=float(scale),
205
+ num_inference_steps=int(step)
206
  )
207
 
208
  # Generate 3D model
209
  glb_path = generate3d(model, np_imgs, np_xyzs, args.device)
210
+
211
  return Image.fromarray(np_imgs), Image.fromarray(np_xyzs), glb_path
212
  except Exception as e:
213
  print(f"Error in gen_image: {str(e)}")
214
+ raise gr.Error(f"Generation failed: {str(e)}")
215
+
216
+ def process_and_generate(image, bg_choice, fg_ratio, bg_color, seed_val, guidance, steps):
217
+ """Combined function to process image and generate 3D model"""
218
+ try:
219
+ if image is None:
220
+ raise gr.Error("No image uploaded!")
221
+
222
+ # Preprocess the image
223
+ processed = preprocess_image(image, bg_choice, fg_ratio, bg_color)
224
+
225
+ # Generate 3D model
226
+ rgb_img, ccm_img, glb_file = gen_image(processed, seed_val, guidance, steps)
227
+
228
+ return processed, rgb_img, ccm_img, glb_file
229
+ except Exception as e:
230
+ print(f"Error in process_and_generate: {str(e)}")
231
+ raise gr.Error(f"Process failed: {str(e)}")
232
 
233
  _DESCRIPTION = '''
234
  * Our [official implementation](https://github.com/thu-ml/CRM) uses UV texture instead of vertex color. It has better texture than this online demo.
 
236
  * If you find the output unsatisfying, try using different seeds:)
237
  '''
238
 
239
+ # Create the Gradio interface
240
+ with gr.Blocks(title="CRM: Single Image to 3D") as demo:
241
  gr.Markdown("# CRM: Single Image to 3D Textured Mesh with Convolutional Reconstruction Model")
242
  gr.Markdown(_DESCRIPTION)
243
 
 
246
  with gr.Row():
247
  image_input = gr.Image(
248
  label="Image input",
249
+ type="pil",
250
+ height=300
251
  )
252
  processed_image = gr.Image(
253
  label="Processed Image",
254
+ type="pil",
255
+ height=300
256
  )
257
 
258
  with gr.Row():
259
  with gr.Column():
260
  background_choice = gr.Radio(
261
+ choices=["Alpha as mask", "Auto Remove background", "Custom Background"],
262
  value="Auto Remove background",
263
  label="Background choice"
264
  )
265
+ back_ground_color = gr.ColorPicker(
266
  label="Background Color",
267
  value="#7F7F7F"
268
  )
 
294
  precision=0
295
  )
296
 
297
+ text_button = gr.Button("Generate 3D shape", variant="primary")
298
 
299
+ # Only add examples if the directory exists
300
+ if os.path.exists("examples") and os.listdir("examples"):
301
+ gr.Examples(
302
+ examples=[[os.path.join("examples", i)] for i in os.listdir("examples") if i.lower().endswith(('.png', '.jpg', '.jpeg'))],
303
+ inputs=[image_input]
304
+ )
305
 
306
  with gr.Column():
307
  image_output = gr.Image(label="Output RGB image")
 
309
  output_model = gr.Model3D(label="Output GLB")
310
  gr.Markdown("Note: Ensure that the input image is correctly pre-processed into a grey background, otherwise the results will be unpredictable.")
311
 
312
+ # Connect the button to the processing function
 
 
 
 
 
313
  text_button.click(
314
  fn=process_and_generate,
315
  inputs=[
316
  image_input,
317
  background_choice,
318
  foreground_ratio,
319
+ back_ground_color,
320
  seed,
321
  guidance_scale,
322
  step
323
  ],
324
  outputs=[
325
+ processed_image,
326
  image_output,
327
  xyz_output,
328
  output_model
 
331
  )
332
 
333
  if __name__ == "__main__":
334
+ # Launch with proper settings for HF Spaces
335
+ demo.queue().launch(
336
+ server_name="0.0.0.0",
337
+ server_port=7860,
338
+ share=False, # Don't need share=True on HF Spaces
339
+ show_api=False # Disable API docs to avoid the error
340
+ )