cavargas10 commited on
Commit
c68d2cb
·
verified ·
1 Parent(s): f74642c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -133
app.py CHANGED
@@ -31,30 +31,7 @@ def end_session(req: gr.Request):
31
  shutil.rmtree(user_dir)
32
 
33
 
34
- def preprocess_image(image: Image.Image) -> Image.Image:
35
- """
36
- Preprocess the input image.
37
-
38
- Args:
39
- image (Image.Image): The input image.
40
-
41
- Returns:
42
- Image.Image: The preprocessed image.
43
- """
44
- processed_image = pipeline.preprocess_image(image)
45
- return processed_image
46
-
47
-
48
  def preprocess_images(images: List[Tuple[Image.Image, str]]) -> List[Image.Image]:
49
- """
50
- Preprocess a list of input images.
51
-
52
- Args:
53
- images (List[Tuple[Image.Image, str]]): The input images.
54
-
55
- Returns:
56
- List[Image.Image]: The preprocessed images.
57
- """
58
  images = [image[0] for image in images]
59
  processed_images = [pipeline.preprocess_image(image) for image in images]
60
  return processed_images
@@ -101,15 +78,11 @@ def unpack_state(state: dict) -> Tuple[Gaussian, edict, str]:
101
 
102
 
103
  def get_seed(randomize_seed: bool, seed: int) -> int:
104
- """
105
- Get the random seed.
106
- """
107
  return np.random.randint(0, MAX_SEED) if randomize_seed else seed
108
 
109
 
110
  @spaces.GPU
