Xinyue Wei commited on
Commit
d15f2fb
·
1 Parent(s): 61e220b
Dockerfile ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ LABEL version="1.0.2"
4
+
5
+ ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
6
+ ENV TZ=America/Los_Angeles
7
+ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
8
+
9
+ RUN apt-get update && apt-get install -y --no-install-recommends \
10
+ curl \
11
+ libx11-6 \
12
+ libxrender1 \
13
+ libxxf86vm1 \
14
+ libxfixes3 \
15
+ libxi6 \
16
+ libxkbcommon0 \
17
+ libgomp1 \
18
+ libsm6 \
19
+ libgl1
20
+
21
+ RUN pip3 install --no-cache-dir \
22
+ numpy \
23
+ trimesh \
24
+ Pillow \
25
+ gradio==4.41.0 \
26
+ bpy \
27
+ scipy
28
+
29
+ # Set up a new user named "user" with user ID 1000
30
+ RUN useradd -m -u 1000 user
31
+ # Switch to the "user" user
32
+ USER user
33
+ # Set home to the user's home directory
34
+ ENV HOME=/home/user \
35
+ PATH=/home/user/.local/bin:$PATH \
36
+ PYTHONPATH=$HOME/app \
37
+ PYTHONUNBUFFERED=1 \
38
+ SYSTEM=spaces
39
+ # Set the working directory to the user's home directory
40
+ WORKDIR $HOME/app
41
+ # Copy the current directory contents into the container at $HOME/app setting the owner to the user
42
+ COPY --chown=user . $HOME/app
43
+
44
+ RUN pip3 install gradio_model3dcolor-0.0.1-py3-none-any.whl
45
+ RUN pip3 install gradio_model3dnormal-0.0.1-py3-none-any.whl
46
+
47
+ CMD ["python3", "launch.py"]
README.md CHANGED
@@ -1,10 +1,11 @@
1
  ---
2
- title: MeshLRM
3
- emoji: 💻
4
- colorFrom: green
5
- colorTo: gray
6
  sdk: docker
7
- pinned: false
 
8
  license: cc-by-nc-4.0
9
  ---
10
 
 
1
  ---
2
+ title: MeshLRM (Unofficial)
3
+ emoji: 🐯
4
+ colorFrom: yellow
5
+ colorTo: pink
6
  sdk: docker
7
+ header: mini
8
+ pinned: true
9
  license: cc-by-nc-4.0
10
  ---
11
 
gradio_model3dcolor-0.0.1-py3-none-any.whl ADDED
Binary file (995 kB). View file
 
gradio_model3dnormal-0.0.1-py3-none-any.whl ADDED
Binary file (995 kB). View file
 
