wyysf commited on
Commit
d135458
1 Parent(s): b02227e
Files changed (2) hide show
  1. gradio_app.py +5 -4
  2. gradio_app_crm.py +0 -279
gradio_app.py CHANGED
@@ -16,6 +16,7 @@ from einops import repeat, rearrange
16
  import pytorch_lightning as pl
17
  from typing import Dict, Optional, Tuple, List
18
  import gradio as gr
 
19
 
20
  proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21
  sys.path.append(os.path.join(proj_dir))
@@ -232,10 +233,10 @@ if __name__=="__main__":
232
  view_back = gr.Image(label="Back", interactive=True, show_label=True)
233
  view_left = gr.Image(label="Left", interactive=True, show_label=True)
234
 
235
- # with gr.Accordion('Advanced options', open=False):
236
- with gr.Row(equal_height=True):
237
- run_mv_btn = gr.Button('Only Generate 2D', interactive=True)
238
- run_3d_btn = gr.Button('Only Generate 3D', interactive=True)
239
 
240
  with gr.Accordion('Advanced options (2D)', open=False):
241
  with gr.Row():
 
16
  import pytorch_lightning as pl
17
  from typing import Dict, Optional, Tuple, List
18
  import gradio as gr
19
+ from typing import Any
20
 
21
  proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
22
  sys.path.append(os.path.join(proj_dir))
 
233
  view_back = gr.Image(label="Back", interactive=True, show_label=True)
234
  view_left = gr.Image(label="Left", interactive=True, show_label=True)
235
 
236
+ with gr.Accordion('Advanced options', open=False):
237
+ with gr.Row(equal_height=True):
238
+ run_mv_btn = gr.Button('Only Generate 2D', interactive=True)
239
+ run_3d_btn = gr.Button('Only Generate 3D', interactive=True)
240
 
241
  with gr.Accordion('Advanced options (2D)', open=False):
242
  with gr.Row():