111
  def image_to_3d(
112
- image: Image.Image,
113
  multiimages: List[Tuple[Image.Image, str]],
114
  is_multiimage: bool,
115
  seed: int,
@@ -120,24 +93,6 @@ def image_to_3d(
120
  multiimage_algo: Literal["multidiffusion", "stochastic"],
121
  req: gr.Request,
122
  ) -> Tuple[dict, str]:
123
- """
124
- Convert an image to a 3D model.
125
-
126
- Args:
127
- image (Image.Image): The input image.
128
- multiimages (List[Tuple[Image.Image, str]]): The input images in multi-image mode.
129
- is_multiimage (bool): Whether is in multi-image mode.
130
- seed (int): The random seed.
131
- ss_guidance_strength (float): The guidance strength for sparse structure generation.
132
- ss_sampling_steps (int): The number of sampling steps for sparse structure generation.
133
- slat_guidance_strength (float): The guidance strength for structured latent generation.
134
- slat_sampling_steps (int): The number of sampling steps for structured latent generation.
135
- multiimage_algo (Literal["multidiffusion", "stochastic"]): The algorithm for multi-image generation.
136
-
137
- Returns:
138
- dict: The information of the generated 3D model.
139
- str: The path to the video of the 3D model.
140
- """
141
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
142
  if not is_multiimage:
143
  outputs = pipeline.run(
@@ -187,17 +142,6 @@ def extract_glb(
187
  texture_size: int,
188
  req: gr.Request,
189
  ) -> Tuple[str, str]:
190
- """
191
- Extract a GLB file from the 3D model.
192
-
193
- Args:
194
- state (dict): The state of the generated 3D model.
195
- mesh_simplify (float): The mesh simplification factor.
196
- texture_size (int): The texture resolution.
197
-
198
- Returns:
199
- str: The path to the extracted GLB file.
200
- """
201
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
202
  gs, mesh = unpack_state(state)
203
  glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
@@ -209,15 +153,6 @@ def extract_glb(
209
 
210
  @spaces.GPU
211
  def extract_gaussian(state: dict, req: gr.Request) -> Tuple[str, str]:
212
- """
213
- Extract a Gaussian file from the 3D model.
214
-
215
- Args:
216
- state (dict): The state of the generated 3D model.
217
-
218
- Returns:
219
- str: The path to the extracted Gaussian file.
220
- """
221
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
222
  gs, _ = unpack_state(state)
223
  gaussian_path = os.path.join(user_dir, 'sample.ply')
@@ -239,44 +174,24 @@ def prepare_multi_example() -> List[Image.Image]:
239
  images.append(Image.fromarray(np.concatenate(_images, axis=1)))
240
  return images
241
 
242
-
243
- def split_image(image: Image.Image) -> List[Image.Image]:
244
- """
245
- Split an image into multiple views.
246
- """
247
- image = np.array(image)
248
- alpha = image[..., 3]
249
- alpha = np.any(alpha>0, axis=0)
250
- start_pos = np.where(~alpha[:-1] & alpha[1:])[0].tolist()
251
- end_pos = np.where(alpha[:-1] & ~alpha[1:])[0].tolist()
252
- images = []
253
- for s, e in zip(start_pos, end_pos):
254
- images.append(Image.fromarray(image[:, s:e+1]))
255
- return [preprocess_image(image) for image in images]
256
-
257
-
258
  with gr.Blocks(delete_cache=(600, 600)) as demo:
259
  gr.Markdown("""
260
  ## Image to 3D Asset with [TRELLIS](https://trellis3d.github.io/)
261
- * Upload an image and click "Generate" to create a 3D asset. If the image has alpha channel, it be used as the mask. Otherwise, we use `rembg` to remove the background.
262
  * If you find the generated 3D asset satisfactory, click "Extract GLB" to extract the GLB file and download it.
263
-
264
- ✨New: 1) Experimental multi-image support. 2) Gaussian file extraction.
265
  """)
266
 
267
  with gr.Row():
268
  with gr.Column():
269
  with gr.Tabs() as input_tabs:
270
- with gr.Tab(label="Single Image", id=0) as single_image_input_tab:
271
- image_prompt = gr.Image(label="Image Prompt", format="png", image_mode="RGBA", type="pil", height=300)
272
  with gr.Tab(label="Multiple Images", id=1) as multiimage_input_tab:
273
  multiimage_prompt = gr.Gallery(label="Image Prompt", format="png", type="pil", height=300, columns=3)
274
  gr.Markdown("""
275
- Input different views of the object in separate images.
276
-
277
- *NOTE: this is an experimental algorithm without training a specialized model. It may not produce the best results for all images, especially those having different poses or inconsistent details.*
278
  """)
279
-
280
  with gr.Accordion(label="Generation Settings", open=False):
281
  seed = gr.Slider(0, MAX_SEED, label="Seed", value=0, step=1)
282
  randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
@@ -289,8 +204,7 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
289
  slat_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=3.0, step=0.1)
290
  slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
291
  multiimage_algo = gr.Radio(["stochastic", "multidiffusion"], label="Multi-image Algorithm", value="stochastic")
292
-
293
- generate_btn = gr.Button("Generate")
294
 
295
  with gr.Accordion(label="GLB Extraction Settings", open=False):
296
  mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify", value=0.95, step=0.01)
@@ -299,10 +213,11 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
299
  with gr.Row():
300
  extract_glb_btn = gr.Button("Extract GLB", interactive=False)
301
  extract_gs_btn = gr.Button("Extract Gaussian", interactive=False)
 
302
  gr.Markdown("""
303
- *NOTE: Gaussian file can be very large (~50MB), it will take a while to display and download.*
304
- """)
305
-
306
  with gr.Column():
307
  video_output = gr.Video(label="Generated 3D Asset", autoplay=True, loop=True, height=300)
308
  model_output = LitModel3D(label="Extracted GLB/Gaussian", exposure=10.0, height=300)
@@ -311,74 +226,47 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
311
  download_glb = gr.DownloadButton(label="Download GLB", interactive=False)
312
  download_gs = gr.DownloadButton(label="Download Gaussian", interactive=False)
313
 
314
- is_multiimage = gr.State(False)
315
  output_buf = gr.State()
316
-
317
  # Example images at the bottom of the page
318
- with gr.Row() as single_image_example:
319
- examples = gr.Examples(
320
- examples=[
321
- f'assets/example_image/{image}'
322
- for image in os.listdir("assets/example_image")
323
- ],
324
- inputs=[image_prompt],
325
- fn=preprocess_image,
326
- outputs=[image_prompt],
327
- run_on_click=True,
328
- examples_per_page=64,
329
- )
330
- with gr.Row(visible=False) as multiimage_example:
331
  examples_multi = gr.Examples(
332
  examples=prepare_multi_example(),
333
- inputs=[image_prompt],
334
  fn=split_image,
335
  outputs=[multiimage_prompt],
336
  run_on_click=True,
337
  examples_per_page=8,
338
  )
339
-
340
  # Handlers
341
  demo.load(start_session)
342
  demo.unload(end_session)
343
 
344
- single_image_input_tab.select(
345
- lambda: tuple([False, gr.Row.update(visible=True), gr.Row.update(visible=False)]),
346
- outputs=[is_multiimage, single_image_example, multiimage_example]
347
- )
348
- multiimage_input_tab.select(
349
- lambda: tuple([True, gr.Row.update(visible=False), gr.Row.update(visible=True)]),
350
- outputs=[is_multiimage, single_image_example, multiimage_example]
351
- )
352
-
353
- image_prompt.upload(
354
- preprocess_image,
355
- inputs=[image_prompt],
356
- outputs=[image_prompt],
357
- )
358
  multiimage_prompt.upload(
359
  preprocess_images,
360
  inputs=[multiimage_prompt],
361
  outputs=[multiimage_prompt],
362
  )
363
-
364
  generate_btn.click(
365
  get_seed,
366
  inputs=[randomize_seed, seed],
367
  outputs=[seed],
368
  ).then(
369
  image_to_3d,
370
- inputs=[image_prompt, multiimage_prompt, is_multiimage, seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps, multiimage_algo],
371
  outputs=[output_buf, video_output],
372
  ).then(
373
  lambda: tuple([gr.Button(interactive=True), gr.Button(interactive=True)]),
374
  outputs=[extract_glb_btn, extract_gs_btn],
375
  )
376
-
377
  video_output.clear(
378
  lambda: tuple([gr.Button(interactive=False), gr.Button(interactive=False)]),
379
  outputs=[extract_glb_btn, extract_gs_btn],
380
  )
381
-
382
  extract_glb_btn.click(
383
  extract_glb,
384
  inputs=[output_buf, mesh_simplify, texture_size],
@@ -396,12 +284,11 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
396
  lambda: gr.Button(interactive=True),
397
  outputs=[download_gs],
398
  )
399
-
400
  model_output.clear(
401
  lambda: gr.Button(interactive=False),
402
  outputs=[download_glb],
403
  )
404
-
405
 
406
  # Launch the Gradio app
407
  if __name__ == "__main__":
@@ -411,4 +298,4 @@ if __name__ == "__main__":
411
  pipeline.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8))) # Preload rembg