launch.py ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import uuid
5
+ import numpy as np
6
+ import gradio as gr
7
+ import trimesh
8
+ import zipfile
9
+ import subprocess
10
+ from datetime import datetime
11
+ from functools import partial
12
+ from PIL import Image, ImageChops
13
+ from huggingface_hub import snapshot_download
14
+
15
+ from gradio_model3dcolor import Model3DColor
16
+ from gradio_model3dnormal import Model3DNormal
17
+
18
+ is_local_run = os.path.exists("../MeshLRM-API")
19
+ code_dir = (
20
+ snapshot_download("sudo-ai/MeshLRM-API", token=os.environ["HF_TOKEN"])
21
+ if not is_local_run
22
+ else "../MeshLRM-API"
23
+ )
24
+
25
+ if not is_local_run:
26
+ zip_file_path = f"{code_dir}/examples.zip"
27
+ # Unzipping the file into the current directory
28
+ with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
29
+ zip_ref.extractall(os.getcwd())
30
+
31
+ with open(f"{code_dir}/api.json", "r") as file:
32
+ api_dict = json.load(file)
33
+ SEGM_i_CALL = api_dict["SEGM_i_CALL"]
34
+ SEGM_CALL = api_dict["SEGM_CALL"]
35
+ UNPOSED_CALL = api_dict["UNPOSED_CALL"]
36
+ MESH_CALL = api_dict["MESH_CALL"]
37
+
38
+
39
+ _TITLE = (
40
+ """[Reproduced] MeshLRM: Large Reconstruction Model for High-Quality Meshes"""
41
+ )
42
+ _LINK = (
43
+ """<a href="https://arxiv.org/abs/2404.12385">[Arxiv]<a/> <a href="https://sarahweiii.github.io/meshlrm/">[Project]<a/> (This is the unofficial MeshLRM demo reproduced in Hillbot)"""
44
+ )
45
+ _DESCRIPTION = (
46
+ """Try MeshLRM to reconstruct 3D textured mesh from one or a few unposed images! Thanks to <a href=https://chaoxu.xyz/sparp/>SpaRP<a> for generating multi-view images from unposed images."""
47
+ )
48
+ _PR = """
49
+ <div>
50
+ <b>Check out <a href="https://www.sudo.ai/3dgen">Hillbot (sudoAI)</a> for more details and advanced features.</b>
51
+ </div>
52
+ """
53
+
54
+
55
+ STYLE = """
56
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
57
+ <style>
58
+ .alert, .alert div, .alert b {
59
+ color: black !important;
60
+ }
61
+ </style>
62
+ """
63
+ # info (info-circle-fill), cursor (hand-index-thumb), wait (hourglass-split), done (check-circle)
64
+ ICONS = {
65
+ "info": """<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#0d6efd" class="bi bi-info-circle-fill flex-shrink-0 me-2" viewBox="0 0 16 16">
66
+ <path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
67
+ </svg>""",
68
+ "cursor": """<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#0dcaf0" class="bi bi-hand-index-thumb-fill flex-shrink-0 me-2" viewBox="0 0 16 16">
69
+ <path d="M8.5 1.75v2.716l.047-.002c.312-.012.742-.016 1.051.046.28.056.543.18.738.288.273.152.456.385.56.642l.132-.012c.312-.024.794-.038 1.158.108.37.148.689.487.88.716.075.09.141.175.195.248h.582a2 2 0 0 1 1.99 2.199l-.272 2.715a3.5 3.5 0 0 1-.444 1.389l-1.395 2.441A1.5 1.5 0 0 1 12.42 16H6.118a1.5 1.5 0 0 1-1.342-.83l-1.215-2.43L1.07 8.589a1.517 1.517 0 0 1 2.373-1.852L5 8.293V1.75a1.75 1.75 0 0 1 3.5 0z"/>
70
+ </svg>""",
71
+ "wait": """<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#6c757d" class="bi bi-hourglass-split flex-shrink-0 me-2" viewBox="0 0 16 16">
72
+ <path d="M2.5 15a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1h-11zm2-13v1c0 .537.12 1.045.337 1.5h6.326c.216-.455.337-.963.337-1.5V2h-7zm3 6.35c0 .701-.478 1.236-1.011 1.492A3.5 3.5 0 0 0 4.5 13s.866-1.299 3-1.48V8.35zm1 0v3.17c2.134.181 3 1.48 3 1.48a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351z"/>
73
+ </svg>""",
74
+ "done": """<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#198754" class="bi bi-check-circle-fill flex-shrink-0 me-2" viewBox="0 0 16 16">
75
+ <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
76
+ </svg>""",
77
+ }
78
+
79
+ icons2alert = {
80
+ "info": "primary", # blue
81
+ "cursor": "info", # light blue
82
+ "wait": "secondary", # gray
83
+ "done": "success", # green
84
+ }
85
+
86
+
87
+ def message(text, icon_type="info"):
88
+ return f"""{STYLE} <div class="alert alert-{icons2alert[icon_type]} d-flex align-items-center" role="alert"> {ICONS[icon_type]}
89
+ <div>
90
+ {text}
91
+ </div>
92
+ </div>"""
93
+
94
+
95
+ def create_tmp_dir():
96
+ tmp_dir = (
97
+ "../demo_exp/"
98
+ + datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
99
+ + "_"
100
+ + str(uuid.uuid4())[:4]
101
+ )
102
+ os.makedirs(tmp_dir, exist_ok=True)
103
+ print("create tmp_exp_dir", tmp_dir)
104
+ return tmp_dir
105
+
106
+
107
+ def preprocess_imgs(tmp_dir, input_img):
108
+ for i, img_tuple in enumerate(input_img):
109
+ img = Image.open(img_tuple[0])
110
+ img.thumbnail([2048, 2048], Image.Resampling.LANCZOS)
111
+ img.save(f"{tmp_dir}/input_{i}.png")
112
+ os.system(SEGM_i_CALL.replace("{tmp_dir}", tmp_dir).replace("{i}", str(i)))
113
+ return [Image.open(f"{tmp_dir}/seg_{i}.png") for i in range(len(input_img))]
114
+
115
+
116
+ def ply_to_glb(ply_path):
117
+ script_path = f"{code_dir}/ply2glb.py"
118
+ result = subprocess.run(
119
+ ["python", script_path, "--", ply_path],
120
+ capture_output=True,
121
+ text=True,
122
+ )
123
+
124
+ print("Output of blender script:")
125
+ print(result.stdout)
126
+
127
+ glb_path = ply_path.replace(".ply", ".glb")
128
+ return glb_path
129
+
130
+
131
+ def mesh_gen(tmp_dir, use_seg):
132
+ os.system(
133
+ UNPOSED_CALL.replace("{tmp_dir}", tmp_dir).replace("{use_seg}", str(use_seg))
134
+ )
135
+ os.system(MESH_CALL.replace("{tmp_dir}", tmp_dir))
136
+
137
+ mesh = trimesh.load_mesh(f"{tmp_dir}/mesh.ply")
138
+ vertex_normals = mesh.vertex_normals
139
+ colors = (-vertex_normals + 1) / 2.0
140
+ colors = colors[:, [2, 1, 0]]
141
+ colors = (colors * 255).astype(np.uint8) # Convert to 8-bit color
142
+ mesh.visual.vertex_colors = colors
143
+ mesh.export(f"{tmp_dir}/mesh_normal.ply", file_type="ply")
144
+
145
+ color_path = ply_to_glb(f"{tmp_dir}/mesh.ply")
146
+ normal_path = ply_to_glb(f"{tmp_dir}/mesh_normal.ply")
147
+
148
+ return color_path, normal_path
149
+
150
+
151
+ def feed_example_to_gallery(img):
152
+ for idx, display_img in enumerate(display_imgs):
153
+ display_img = display_img[0]
154
+ if img.size != display_img.size:
155
+ continue
156
+ diff = ImageChops.difference(img, display_img)
157
+ if not diff.getbbox(): # two images are the same and the same size
158
+ img_id = display_img.filename
159
+ data_dir = os.path.join(data_folder, str(img_id))
160
+ data_fns = os.listdir(data_dir)
161
+ data_fns.sort()
162
+ data_imgs = []
163
+ for data_fn in data_fns:
164
+ file_path = os.path.join(data_dir, data_fn)
165
+ img = Image.open(file_path)
166
+ data_imgs.append(img)
167
+ return data_imgs
168
+ return [img]
169
+
170
+
171
+ custom_theme = gr.themes.Soft(primary_hue="blue").set(
172
+ button_secondary_background_fill="*neutral_100",
173
+ button_secondary_background_fill_hover="*neutral_200",
174
+ )
175
+
176
+ # Gradio blocks
177
+ with gr.Blocks(title=_TITLE, css="style.css", theme=custom_theme) as demo:
178
+ tmp_dir_unposed = gr.State("./demo_exp/placeholder")
179
+ display_folder = os.path.join(os.path.dirname(__file__), "examples_display")
180
+ display_fns = os.listdir(display_folder)
181
+ display_fns.sort()
182
+ display_imgs = []
183
+ for i, display_fn in enumerate(display_fns):
184
+ file_path = os.path.join(display_folder, display_fn)
185
+ img = Image.open(file_path)
186
+ img.filename = f"{i:02}"
187
+ if np.array(img).shape[-1] == 3:
188
+ img.putalpha(255)
189
+ display_imgs.append([img])
190
+ data_folder = os.path.join(os.path.dirname(__file__), "examples_data")
191
+
192
+ # UI
193
+ with gr.Row():
194
+ gr.Markdown("# " + _TITLE)
195
+ with gr.Row():
196
+ gr.Markdown("### " + _LINK)
197
+ with gr.Row():
198
+ gr.Markdown("### " + _DESCRIPTION)
199
+ with gr.Row():
200
+ gr.Markdown(_PR)
201
+ with gr.Row():
202
+ guide_text = gr.HTML(
203
+ message("Input image(s) of object that you want to generate mesh with.")
204
+ )
205
+ with gr.Row(variant="panel"):
206
+ with gr.Column():
207
+ with gr.Row():
208
+ with gr.Column(scale=5):
209
+ input_gallery = gr.Gallery(
210
+ label="Input Images",
211
+ show_label=False,
212
+ columns=[3],
213
+ rows=[2],
214
+ object_fit="contain",
215
+ height=400,
216
+ show_share_button=False,
217
+ )
218
+ input_image = gr.Image(
219
+ type="pil",
220
+ image_mode="RGBA",
221
+ visible=False,
222
+ )
223
+ with gr.Column(scale=5):
224
+ processed_gallery = gr.Gallery(
225
+ label="Background Removal",
226
+ columns=[3],
227
+ rows=[2],
228
+ object_fit="contain",
229
+ height=400,
230
+ interactive=False,
231
+ show_share_button=False,
232
+ )
233
+ with gr.Row():
234
+ with gr.Column(scale=5):
235
+ example = gr.Examples(
236
+ examples=display_imgs,
237
+ inputs=[input_image],
238
+ outputs=[input_gallery],
239
+ fn=feed_example_to_gallery,
240
+ label="Image Examples (Click one of the images below to start)",
241
+ examples_per_page=30,
242
+ run_on_click=True,
243
+ )
244
+ with gr.Column(scale=5):
245
+ with gr.Row():
246
+ bg_removed_checkbox = gr.Checkbox(
247
+ value=True,
248
+ label="Use background removed images (uncheck to use original)",
249
+ interactive=True,
250
+ )
251
+ with gr.Row():
252
+ run_btn = gr.Button(
253
+ "Generate",
254
+ variant="primary",
255
+ interactive=False,
256
+ )
257
+ with gr.Row():
258
+ with gr.Column(scale=5):
259
+ mesh_output = Model3DColor(
260
+ label="Generated Mesh (color)",
261
+ elem_id="mesh-out",
262
+ height=400,
263
+ )
264
+ with gr.Column(scale=5):
265
+ mesh_output_normal = Model3DNormal(
266
+ label="Generated Mesh (normal)",
267
+ elem_id="mesh-normal-out",
268
+ height=400,
269
+ )
270
+
271
+ # Callbacks
272
+ generating_mesh = gr.State(False)
273
+
274
+ disable_button = lambda: gr.Button(interactive=False)
275
+ enable_button = lambda: gr.Button(interactive=True)
276
+ update_guide = lambda GUIDE_TEXT, icon_type="info": gr.HTML(
277
+ value=message(GUIDE_TEXT, icon_type)
278
+ )
279
+
280
+ def is_cleared(content):
281
+ if content:
282
+ raise ValueError # gr.Error(visible=False) doesn't work, trick for not showing error message
283
+
284
+ def not_cleared(content):
285
+ if not content:
286
+ raise ValueError
287
+
288
+ def toggle_mesh_generation_status(generating_mesh):
289
+ generating_mesh = not generating_mesh
290
+ return generating_mesh
291
+
292
+ def is_generating_mesh(generating_mesh):
293
+ if generating_mesh:
294
+ raise ValueError
295
+
296
+ # Upload event listener for input gallery
297
+ input_gallery.upload(
298
+ fn=disable_button,
299
+ outputs=[run_btn],
300
+ queue=False,
301
+ ).success(
302
+ fn=create_tmp_dir,
303
+ outputs=[tmp_dir_unposed],
304
+ queue=True,
305
+ ).success(
306
+ fn=partial(
307
+ update_guide, "Removing background of the input image(s)...", "wait"
308
+ ),
309
+ outputs=[guide_text],
310
+ queue=False,
311
+ ).success(
312
+ fn=preprocess_imgs,
313
+ inputs=[tmp_dir_unposed, input_gallery],
314
+ outputs=[processed_gallery],
315
+ queue=True,
316
+ ).success(
317
+ fn=partial(update_guide, "Click <b>Generate</b> to generate mesh.", "cursor"),
318
+ outputs=[guide_text],
319
+ queue=False,
320
+ ).success(
321
+ fn=is_generating_mesh,
322
+ inputs=[generating_mesh],
323
+ queue=False,
324
+ ).success(
325
+ fn=enable_button,
326
+ outputs=[run_btn],
327
+ queue=False,
328
+ )
329
+
330
+ # Clear event listener for input gallery
331
+ input_gallery.change(
332
+ fn=is_cleared,
333
+ inputs=[input_gallery],
334
+ queue=False,
335
+ ).success(
336
+ fn=disable_button,
337
+ outputs=[run_btn],
338
+ queue=False,
339
+ ).success(
340
+ fn=lambda: None,
341
+ outputs=[input_image],
342
+ queue=False,
343
+ ).success(
344
+ fn=lambda: None,
345
+ outputs=[processed_gallery],
346
+ queue=False,
347
+ ).success(
348
+ fn=partial(
349
+ update_guide,
350
+ "Input image(s) of object that you want to generate mesh with.",
351
+ "info",
352
+ ),
353
+ outputs=[guide_text],
354
+ queue=False,
355
+ )
356
+
357
+ # Change event listener for input image
358
+ input_image.change(
359
+ fn=not_cleared,
360
+ inputs=[input_image],
361
+ queue=False,
362
+ ).success(
363
+ fn=disable_button,
364
+ outputs=run_btn,
365
+ queue=False,
366
+ ).success(
367
+ fn=create_tmp_dir,
368
+ outputs=tmp_dir_unposed,
369
+ queue=True,
370
+ ).success(
371
+ fn=partial(
372
+ update_guide, "Removing background of the input image(s)...", "wait"
373
+ ),
374
+ outputs=[guide_text],
375
+ queue=False,
376
+ ).success(
377
+ fn=preprocess_imgs,
378
+ inputs=[tmp_dir_unposed, input_gallery],
379
+ outputs=[processed_gallery],
380
+ queue=True,
381
+ ).success(
382
+ fn=partial(update_guide, "Click <b>Generate</b> to generate mesh.", "cursor"),
383
+ outputs=[guide_text],
384
+ queue=False,
385
+ ).success(
386
+ fn=is_generating_mesh,
387
+ inputs=[generating_mesh],
388
+ queue=False,
389
+ ).success(
390
+ fn=enable_button,
391
+ outputs=run_btn,
392
+ queue=False,
393
+ )
394
+
395
+ # Click event listener for run button
396
+ run_btn.click(
397
+ fn=disable_button,
398
+ outputs=[run_btn],
399
+ queue=False,
400
+ ).success(
401
+ fn=lambda: None,
402
+ outputs=[mesh_output],
403
+ queue=False,
404
+ ).success(
405
+ fn=lambda: None,
406
+ outputs=[mesh_output_normal],
407
+ queue=False,
408
+ ).success(
409
+ fn=partial(update_guide, "Generating the mesh...", "wait"),
410
+ outputs=[guide_text],
411
+ queue=False,
412
+ ).success(
413
+ fn=toggle_mesh_generation_status,
414
+ inputs=[generating_mesh],
415
+ outputs=[generating_mesh],
416
+ queue=False,
417
+ ).success(
418
+ fn=mesh_gen,
419
+ inputs=[tmp_dir_unposed, bg_removed_checkbox],
420
+ outputs=[mesh_output, mesh_output_normal],
421
+ queue=True,
422
+ ).success(
423
+ fn=toggle_mesh_generation_status,
424
+ inputs=[generating_mesh],
425
+ outputs=[generating_mesh],
426
+ queue=False,
427
+ ).success(
428
+ fn=partial(
429
+ update_guide,
430
+ "Successfully generated the mesh. (It might take a few seconds to load the mesh)",
431
+ "done",
432
+ ),
433
+ outputs=[guide_text],
434
+ queue=False,
435
+ ).success(
436
+ fn=not_cleared,
437
+ inputs=[input_gallery],
438
+ queue=False,
439
+ ).success(
440
+ fn=enable_button,
441
+ outputs=[run_btn],
442
+ queue=False,
443
+ )
444
+
445
+ demo.queue().launch(
446
+ debug=False,
447
+ share=False,
448
+ inline=False,
449
+ show_api=False,
450
+ server_name="0.0.0.0",
451
+ )
style.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .centered {
2
+ text-align: center; /* Horizontally center the content */
3
+ }
4
+
5
+ .centered img {
6
+ display: block; /* Make the image a block element */
7
+ margin: 0 auto; /* Center the block element (the image) horizontally */
8
+ height: 100px;
9
+ }
10
+
11
+ .tab_at_top button.selected{
12
+ font-size: 24px !important;
13
+ }