gradio_app_crm.py DELETED
@@ -1,279 +0,0 @@
1
- import spaces
2
- import argparse
3
- import os
4
- import json
5
- import torch
6
- import sys
7
- import time
8
- import importlib
9
- import numpy as np
10
- from omegaconf import OmegaConf
11
- from huggingface_hub import hf_hub_download
12
-
13
- from collections import OrderedDict
14
- import trimesh
15
- from einops import repeat, rearrange
16
- import pytorch_lightning as pl
17
- from typing import Dict, Optional, Tuple, List
18
- import gradio as gr
19
-
20
- proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21
- sys.path.append(os.path.join(proj_dir))
22
-
23
- import tempfile
24
- import craftsman
25
- from craftsman.systems.base import BaseSystem
26
- from craftsman.utils.config import ExperimentConfig, load_config
27
-
28
- from apps.utils import *
29
- from apps.mv_models import GenMVImage
30
-
31
- _TITLE = '''CraftsMan: High-fidelity Mesh Generation with 3D Native Generation and Interactive Geometry Refiner'''
32
- _DESCRIPTION = '''
33
- <div>
34
- Select or upload a image, then just click 'Generate'.
35
- <br>
36
- By mimicking the artist/craftsman modeling workflow, we propose CraftsMan (aka 匠心) that uses 3D Latent Set Diffusion Model that directly generate coarse meshes,
37
- then a multi-view normal enhanced image generation model is used to refine the mesh.
38
- We provide the coarse 3D diffusion part here.
39
- <br>
40
- If you found Crafts is helpful, please help to ⭐ the <a href='https://github.com/wyysf-98/CraftsMan/' target='_blank'>Github Repo</a>. Thanks!
41
- <a style="display:inline-block; margin-left: .5em" href='https://github.com/wyysf-98/CraftsMan/'><img src='https://img.shields.io/github/stars/wyysf-98/CraftsMan?style=social' /></a>
42
- <br>
43
- *please note that the model is fliped due to the gradio viewer, please download the obj file and you will get the correct mesh.
44
- <br>
45
- *If you have your own multi-view images, you can directly upload it.
46
- </div>
47
- '''
48
- _CITE_ = r"""
49
- ---
50
- 📝 **Citation**
51
- If you find our work useful for your research or applications, please cite using this bibtex:
52
- ```bibtex
53
- @article{craftsman,
54
- author = {Weiyu Li and Jiarui Liu and Rui Chen and Yixun Liang and Xuelin Chen and Ping Tan and Xiaoxiao Long},
55
- title = {CraftsMan: High-fidelity Mesh Generation with 3D Native Generation and Interactive Geometry Refiner},
56
- journal = {arxiv:xxx},
57
- year = {2024},
58
- }
59
- ```
60
- 🤗 **Acknowledgements**
61
- We use <a href='https://github.com/wjakob/instant-meshes' target='_blank'>Instant Meshes</a> to remesh the generated mesh to a lower face count, thanks to the authors for the great work.
62
- 📋 **License**
63
- CraftsMan is under [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.en.html), so any downstream solution and products (including cloud services) that include CraftsMan code or a trained model (both pretrained or custom trained) inside it should be open-sourced to comply with the AGPL conditions. If you have any questions about the usage of CraftsMan, please contact us first.
64
- 📧 **Contact**
65
- If you have any questions, feel free to open a discussion or contact us at <b>weiyuli.cn@gmail.com</b>.
66
- """
67
-
68
- model = None
69
- cached_dir = None
70
-
71
- @spaces.GPU
72
- def image2mesh(view_front: np.ndarray,
73
- view_right: np.ndarray,
74
- view_back: np.ndarray,
75
- view_left: np.ndarray,
76
- more: bool = False,
77
- scheluder_name: str ="DDIMScheduler",
78
- guidance_scale: int = 7.5,
79
- seed: int = 4,
80
- octree_depth: int = 7):
81
-
82
- sample_inputs = {
83
- "mvimages": [[
84
- Image.fromarray(view_front),
85
- Image.fromarray(view_right),
86
- Image.fromarray(view_back),
87
- Image.fromarray(view_left)
88
- ]]
89
- }
90
-
91
- global model
92
- latents = model.sample(
93
- sample_inputs,
94
- sample_times=1,
95
- guidance_scale=guidance_scale,
96
- return_intermediates=False,
97
- seed=seed
98
-
99
- )[0]
100
-
101
- # decode the latents to mesh
102
- box_v = 1.1
103
- mesh_outputs, _ = model.shape_model.extract_geometry(
104
- latents,
105
- bounds=[-box_v, -box_v, -box_v, box_v, box_v, box_v],
106
- octree_depth=octree_depth
107
- )
108
- assert len(mesh_outputs) == 1, "Only support single mesh output for gradio demo"
109
- mesh = trimesh.Trimesh(mesh_outputs[0][0], mesh_outputs[0][1])
110
- # filepath = f"{cached_dir}/{time.time()}.obj"
111
- filepath = tempfile.NamedTemporaryFile(suffix=f".obj", delete=False).name
112
- mesh.export(filepath, include_normals=True)
113
-
114
- if 'Remesh' in more:
115
- remeshed_filepath = tempfile.NamedTemporaryFile(suffix=f"_remeshed.obj", delete=False).name
116
- print("Remeshing with Instant Meshes...")
117
- # target_face_count = int(len(mesh.faces)/10)
118
- target_face_count = 1000
119
- command = f"{proj_dir}/apps/third_party/InstantMeshes {filepath} -f {target_face_count} -o {remeshed_filepath}"
120
- os.system(command)
121
- filepath = remeshed_filepath
122
- # filepath = filepath.replace('.obj', '_remeshed.obj')
123
-
124
- return filepath
125
-
126
- if __name__=="__main__":
127
- parser = argparse.ArgumentParser()
128
- # parser.add_argument("--model_path", type=str, required=True, help="Path to the object file",)
129
- parser.add_argument("--cached_dir", type=str, default="./gradio_cached_dir")
130
- parser.add_argument("--device", type=int, default=0)
131
- args = parser.parse_args()
132
-
133
- cached_dir = args.cached_dir
134
- os.makedirs(args.cached_dir, exist_ok=True)
135
- device = torch.device(f"cuda:{args.device}" if torch.cuda.is_available() else "cpu")
136
- print(f"using device: {device}")
137
-
138
- # for multi-view images generation
139
- background_choice = OrderedDict({
140
- "Alpha as Mask": "Alpha as Mask",
141
- "Auto Remove Background": "Auto Remove Background",
142
- "Original Image": "Original Image",
143
- })
144
- # mvimg_model_config_list = ["CRM"]
145
- mvimg_model_config_list = ["CRM", "ImageDream", "Wonder3D"]
146
-
147
- # for 3D latent set diffusion
148
- ckpt_path = hf_hub_download(repo_id="wyysf/CraftsMan", filename="image-to-shape-diffusion/clip-mvrgb-modln-l256-e64-ne8-nd16-nl6/model.ckpt", repo_type="model")
149
- config_path = hf_hub_download(repo_id="wyysf/CraftsMan", filename="image-to-shape-diffusion/clip-mvrgb-modln-l256-e64-ne8-nd16-nl6/config.yaml", repo_type="model")
150
- scheluder_dict = OrderedDict({
151
- "DDIMScheduler": 'diffusers.schedulers.DDIMScheduler',
152
- # "DPMSolverMultistepScheduler": 'diffusers.schedulers.DPMSolverMultistepScheduler', # not support yet
153
- # "UniPCMultistepScheduler": 'diffusers.schedulers.UniPCMultistepScheduler', # not support yet
154
- })
155
-
156
- # main GUI
157
- custom_theme = gr.themes.Soft(primary_hue="blue").set(
158
- button_secondary_background_fill="*neutral_100",
159
- button_secondary_background_fill_hover="*neutral_200")
160
- custom_css = '''#disp_image {
161
- text-align: center; /* Horizontally center the content */
162
- }'''
163
-
164
- with gr.Blocks(title=_TITLE, theme=custom_theme, css=custom_css) as demo:
165
- with gr.Row():
166
- with gr.Column(scale=1):
167
- gr.Markdown('# ' + _TITLE)
168
- gr.Markdown(_DESCRIPTION)
169
-
170
- with gr.Row():
171
- with gr.Column(scale=2):
172
- with gr.Row():
173
- image_input = gr.Image(
174
- label="Image Input",
175
- image_mode="RGBA",
176
- sources="upload",
177
- type="pil",
178
- )
179
- with gr.Row():
180
- text = gr.Textbox(label="Prompt (Optional, only works for mvdream)", visible=False)
181
- with gr.Row():
182
- gr.Markdown('''Try a different <b>seed</b> if the result is unsatisfying. Good Luck :)''')
183
- with gr.Row():
184
- seed = gr.Number(42, label='Seed', show_label=True)
185
- more = gr.CheckboxGroup(["Remesh", "Symmetry(TBD)"], label="More", show_label=False)
186
- # remesh = gr.Checkbox(value=False, label='Remesh')
187
- # symmetry = gr.Checkbox(value=False, label='Symmetry(TBD)', interactive=False)
188
- run_btn = gr.Button('Generate', variant='primary', interactive=True)
189
-
190
- with gr.Row():
191
- gr.Examples(
192
- examples=[os.path.join("./apps/examples", i) for i in os.listdir("./apps/examples")],
193
- inputs=[image_input],
194
- examples_per_page=8
195
- )
196
-
197
- with gr.Column(scale=4):
198
- with gr.Row():
199
- output_model_obj = gr.Model3D(
200
- label="Output Model (OBJ Format)",
201
- camera_position=(90.0, 90.0, 3.5),
202
- interactive=False,
203
- )
204
-
205
- with gr.Row():
206
- view_front = gr.Image(label="Front", interactive=True, show_label=True)
207
- view_right = gr.Image(label="Right", interactive=True, show_label=True)
208
- view_back = gr.Image(label="Back", interactive=True, show_label=True)
209
- view_left = gr.Image(label="Left", interactive=True, show_label=True)
210
-
211
- # with gr.Accordion('Advanced options', open=False):
212
- with gr.Row(equal_height=True):
213
- run_mv_btn = gr.Button('Only Generate 2D', interactive=True)
214
- run_3d_btn = gr.Button('Only Generate 3D', interactive=True)
215
-
216
- with gr.Accordion('Advanced options (2D)', open=False):
217
- with gr.Row():
218
- crop_size = gr.Number(224, label='Crop size')
219
- mvimg_model = gr.Dropdown(value="CRM", label="MV Image Model", choices=mvimg_model_config_list)
220
-
221
- with gr.Row():
222
- foreground_ratio = gr.Slider(
223
- label="Foreground Ratio",
224
- minimum=0.5,
225
- maximum=1.0,
226
- value=1.0,
227
- step=0.05,
228
- )
229
-
230
- with gr.Row():
231
- background_choice = gr.Dropdown(label="Backgroud Choice", value="Auto Remove Background",choices=list(background_choice.keys()))
232
- rmbg_type = gr.Dropdown(label="Backgroud Remove Type", value="rembg",choices=['sam', "rembg"])
233
- backgroud_color = gr.ColorPicker(label="Background Color", value="#FFFFFF", interactive=True)
234
-
235
- with gr.Row():
236
- mvimg_guidance_scale = gr.Number(value=3.5, minimum=3, maximum=10, label="2D Guidance Scale")
237
- mvimg_steps = gr.Number(value=30, minimum=20, maximum=100, label="2D Sample Steps", precision=0)
238
-
239
- with gr.Accordion('Advanced options (3D)', open=False):
240
- with gr.Row():
241
- guidance_scale = gr.Number(label="3D Guidance Scale", value=7.5, minimum=3.0, maximum=10.0)
242
- steps = gr.Number(value=50, minimum=20, maximum=100, label="3D Sample Steps", precision=0)
243
-
244
- with gr.Row():
245
- scheduler = gr.Dropdown(label="scheluder", value="DDIMScheduler",choices=list(scheluder_dict.keys()))
246
- octree_depth = gr.Slider(label="Octree Depth", value=7, minimum=4, maximum=8, step=1)
247
-
248
- gr.Markdown(_CITE_)
249
-
250
- outputs = [output_model_obj]
251
- rmbg = RMBG(device)
252
-
253
- gen_mvimg = GenMVImage(device)
254
- model = load_model(ckpt_path, config_path, device)
255
-
256
- run_btn.click(fn=check_input_image, inputs=[image_input]
257
- ).success(
258
- fn=rmbg.run,
259
- inputs=[rmbg_type, image_input, crop_size, foreground_ratio, background_choice, backgroud_color],
260
- outputs=[image_input]
261
- ).success(
262
- fn=gen_mvimg.run,
263
- inputs=[mvimg_model, text, image_input, crop_size, seed, mvimg_guidance_scale, mvimg_steps],
264
- outputs=[view_front, view_right, view_back, view_left]
265
- ).success(
266
- fn=image2mesh,
267
- inputs=[view_front, view_right, view_back, view_left, more, scheduler, guidance_scale, seed, octree_depth],
268
- outputs=outputs,
269
- api_name="generate_img2obj")
270
- run_mv_btn.click(fn=gen_mvimg.run,
271
- inputs=[mvimg_model, text, image_input, crop_size, seed, mvimg_guidance_scale, mvimg_steps],
272
- outputs=[view_front, view_right, view_back, view_left]
273
- )
274
- run_3d_btn.click(fn=image2mesh,
275
- inputs=[view_front, view_right, view_back, view_left, more, scheduler, guidance_scale, seed, octree_depth],
276
- outputs=outputs,
277
- api_name="generate_img2obj")
278
-
279
- demo.queue().launch(share=True, allowed_paths=[args.cached_dir])