412
  except:
413
  pass
414
- demo.launch(show_error=True)
 
31
  shutil.rmtree(user_dir)
32
 
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  def preprocess_images(images: List[Tuple[Image.Image, str]]) -> List[Image.Image]:
 
 
 
 
 
 
 
 
 
35
  images = [image[0] for image in images]
36
  processed_images = [pipeline.preprocess_image(image) for image in images]
37
  return processed_images
 
78
 
79
 
80
  def get_seed(randomize_seed: bool, seed: int) -> int:
 
 
 
81
  return np.random.randint(0, MAX_SEED) if randomize_seed else seed
82
 
83
 
84
  @spaces.GPU
85
  def image_to_3d(
 
86
  multiimages: List[Tuple[Image.Image, str]],
87
  is_multiimage: bool,
88
  seed: int,
 
93
  multiimage_algo: Literal["multidiffusion", "stochastic"],
94
  req: gr.Request,
95
  ) -> Tuple[dict, str]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
97
  if not is_multiimage:
98
  outputs = pipeline.run(
 
142
  texture_size: int,
143
  req: gr.Request,
144
  ) -> Tuple[str, str]:
 
 
 
 
 
 
 
 
 
 
 
145
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
146
  gs, mesh = unpack_state(state)
147
  glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
 
153
 
154
  @spaces.GPU
155
  def extract_gaussian(state: dict, req: gr.Request) -> Tuple[str, str]:
 
 
 
 
 
 
 
 
 
156
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
157
  gs, _ = unpack_state(state)
158
  gaussian_path = os.path.join(user_dir, 'sample.ply')
 
174
  images.append(Image.fromarray(np.concatenate(_images, axis=1)))
175
  return images
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  with gr.Blocks(delete_cache=(600, 600)) as demo:
178
  gr.Markdown("""
179
  ## Image to 3D Asset with [TRELLIS](https://trellis3d.github.io/)
180
+ * Upload multiple images of an object from different views and click "Generate" to create a 3D asset.
181
  * If you find the generated 3D asset satisfactory, click "Extract GLB" to extract the GLB file and download it.
182
+ ✨New: Experimental multi-image support and Gaussian file extraction.
 
183
  """)
