Spaces:
Runtime error
Runtime error
Update app.py
Browse files
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 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
|
253 |
-
|
254 |
-
|
|
|
|
|
|
|
|
|
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! [](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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
|
279 |
-
|
|
|
|
|
|
|
|
|
|
|
280 |
"""
|
281 |
|
|
|
|
|
|
|
282 |
|
283 |
with gr.Blocks() as demo:
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
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 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
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 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
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.
|
|
|
|
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()
|