ThomasSimonini HF staff commited on
Commit
dbbb9d0
·
verified ·
1 Parent(s): 16812a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -150
app.py CHANGED
@@ -13,6 +13,8 @@ from einops import rearrange, repeat
13
  from tqdm import tqdm
14
  from diffusers import DiffusionPipeline, EulerAncestralDiscreteScheduler
15
 
 
 
16
  from src.utils.train_util import instantiate_from_config
17
  from src.utils.camera_util import (
18
  FOV_to_intrinsics,
@@ -30,6 +32,9 @@ from huggingface_hub import hf_hub_download
30
  import gradio as gr
31
 
32
 
 
 
 
33
  def get_render_cameras(batch_size=1, M=120, radius=2.5, elevation=10.0, is_flexicubes=False):
34
  """
35
  Get the rendering camera parameters.
@@ -59,13 +64,6 @@ def images_to_video(images, output_path, fps=30):
59
  frames.append(frame)
60
  imageio.mimwrite(output_path, np.stack(frames), fps=fps, codec='h264')
61
 
62
-
63
- ###############################################################################
64
- # Configuration.
65
- ###############################################################################
66
-
67
- import shutil
68
-
69
  def find_cuda():
70
  # Check if CUDA_HOME or CUDA_PATH environment variables are set
71
  cuda_home = os.environ.get('CUDA_HOME') or os.environ.get('CUDA_PATH')
@@ -195,36 +193,7 @@ def make3d(images):
195
  with torch.no_grad():
196
  # get triplane
197
  planes = model.forward_planes(images, input_cameras)
198
-
199
- # # get video
200
- # chunk_size = 20 if IS_FLEXICUBES else 1
201
- # render_size = 384
202
 
203
- # frames = []
204
- # for i in tqdm(range(0, render_cameras.shape[1], chunk_size)):
205
- # if IS_FLEXICUBES:
206
- # frame = model.forward_geometry(
207
- # planes,
208
- # render_cameras[:, i:i+chunk_size],
209
- # render_size=render_size,
210
- # )['img']
211
- # else:
212
- # frame = model.synthesizer(
213
- # planes,
214
- # cameras=render_cameras[:, i:i+chunk_size],
215
- # render_size=render_size,
216
- # )['images_rgb']
217
- # frames.append(frame)
218
- # frames = torch.cat(frames, dim=1)
219
-
220
- # images_to_video(
221
- # frames[0],
222
- # video_fpath,
223
- # fps=30,
224
- # )
225
-
226
- # print(f"Video saved to {video_fpath}")
227
-
228
  # get mesh
229
  mesh_out = model.extract_mesh(
230
  planes,
@@ -243,148 +212,131 @@ def make3d(images):
243
  return mesh_fpath, mesh_glb_fpath
244
 
245
 
246
- _HEADER_ = '''
247
- <h2><b>Official 🤗 Gradio Demo</b></h2><h2><a href='https://github.com/TencentARC/InstantMesh' target='_blank'><b>InstantMesh: Efficient 3D Mesh Generation from a Single Image with Sparse-view Large Reconstruction Models</b></a></h2>
248
-
249
- **InstantMesh** is a feed-forward framework for efficient 3D mesh generation from a single image based on the LRM/Instant3D architecture.
250
-
251
- Code: <a href='https://github.com/TencentARC/InstantMesh' target='_blank'>GitHub</a>. Techenical report: <a href='https://arxiv.org/abs/2404.07191' target='_blank'>ArXiv</a>.
 
 
 
 
 
 
 
252
 
253
- ❗️❗️❗️**Important Notes:**
254
- - Our demo can export a .obj mesh with vertex colors or a .glb mesh now. If you prefer to export a .obj mesh with a **texture map**, please refer to our <a href='https://github.com/TencentARC/InstantMesh?tab=readme-ov-file#running-with-command-line' target='_blank'>Github Repo</a>.
 
 
 
 
255
  - The 3D mesh generation results highly depend on the quality of generated multi-view images. Please try a different **seed value** if the result is unsatisfying (Default: 42).
256
- '''
257
-
258
- _CITE_ = r"""
259
- If InstantMesh is helpful, please help to ⭐ the <a href='https://github.com/TencentARC/InstantMesh' target='_blank'>Github Repo</a>. Thanks! [![GitHub Stars](https://img.shields.io/github/stars/TencentARC/InstantMesh?style=social)](https://github.com/TencentARC/InstantMesh)
260
- ---
261
- 📝 **Citation**
262
-
263
- If you find our work useful for your research or applications, please cite using this bibtex:
264
- ```bibtex
265
- @article{xu2024instantmesh,
266
- title={InstantMesh: Efficient 3D Mesh Generation from a Single Image with Sparse-view Large Reconstruction Models},
267
- author={Xu, Jiale and Cheng, Weihao and Gao, Yiming and Wang, Xintao and Gao, Shenghua and Shan, Ying},
268
- journal={arXiv preprint arXiv:2404.07191},
269
- year={2024}
270
- }
271
- ```
272
-
273
- 📋 **License**
274
-
275
- Apache-2.0 LICENSE. Please refer to the [LICENSE file](https://huggingface.co/spaces/TencentARC/InstantMesh/blob/main/LICENSE) for details.
276
 
277
- 📧 **Contact**
 
 
 
 
 
 
 
 
278
 
279
- If you have any questions, feel free to open a discussion or contact us at <b>bluestyle928@gmail.com</b>.
 
 
 
 
 
280
  """
281
 
 
 
 
282
 
283
  with gr.Blocks() as demo:
284
- gr.Markdown(_HEADER_)
285
- with gr.Row(variant="panel"):
286
- with gr.Column():
287
- with gr.Row():
288
- input_image = gr.Image(
289
- label="Input Image",
290
- image_mode="RGBA",
291
- sources="upload",
292
- #width=256,
293
- #height=256,
294
- type="pil",
295
- elem_id="content_image",
296
- )
297
- processed_image = gr.Image(
298
- label="Processed Image",
299
- image_mode="RGBA",
300
- #width=256,
301
- #height=256,
302
- type="pil",
303
- interactive=False
304
- )
305
- with gr.Row():
306
- with gr.Group():
307
- do_remove_background = gr.Checkbox(
308
- label="Remove Background", value=True
309
- )
310
- sample_seed = gr.Number(value=42, label="Seed Value", precision=0)
311
-
312
- sample_steps = gr.Slider(
313
  label="Sample Steps",
314
  minimum=30,
315
  maximum=75,
316
  value=75,
317
  step=5
318
  )
319
-
320
- with gr.Row():
321
- submit = gr.Button("Generate", elem_id="generate", variant="primary")
322
-
323
- with gr.Row(variant="panel"):
324
- gr.Examples(
325
- examples=[
326
- os.path.join("examples", img_name) for img_name in sorted(os.listdir("examples"))
327
- ],
328
- inputs=[input_image],
329
- label="Examples",
330
- cache_examples=False,
331
- examples_per_page=16
332
- )
333
-
334
- with gr.Column():
335
-
336
- with gr.Row():
337
-
338
- with gr.Column():
339
- mv_show_images = gr.Image(
340
  label="Generated Multi-views",
341
  type="pil",
342
  width=379,
343
  interactive=False
344
  )
345
-
346
- # with gr.Column():
347
- # output_video = gr.Video(
348
- # label="video", format="mp4",
349
- # width=379,
350
- # autoplay=True,
351
- # interactive=False
352
- # )
353
-
354
- with gr.Row():
355
- with gr.Tab("OBJ"):
356
- output_model_obj = gr.Model3D(
357
- label="Output Model (OBJ Format)",
358
- interactive=False,
359
- )
360
- gr.Markdown("Note: Downloaded .obj model will be flipped. Export .glb instead or manually flip it before usage.")
361
- with gr.Tab("GLB"):
362
- output_model_glb = gr.Model3D(
363
- label="Output Model (GLB Format)",
364
- interactive=False,
365
- )
366
- gr.Markdown("Note: The model shown here has a darker appearance. Download to get correct results.")
367
-
368
- with gr.Row():
369
- gr.Markdown('''Try a different <b>seed value</b> if the result is unsatisfying (Default: 42).''')
370
-
371
- gr.Markdown(_CITE_)
372
-
373
- mv_images = gr.State()
374
-
375
- submit.click(fn=check_input_image, inputs=[input_image]).success(
376
  fn=preprocess,
377
  inputs=[input_image, do_remove_background],
378
  outputs=[processed_image],
379
  ).success(
380
  fn=generate_mvs,
381
  inputs=[processed_image, sample_steps, sample_seed],
382
- outputs=[mv_images, mv_show_images]
383
-
384
  ).success(
385
  fn=make3d,
386
  inputs=[mv_images],
387
  outputs=[output_model_obj, output_model_glb]
388
  )
 
 
 
389
 
390
- demo.launch()
 
 
13
  from tqdm import tqdm
14
  from diffusers import DiffusionPipeline, EulerAncestralDiscreteScheduler
15
 
16
+ # Imports for InstantMesh
17
+ import shutil
18
  from src.utils.train_util import instantiate_from_config
19
  from src.utils.camera_util import (
20
  FOV_to_intrinsics,
 
32
  import gradio as gr
33
 
34
 
35
+ ###############################################################################
36
+ # Configuration for InstantMesh
37
+ ###############################################################################
38
  def get_render_cameras(batch_size=1, M=120, radius=2.5, elevation=10.0, is_flexicubes=False):
39
  """
40
  Get the rendering camera parameters.
 
64
  frames.append(frame)
65
  imageio.mimwrite(output_path, np.stack(frames), fps=fps, codec='h264')
66
 
 
 
 
 
 
 
 
67
  def find_cuda():
68
  # Check if CUDA_HOME or CUDA_PATH environment variables are set
69
  cuda_home = os.environ.get('CUDA_HOME') or os.environ.get('CUDA_PATH')
 
193
  with torch.no_grad():
194
  # get triplane
195
  planes = model.forward_planes(images, input_cameras)
 
 
 
 
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  # get mesh
198
  mesh_out = model.extract_mesh(
199
  planes,
 
212
  return mesh_fpath, mesh_glb_fpath
213
 
214
 
215
+ ###############################################################################
216
+ # Gradio
217
+ ###############################################################################
218
+ HEADER = """
219
+ # Generate 3D Assets for Roblox
220
+ With this Space, you can generate 3D Assets using AI for your Roblox game for free.
221
+ Simply follow the 4 steps below.
222
+ 1. Generate a 3D Mesh using an image model as input.
223
+ 2. Simplify the Mesh to get lower polygon number
224
+ 3. (Optional) make the Mesh more smooth
225
+ 4. Get the Material
226
+ We wrote a tutorial here
227
+ """
228
 
229
+ STEP1_HEADER = """
230
+ ## Step 1: Generate the 3D Mesh
231
+ For this step, we use <a href='https://github.com/TencentARC/InstantMesh' target='_blank'>InstantMesh</a>, an open-source model for **fast** feedforward 3D mesh generation from a single image.
232
+ During this step, you need to upload an image of what you want to generate a 3D Model from.
233
+ ## 💡 Tips
234
+ - If there's a background, ✅ Remove background.
235
  - The 3D mesh generation results highly depend on the quality of generated multi-view images. Please try a different **seed value** if the result is unsatisfying (Default: 42).
236
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
+ STEP2_HEADER = """
239
+ ## Step 2: Simplify the generated 3D Mesh
240
+ ADD ILLUSTRATION
241
+ The 3D Mesh Generated contains too much polygons, fortunately, we can use another AI model to help us optimize it.
242
+ The model we use is called [MeshAnythingV2]().
243
+ ## 💡 Tips
244
+ - We don't click on Preprocess with marching Cubes, because in the last step the input mesh was produced by it.
245
+ - Limited by computational resources, MeshAnything is trained on meshes with fewer than 1600 faces and cannot generate meshes with more than 1600 faces. The shape of the input mesh should be sharp enough; otherwise, it will be challenging to represent it with only 1600 faces. Thus, feed-forward image-to-3D methods may often produce bad results due to insufficient shape quality.
246
+ """
247
 
248
+ STEP3_HEADER = """
249
+ ## Step 3 (optional): Shader Smooth
250
+ - The mesh simplified in step 2, looks low poly. One way to make it more smooth is to use Shader Smooth.
251
+ - You can usually do it in Blender, but we can do it directly here
252
+ ADD ILLUSTRATION
253
+ ADD SHADERSMOOTH
254
  """
255
 
256
+ STEP4_HEADER = """
257
+ ## Step 4: Get the Mesh Material
258
+ """
259
 
260
  with gr.Blocks() as demo:
261
+ gr.Markdown(HEADER)
262
+ gr.Markdown(STEP1_HEADER)
263
+ with gr.Row(variant = "panel"):
264
+ with gr.Column():
265
+ with gr.Row():
266
+ input_image = gr.Image(
267
+ label = "Input Image",
268
+ image_mode = "RGBA",
269
+ sources = "upload",
270
+ type="pil",
271
+ elem_id="content_image"
272
+ )
273
+ processed_image = gr.Image(label="Processed Image",
274
+ image_mode="RGBA",
275
+ type="pil",
276
+ interactive=False
277
+ )
278
+ with gr.Row():
279
+ with gr.Group():
280
+ do_remove_background = gr.Checkbox(
281
+ label="Remove Background",
282
+ value=True)
283
+ sample_seed = gr.Number(
284
+ value=42,
285
+ label="Seed Value",
286
+ precision=0
287
+ )
288
+ sample_steps = gr.Slider(
 
289
  label="Sample Steps",
290
  minimum=30,
291
  maximum=75,
292
  value=75,
293
  step=5
294
  )
295
+ with gr.Row():
296
+ step1_submit = gr.Button("Generate", elem_id="generate", variant="primary")
297
+ with gr.Column():
298
+ with gr.Row():
299
+ with gr.Column():
300
+ mv_show_images = gr.Image(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  label="Generated Multi-views",
302
  type="pil",
303
  width=379,
304
  interactive=False
305
  )
306
+ with gr.Column():
307
+ with gr.Tab("OBJ"):
308
+ output_model_obj = gr.Model3D(
309
+ label = "Output Model (OBJ Format)",
310
+ interactive = False,
311
+ )
312
+ gr.Markdown("Note: Downloaded object will be flipped in case of .obj export. Export .glb instead or manually flip it before usage.")
313
+ with gr.Tab("GLB"):
314
+ output_model_glb = gr.Model3D(
315
+ label="Output Model (GLB Format)",
316
+ interactive=False,
317
+ )
318
+ gr.Markdown("Note: The model shown here has a darker appearance. Download to get correct results.")
319
+ with gr.Row():
320
+ gr.Markdown('''Try a different <b>seed value</b> if the result is unsatisfying (Default: 42).''')
321
+
322
+ mv_images = gr.State()
323
+
324
+ step1_submit.click(fn=check_input_image, inputs=[input_image]).success(
 
 
 
 
 
 
 
 
 
 
 
 
325
  fn=preprocess,
326
  inputs=[input_image, do_remove_background],
327
  outputs=[processed_image],
328
  ).success(
329
  fn=generate_mvs,
330
  inputs=[processed_image, sample_steps, sample_seed],
331
+ outputs=[mv_images, mv_show_images],
 
332
  ).success(
333
  fn=make3d,
334
  inputs=[mv_images],
335
  outputs=[output_model_obj, output_model_glb]
336
  )
337
+ gr.Markdown(STEP2_HEADER)
338
+ gr.Markdown(STEP3_HEADER)
339
+ gr.Markdown(STEP4_HEADER)
340
 
341
+ demo.queue(max_size=10)
342
+ demo.launch()