184
 
185
  with gr.Row():
186
  with gr.Column():
187
  with gr.Tabs() as input_tabs:
 
 
188
  with gr.Tab(label="Multiple Images", id=1) as multiimage_input_tab:
189
  multiimage_prompt = gr.Gallery(label="Image Prompt", format="png", type="pil", height=300, columns=3)
190
  gr.Markdown("""
191
+ Input different views of the object in separate images.
192
+ NOTE: this is an experimental algorithm without training a specialized model. It may not produce the best results for all images, especially those having different poses or inconsistent details.*
 
193
  """)
194
+
195
  with gr.Accordion(label="Generation Settings", open=False):
196
  seed = gr.Slider(0, MAX_SEED, label="Seed", value=0, step=1)
197
  randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
 
204
  slat_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=3.0, step=0.1)
205
  slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
206
  multiimage_algo = gr.Radio(["stochastic", "multidiffusion"], label="Multi-image Algorithm", value="stochastic")
207
+ generate_btn = gr.Button("Generate")
 
208
 
209
  with gr.Accordion(label="GLB Extraction Settings", open=False):
210
  mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify", value=0.95, step=0.01)
 
213
  with gr.Row():
214
  extract_glb_btn = gr.Button("Extract GLB", interactive=False)
215
  extract_gs_btn = gr.Button("Extract Gaussian", interactive=False)
216
+
217
  gr.Markdown("""
218
+ NOTE: Gaussian file can be very large (~50MB), it will take a while to display and download.*
219
+ """)
220
+
221
  with gr.Column():
222
  video_output = gr.Video(label="Generated 3D Asset", autoplay=True, loop=True, height=300)
223
  model_output = LitModel3D(label="Extracted GLB/Gaussian", exposure=10.0, height=300)
 
226
  download_glb = gr.DownloadButton(label="Download GLB", interactive=False)
227
  download_gs = gr.DownloadButton(label="Download Gaussian", interactive=False)
228
 
 
229
  output_buf = gr.State()
230
+
231
  # Example images at the bottom of the page
232
+ with gr.Row(visible=True) as multiimage_example:
 
 
 
 
 
 
 
 
 
 
 
 
233
  examples_multi = gr.Examples(
234
  examples=prepare_multi_example(),
235
+ inputs=[multiimage_prompt],
236
  fn=split_image,
237
  outputs=[multiimage_prompt],
238
  run_on_click=True,
239
  examples_per_page=8,
240
  )
241
+
242
  # Handlers
243
  demo.load(start_session)
244
  demo.unload(end_session)
245
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  multiimage_prompt.upload(
247
  preprocess_images,
248
  inputs=[multiimage_prompt],
249
  outputs=[multiimage_prompt],
250
  )
251
+
252
  generate_btn.click(
253
  get_seed,
254
  inputs=[randomize_seed, seed],
255
  outputs=[seed],
256
  ).then(
257
  image_to_3d,
258
+ inputs=[multiimage_prompt, seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps, multiimage_algo],
259
  outputs=[output_buf, video_output],
260
  ).then(
261
  lambda: tuple([gr.Button(interactive=True), gr.Button(interactive=True)]),
262
  outputs=[extract_glb_btn, extract_gs_btn],
263
  )
264
+
265
  video_output.clear(
266
  lambda: tuple([gr.Button(interactive=False), gr.Button(interactive=False)]),
267
  outputs=[extract_glb_btn, extract_gs_btn],
268
  )
269
+
270
  extract_glb_btn.click(
271
  extract_glb,
272
  inputs=[output_buf, mesh_simplify, texture_size],
 
284
  lambda: gr.Button(interactive=True),
285
  outputs=[download_gs],
286
  )
287
+
288
  model_output.clear(
289
  lambda: gr.Button(interactive=False),
290
  outputs=[download_glb],
291
  )
 
292
 
293
  # Launch the Gradio app
294
  if __name__ == "__main__":
 
298
  pipeline.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8))) # Preload rembg
299
  except:
300
  pass
301
+ demo.launch(show_error=True)