wyysf commited on
Commit
9094561
·
1 Parent(s): 175ba5a

update the code of gradio

Browse files
Files changed (1) hide show
  1. gradio_app.py +78 -38
gradio_app.py CHANGED
@@ -4,18 +4,16 @@ 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
- from diffusers import DiffusionPipeline
13
 
14
  import PIL
15
  from PIL import Image
16
  from collections import OrderedDict
17
  import trimesh
18
  import rembg
 
19
  import gradio as gr
20
  from typing import Any
21
 
@@ -50,7 +48,7 @@ _CITE_ = r"""
50
  If you find our work useful for your research or applications, please cite using this bibtex:
51
  ```bibtex
52
  @article{li2024craftsman,
53
- author = {Weiyu Li and Jiarui Liu and Rui Chen and Yixun Liang and Xuelin Chen and Ping Tan and Xiaoxiao Long},
54
  title = {CraftsMan: High-fidelity Mesh Generation with 3D Native Generation and Interactive Geometry Refiner},
55
  journal = {arXiv preprint arXiv:2405.14979},
56
  year = {2024},
@@ -67,7 +65,6 @@ If you have any questions, feel free to open a discussion or contact us at <b>we
67
  model = None
68
  cached_dir = None
69
 
70
-
71
  def check_input_image(input_image):
72
  if input_image is None:
73
  raise gr.Error("No image uploaded!")
@@ -87,7 +84,7 @@ class RMBG(object):
87
  if image.mode == "RGBA" and image.getextrema()[3][0] < 255:
88
  # explain why current do not rm bg
89
  print("alhpa channl not enpty, skip remove background, using alpha channel as mask")
90
- background = Image.new("RGBA", image.size, background_color)
91
  image = Image.alpha_composite(background, image)
92
  do_remove = False
93
  do_remove = do_remove or force
@@ -97,11 +94,11 @@ class RMBG(object):
97
  # calculate the min bbox of the image
98
  alpha = image.split()[-1]
99
  image = image.crop(alpha.getbbox())
100
-
101
  return image
102
  return _rembg_remove(input_image, None, force_remove=True)
103
 
104
- def run(self, rm_type, image, foreground_ratio, background_choice, background_color=(0, 0, 0, 0)):
 
105
  if "Original" in background_choice:
106
  return image
107
  else:
@@ -120,7 +117,7 @@ class RMBG(object):
120
  # Resize the image while maintaining the aspect ratio
121
  resized_image = image.resize(new_size)
122
  # Create a new image with the original size and white background
123
- padded_image = PIL.Image.new("RGBA", image.size, (0, 0, 0, 0))
124
  paste_position = ((image.width - resized_image.width) // 2, (image.height - resized_image.height) // 2)
125
  padded_image.paste(resized_image, paste_position)
126
 
@@ -129,24 +126,29 @@ class RMBG(object):
129
  if width == height:
130
  return padded_image
131
  new_size = (max(width, height), max(width, height))
132
- image = PIL.Image.new("RGBA", new_size, (0, 0, 0, 0))
133
  paste_position = ((new_size[0] - width) // 2, (new_size[1] - height) // 2)
134
  image.paste(padded_image, paste_position)
135
- return image
 
 
136
 
137
- @spaces.GPU
138
  def image2mesh(image: Any,
139
  more: bool = False,
140
  scheluder_name: str ="DDIMScheduler",
141
  guidance_scale: int = 7.5,
142
- steps: int = 30,
143
  seed: int = 4,
144
  target_face_count: int = 2000,
145
  octree_depth: int = 7):
146
 
 
 
 
147
  sample_inputs = {
148
  "image": [
149
- image
150
  ]
151
  }
152
 
@@ -169,7 +171,7 @@ def image2mesh(image: Any,
169
  assert len(mesh_outputs) == 1, "Only support single mesh output for gradio demo"
170
  mesh = trimesh.Trimesh(mesh_outputs[0][0], mesh_outputs[0][1])
171
  # filepath = f"{cached_dir}/{time.time()}.obj"
172
- filepath = tempfile.NamedTemporaryFile(suffix=f".obj", delete=False).name
173
  mesh.export(filepath, include_normals=True)
174
 
175
  if 'Remesh' in more:
@@ -181,6 +183,30 @@ def image2mesh(image: Any,
181
 
182
  return filepath
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  if __name__=="__main__":
185
  parser = argparse.ArgumentParser()
186
  parser.add_argument("--model_path", type=str, default="", help="Path to the object file",)
@@ -238,39 +264,23 @@ if __name__=="__main__":
238
  label="Image Input",
239
  image_mode="RGBA",
240
  sources="upload",
241
- type="pil",
242
  )
243
  run_btn = gr.Button('Generate', variant='primary', interactive=True)
244
 
245
  with gr.Row():
246
  gr.Markdown('''Try a different <b>seed and MV Model</b> for better results. Good Luck :)''')
247
  with gr.Row():
248
- seed = gr.Number(0, label='Seed', show_label=True)
249
  more = gr.CheckboxGroup(["Remesh"], label="More", show_label=False)
250
  target_face_count = gr.Number(2000, label='Target Face Count', show_label=True)
251
 
252
- with gr.Row():
253
- gr.Examples(
254
- examples=[os.path.join("./examples", i) for i in os.listdir("./examples")],
255
- inputs=[image_input],
256
- examples_per_page=8
257
- )
258
 
259
- with gr.Column(scale=4):
260
- with gr.Row():
261
- output_model_obj = gr.Model3D(
262
- label="Output Model (OBJ Format)",
263
- camera_position=(90.0, 90.0, 3.5),
264
- interactive=False,
265
- )
266
- with gr.Row():
267
- gr.Markdown('''*please note that the model is fliped due to the gradio viewer, please download the obj file and you will get the correct orientation.''')
268
-
269
  with gr.Accordion('Advanced options', open=False):
270
  with gr.Row():
271
  background_choice = gr.Dropdown(label="Backgroud Choice", value="Auto Remove Background",choices=list(background_choice.keys()))
272
  rmbg_type = gr.Dropdown(label="Backgroud Remove Type", value="rembg",choices=['sam', "rembg"])
273
- foreground_ratio = gr.Slider(label="Foreground Ratio", value=1.0, minimum=0.5, maximum=1.0, step=0.01)
274
 
275
  with gr.Row():
276
  guidance_scale = gr.Number(label="3D Guidance Scale", value=7.5, minimum=3.0, maximum=10.0)
@@ -279,10 +289,34 @@ if __name__=="__main__":
279
  with gr.Row():
280
  scheduler = gr.Dropdown(label="scheluder", value="DDIMScheduler",choices=list(scheluder_dict.keys()))
281
  octree_depth = gr.Slider(label="Octree Depth", value=7, minimum=4, maximum=8, step=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
  gr.Markdown(_CITE_)
284
 
285
- outputs = [output_model_obj]
 
286
  rmbg = RMBG()
287
 
288
  # model = load_model(ckpt_path, config_path, device)
@@ -304,7 +338,13 @@ if __name__=="__main__":
304
  ).success(
305
  fn=image2mesh,
306
  inputs=[image_input, more, scheduler, guidance_scale, steps, seed, target_face_count, octree_depth],
307
- outputs=outputs,
308
- api_name="generate_img2obj")
 
 
 
 
 
 
309
 
310
  demo.queue().launch(share=True, allowed_paths=[args.cached_dir])
 
4
  import json
5
  import torch
6
  import sys
7
+ import base64
 
8
  import numpy as np
 
9
  from huggingface_hub import hf_hub_download
 
10
 
11
  import PIL
12
  from PIL import Image
13
  from collections import OrderedDict
14
  import trimesh
15
  import rembg
16
+ import requests
17
  import gradio as gr
18
  from typing import Any
19
 
 
48
  If you find our work useful for your research or applications, please cite using this bibtex:
49
  ```bibtex
50
  @article{li2024craftsman,
51
+ author = {Weiyu Li and Jiarui Liu and Hongyu Yan and Rui Chen and Yixun Liang and Xuelin Chen and Ping Tan and Xiaoxiao Long},
52
  title = {CraftsMan: High-fidelity Mesh Generation with 3D Native Generation and Interactive Geometry Refiner},
53
  journal = {arXiv preprint arXiv:2405.14979},
54
  year = {2024},
 
65
  model = None
66
  cached_dir = None
67
 
 
68
  def check_input_image(input_image):
69
  if input_image is None:
70
  raise gr.Error("No image uploaded!")
 
84
  if image.mode == "RGBA" and image.getextrema()[3][0] < 255:
85
  # explain why current do not rm bg
86
  print("alhpa channl not enpty, skip remove background, using alpha channel as mask")
87
+ background = Image.new("RGBA", image.size, (*background_color, 0))
88
  image = Image.alpha_composite(background, image)
89
  do_remove = False
90
  do_remove = do_remove or force
 
94
  # calculate the min bbox of the image
95
  alpha = image.split()[-1]
96
  image = image.crop(alpha.getbbox())
 
97
  return image
98
  return _rembg_remove(input_image, None, force_remove=True)
99
 
100
+ def run(self, rm_type, image_file, foreground_ratio, background_choice, background_color=(255, 255, 255)):
101
+ image = Image.open(image_file)
102
  if "Original" in background_choice:
103
  return image
104
  else:
 
117
  # Resize the image while maintaining the aspect ratio
118
  resized_image = image.resize(new_size)
119
  # Create a new image with the original size and white background
120
+ padded_image = PIL.Image.new("RGBA", image.size, (*background_color, 0))
121
  paste_position = ((image.width - resized_image.width) // 2, (image.height - resized_image.height) // 2)
122
  padded_image.paste(resized_image, paste_position)
123
 
 
126
  if width == height:
127
  return padded_image
128
  new_size = (max(width, height), max(width, height))
129
+ image = PIL.Image.new("RGBA", new_size, (*background_color, 1))
130
  paste_position = ((new_size[0] - width) // 2, (new_size[1] - height) // 2)
131
  image.paste(padded_image, paste_position)
132
+ filepath = tempfile.NamedTemporaryFile(suffix=f".png", delete=False).name
133
+ image.save(filepath)
134
+ return filepath
135
 
136
+ # @spaces.GPU
137
  def image2mesh(image: Any,
138
  more: bool = False,
139
  scheluder_name: str ="DDIMScheduler",
140
  guidance_scale: int = 7.5,
141
+ steps: int = 50,
142
  seed: int = 4,
143
  target_face_count: int = 2000,
144
  octree_depth: int = 7):
145
 
146
+ # global rmbg
147
+ # processed_image = rmbg.run(rm_type, image, foreground_ratio, background_choice)
148
+ processed_image = Image.open(image)
149
  sample_inputs = {
150
  "image": [
151
+ processed_image
152
  ]
153
  }
154
 
 
171
  assert len(mesh_outputs) == 1, "Only support single mesh output for gradio demo"
172
  mesh = trimesh.Trimesh(mesh_outputs[0][0], mesh_outputs[0][1])
173
  # filepath = f"{cached_dir}/{time.time()}.obj"
174
+ filepath = tempfile.NamedTemporaryFile(suffix=f".glb", delete=False).name
175
  mesh.export(filepath, include_normals=True)
176
 
177
  if 'Remesh' in more:
 
183
 
184
  return filepath
185
 
186
+ def mesh2texture(mesh_file, image_file):
187
+ headers = {'Content-Type': 'application/json'}
188
+ server_url = "114.249.238.184:34119"
189
+ with open(image_file, 'rb') as f:
190
+ image_bytes = f.read()
191
+ with open(mesh_file, 'rb') as f:
192
+ mesh_bytes = f.read()
193
+ request = {
194
+ 'png_base64_image': base64.b64encode(image_bytes).decode('utf-8'),
195
+ 'glb_base64_mesh': base64.b64encode(mesh_bytes).decode('utf-8'),
196
+ }
197
+ response = requests.post(
198
+ url=f"http://{server_url}/generate_texture",
199
+ headers=headers,
200
+ data=json.dumps(request),
201
+ ).json()
202
+ mesh_bytes = base64.b64decode(response['glb_base64_mesh'])
203
+ filepath = tempfile.NamedTemporaryFile(suffix=f".glb", delete=False).name
204
+ with open(filepath, 'wb') as f:
205
+ f.write(mesh_bytes)
206
+
207
+ return filepath
208
+
209
+
210
  if __name__=="__main__":
211
  parser = argparse.ArgumentParser()
212
  parser.add_argument("--model_path", type=str, default="", help="Path to the object file",)
 
264
  label="Image Input",
265
  image_mode="RGBA",
266
  sources="upload",
267
+ type="filepath",
268
  )
269
  run_btn = gr.Button('Generate', variant='primary', interactive=True)
270
 
271
  with gr.Row():
272
  gr.Markdown('''Try a different <b>seed and MV Model</b> for better results. Good Luck :)''')
273
  with gr.Row():
274
+ seed = gr.Number(42, label='Seed', show_label=True)
275
  more = gr.CheckboxGroup(["Remesh"], label="More", show_label=False)
276
  target_face_count = gr.Number(2000, label='Target Face Count', show_label=True)
277
 
 
 
 
 
 
 
278
 
 
 
 
 
 
 
 
 
 
 
279
  with gr.Accordion('Advanced options', open=False):
280
  with gr.Row():
281
  background_choice = gr.Dropdown(label="Backgroud Choice", value="Auto Remove Background",choices=list(background_choice.keys()))
282
  rmbg_type = gr.Dropdown(label="Backgroud Remove Type", value="rembg",choices=['sam', "rembg"])
283
+ foreground_ratio = gr.Slider(label="Foreground Ratio", value=0.95, minimum=0.5, maximum=1.0, step=0.01)
284
 
285
  with gr.Row():
286
  guidance_scale = gr.Number(label="3D Guidance Scale", value=7.5, minimum=3.0, maximum=10.0)
 
289
  with gr.Row():
290
  scheduler = gr.Dropdown(label="scheluder", value="DDIMScheduler",choices=list(scheluder_dict.keys()))
291
  octree_depth = gr.Slider(label="Octree Depth", value=7, minimum=4, maximum=8, step=1)
292
+
293
+ with gr.Row():
294
+ gr.Examples(
295
+ examples=[os.path.join("./assets/examples", i) for i in os.listdir("./assets/examples")],
296
+ inputs=[image_input],
297
+ examples_per_page=8
298
+ )
299
+
300
+ with gr.Column(scale=4):
301
+ with gr.Row():
302
+ output_model_obj = gr.Model3D(
303
+ label="Output Model (GLB Format)",
304
+ camera_position=(90.0, 90.0, 3.5),
305
+ interactive=False,
306
+ )
307
+ with gr.Row():
308
+ output_model_tex = gr.Model3D(
309
+ label="Output Textured Model (GLB Format)",
310
+ camera_position=(90.0, 90.0, 3.5),
311
+ interactive=False,
312
+ )
313
+ # with gr.Row():
314
+ # gr.Markdown('''*please note that the model is fliped due to the gradio viewer, please download the obj file and you will get the correct orientation.''')
315
 
316
  gr.Markdown(_CITE_)
317
 
318
+ # outputs = [output_model_obj]
319
+ # outputs_tex = [output_model_tex]
320
  rmbg = RMBG()
321
 
322
  # model = load_model(ckpt_path, config_path, device)
 
338
  ).success(
339
  fn=image2mesh,
340
  inputs=[image_input, more, scheduler, guidance_scale, steps, seed, target_face_count, octree_depth],
341
+ outputs=[output_model_obj],
342
+ api_name="generate_img2obj"
343
+ ).success(
344
+ fn=mesh2texture,
345
+ inputs=[output_model_obj, image_input],
346
+ outputs=[output_model_tex],
347
+ api_name="generate_obj2tex"
348
+ )
349
 
350
  demo.queue().launch(share=True, allowed_paths=[args.cached_dir])