xinjie.wang commited on
Commit
eae4507
·
1 Parent(s): cbd4574
app.py CHANGED
@@ -1,6 +1,8 @@
1
  import os
2
 
3
  os.environ["GRADIO_APP"] = "imageto3d"
 
 
4
  import gradio as gr
5
  from common import (
6
  MAX_SEED,
@@ -198,12 +200,9 @@ with gr.Blocks(
198
  with gr.Row() as single_image_example:
199
  examples = gr.Examples(
200
  label="Image Gallery",
201
- examples=[
202
- [f"assets/example_image/{image}"]
203
- for image in os.listdir(
204
- "assets/example_image"
205
- )
206
- ],
207
  inputs=[image_prompt],
208
  fn=preprocess_image_fn,
209
  outputs=[image_prompt, raw_image_cache],
@@ -214,12 +213,9 @@ with gr.Blocks(
214
  with gr.Row(visible=False) as single_sam_image_example:
215
  examples = gr.Examples(
216
  label="Image Gallery",
217
- examples=[
218
- f"assets/example_image/{image}"
219
- for image in os.listdir(
220
- "assets/example_image"
221
- )
222
- ],
223
  inputs=[image_prompt_sam],
224
  fn=preprocess_sam_image_fn,
225
  outputs=[image_prompt_sam, raw_image_cache],
 
1
  import os
2
 
3
  os.environ["GRADIO_APP"] = "imageto3d"
4
+ from glob import glob
5
+
6
  import gradio as gr
7
  from common import (
8
  MAX_SEED,
 
200
  with gr.Row() as single_image_example:
201
  examples = gr.Examples(
202
  label="Image Gallery",
203
+ examples=sorted(
204
+ glob("assets/example_image/*")
205
+ ),
 
 
 
206
  inputs=[image_prompt],
207
  fn=preprocess_image_fn,
208
  outputs=[image_prompt, raw_image_cache],
 
213
  with gr.Row(visible=False) as single_sam_image_example:
214
  examples = gr.Examples(
215
  label="Image Gallery",
216
+ examples=sorted(
217
+ glob("assets/example_image/*")
218
+ ),
 
 
 
219
  inputs=[image_prompt_sam],
220
  fn=preprocess_sam_image_fn,
221
  outputs=[image_prompt_sam, raw_image_cache],
asset3d_gen/data/backproject_v2.py CHANGED
@@ -2,10 +2,11 @@ import argparse
2
  import logging
3
  import math
4
  import os
5
- import spaces
6
  import cv2
7
  import numpy as np
8
  import nvdiffrast.torch as dr
 
9
  import torch
10
  import torch.nn.functional as F
11
  import trimesh
@@ -220,7 +221,7 @@ class TextureBacker:
220
  bake_angle_thresh: int = 75,
221
  mask_thresh: float = 0.5,
222
  ):
223
-
224
  self.camera_params = camera_params
225
  self.renderer = None
226
  self.view_weights = view_weights
@@ -419,17 +420,17 @@ class TextureBacker:
419
  return texture
420
 
421
  @spaces.GPU
422
- def cuda_forward(
423
  self,
424
  colors: list[Image.Image],
425
  mesh: trimesh.Trimesh,
426
  ) -> trimesh.Trimesh:
427
  self._lazy_init_render(self.camera_params, self.mask_thresh)
428
-
429
  vertices = torch.from_numpy(mesh.vertices).to(self.device).float()
430
  faces = torch.from_numpy(mesh.faces).to(self.device).to(torch.int)
431
  uv_map = torch.from_numpy(mesh.visual.uv).to(self.device).float()
432
-
433
  rendered_depth, masks = self.renderer.render_depth(vertices, faces)
434
  norm_deps = self.renderer.normalize_map_by_mask(rendered_depth, masks)
435
  render_uvs, _ = self.renderer.render_uv(vertices, faces, uv_map)
@@ -454,7 +455,7 @@ class TextureBacker:
454
 
455
  texture_np = texture.cpu().numpy()
456
  mask_np = (mask.squeeze(-1).cpu().numpy() * 255).astype(np.uint8)
457
-
458
  return texture_np, mask_np
459
 
460
  def __call__(
@@ -464,8 +465,8 @@ class TextureBacker:
464
  output_path: str,
465
  ) -> trimesh.Trimesh:
466
  mesh = self.load_mesh(mesh)
467
- texture_np, mask_np = self.cuda_forward(colors, mesh)
468
-
469
  texture_np = self.uv_inpaint(mesh, texture_np, mask_np)
470
  texture_np = post_process_texture(texture_np)
471
  vertices, faces, uv_map = self.get_mesh_np_attrs(
 
2
  import logging
3
  import math
4
  import os
5
+
6
  import cv2
7
  import numpy as np
8
  import nvdiffrast.torch as dr
9
+ import spaces
10
  import torch
11
  import torch.nn.functional as F
12
  import trimesh
 
221
  bake_angle_thresh: int = 75,
222
  mask_thresh: float = 0.5,
223
  ):
224
+
225
  self.camera_params = camera_params
226
  self.renderer = None
227
  self.view_weights = view_weights
 
420
  return texture
421
 
422
  @spaces.GPU
423
+ def compute_texture(
424
  self,
425
  colors: list[Image.Image],
426
  mesh: trimesh.Trimesh,
427
  ) -> trimesh.Trimesh:
428
  self._lazy_init_render(self.camera_params, self.mask_thresh)
429
+
430
  vertices = torch.from_numpy(mesh.vertices).to(self.device).float()
431
  faces = torch.from_numpy(mesh.faces).to(self.device).to(torch.int)
432
  uv_map = torch.from_numpy(mesh.visual.uv).to(self.device).float()
433
+
434
  rendered_depth, masks = self.renderer.render_depth(vertices, faces)
435
  norm_deps = self.renderer.normalize_map_by_mask(rendered_depth, masks)
436
  render_uvs, _ = self.renderer.render_uv(vertices, faces, uv_map)
 
455
 
456
  texture_np = texture.cpu().numpy()
457
  mask_np = (mask.squeeze(-1).cpu().numpy() * 255).astype(np.uint8)
458
+
459
  return texture_np, mask_np
460
 
461
  def __call__(
 
465
  output_path: str,
466
  ) -> trimesh.Trimesh:
467
  mesh = self.load_mesh(mesh)
468
+ texture_np, mask_np = self.compute_texture(colors, mesh)
469
+
470
  texture_np = self.uv_inpaint(mesh, texture_np, mask_np)
471
  texture_np = post_process_texture(texture_np)
472
  vertices, faces, uv_map = self.get_mesh_np_attrs(
asset3d_gen/data/mesh_operator.py CHANGED
@@ -1,9 +1,10 @@
1
  import logging
2
  from typing import Tuple, Union
3
- import spaces
4
  import igraph
5
  import numpy as np
6
  import pyvista as pv
 
7
  import torch
8
  import utils3d
9
  from pymeshfix import _meshfix
 
1
  import logging
2
  from typing import Tuple, Union
3
+
4
  import igraph
5
  import numpy as np
6
  import pyvista as pv
7
+ import spaces
8
  import torch
9
  import utils3d
10
  from pymeshfix import _meshfix
asset3d_gen/models/delight_model.py CHANGED
@@ -1,8 +1,9 @@
1
  import os
2
  from typing import Union
3
- import spaces
4
  import cv2
5
  import numpy as np
 
6
  import torch
7
  from diffusers import (
8
  EulerAncestralDiscreteScheduler,
@@ -28,7 +29,6 @@ class DelightingModel(object):
28
  device: str = "cuda",
29
  seed: int = 0,
30
  ) -> None:
31
-
32
  self.image_guide_scale = image_guide_scale
33
  self.text_guide_scale = text_guide_scale
34
  self.num_infer_step = num_infer_step
@@ -38,8 +38,8 @@ class DelightingModel(object):
38
  )
39
  self.seed = seed
40
  self.device = device
41
- self.pipeline = None # lazy load model adapt to @spaces.GPU
42
-
43
  if model_path is None:
44
  suffix = "hunyuan3d-delight-v2-0"
45
  model_path = snapshot_download(
@@ -114,7 +114,7 @@ class DelightingModel(object):
114
  target_wh: tuple[int, int] = None,
115
  ) -> Image.Image:
116
  self._lazy_init_pipeline()
117
-
118
  if isinstance(image, str):
119
  image = Image.open(image)
120
  elif isinstance(image, np.ndarray):
@@ -158,7 +158,7 @@ if __name__ == "__main__":
158
  delighting_model = DelightingModel(
159
  # model_path="/horizon-bucket/robot_lab/users/xinjie.wang/weights/hunyuan3d-delight-v2-0" # noqa
160
  )
161
- image_path = "/home/users/xinjie.wang/xinjie/asset3d-gen/scripts/apps/assets/example_image/room_bottle_002.jpeg"
162
  image = delighting_model(
163
  image_path, preprocess=True, target_wh=(512, 512)
164
  ) # noqa
 
1
  import os
2
  from typing import Union
3
+
4
  import cv2
5
  import numpy as np
6
+ import spaces
7
  import torch
8
  from diffusers import (
9
  EulerAncestralDiscreteScheduler,
 
29
  device: str = "cuda",
30
  seed: int = 0,
31
  ) -> None:
 
32
  self.image_guide_scale = image_guide_scale
33
  self.text_guide_scale = text_guide_scale
34
  self.num_infer_step = num_infer_step
 
38
  )
39
  self.seed = seed
40
  self.device = device
41
+ self.pipeline = None # lazy load model adapt to @spaces.GPU
42
+
43
  if model_path is None:
44
  suffix = "hunyuan3d-delight-v2-0"
45
  model_path = snapshot_download(
 
114
  target_wh: tuple[int, int] = None,
115
  ) -> Image.Image:
116
  self._lazy_init_pipeline()
117
+
118
  if isinstance(image, str):
119
  image = Image.open(image)
120
  elif isinstance(image, np.ndarray):
 
158
  delighting_model = DelightingModel(
159
  # model_path="/horizon-bucket/robot_lab/users/xinjie.wang/weights/hunyuan3d-delight-v2-0" # noqa
160
  )
161
+ image_path = "scripts/apps/assets/example_image/room_bottle_002.jpeg"
162
  image = delighting_model(
163
  image_path, preprocess=True, target_wh=(512, 512)
164
  ) # noqa
asset3d_gen/models/gs_model.py CHANGED
@@ -428,7 +428,7 @@ class GaussianOperator(GaussianBase):
428
  sh_degree=self.sh_degree,
429
  device=self.device,
430
  )
431
- print("self.device", self.device)
432
  return GaussianOperator(**gs_dict)
433
 
434
  def rescale(self, scale: float):
@@ -459,7 +459,9 @@ class GaussianOperator(GaussianBase):
459
  sh_degree: int = 0,
460
  device: str = "cuda",
461
  ) -> None:
462
- gs_model = GaussianOperator.load_from_ply(in_ply, sh_degree, device=device)
 
 
463
 
464
  if instance_pose is not None:
465
  gs_model = gs_model.get_gaussians(instance_pose=instance_pose)
 
428
  sh_degree=self.sh_degree,
429
  device=self.device,
430
  )
431
+
432
  return GaussianOperator(**gs_dict)
433
 
434
  def rescale(self, scale: float):
 
459
  sh_degree: int = 0,
460
  device: str = "cuda",
461
  ) -> None:
462
+ gs_model = GaussianOperator.load_from_ply(
463
+ in_ply, sh_degree, device=device
464
+ )
465
 
466
  if instance_pose is not None:
467
  gs_model = gs_model.get_gaussians(instance_pose=instance_pose)
asset3d_gen/models/sr_model.py CHANGED
@@ -1,8 +1,9 @@
1
  import logging
2
  import os
3
  from typing import Union
4
- import spaces
5
  import numpy as np
 
6
  import torch
7
  from huggingface_hub import snapshot_download
8
  from PIL import Image
@@ -66,11 +67,16 @@ class ImageRealESRGAN:
66
  if version.parse(torchvision.__version__) > version.parse("0.16"):
67
  import sys
68
  import types
 
69
  import torchvision.transforms.functional as TF
70
 
71
- functional_tensor = types.ModuleType("torchvision.transforms.functional_tensor")
 
 
72
  functional_tensor.rgb_to_grayscale = TF.rgb_to_grayscale
73
- sys.modules["torchvision.transforms.functional_tensor"] = functional_tensor
 
 
74
 
75
  self.outscale = outscale
76
  self.upsampler = None
@@ -80,15 +86,16 @@ class ImageRealESRGAN:
80
  model_path = snapshot_download(
81
  repo_id="xinjjj/RoboAssetGen", allow_patterns=f"{suffix}/*"
82
  )
83
- model_path = os.path.join(model_path, suffix, "RealESRGAN_x4plus.pth")
 
 
84
 
85
  self.model_path = model_path
86
-
87
  def _lazy_init(self):
88
  if self.upsampler is None:
89
  from basicsr.archs.rrdbnet_arch import RRDBNet
90
  from realesrgan import RealESRGANer
91
- from huggingface_hub import snapshot_download
92
 
93
  model = RRDBNet(
94
  num_in_ch=3,
@@ -110,7 +117,7 @@ class ImageRealESRGAN:
110
  @spaces.GPU
111
  def __call__(self, image: Union[Image.Image, np.ndarray]) -> Image.Image:
112
  self._lazy_init()
113
-
114
  if isinstance(image, Image.Image):
115
  image = np.array(image)
116
 
 
1
  import logging
2
  import os
3
  from typing import Union
4
+
5
  import numpy as np
6
+ import spaces
7
  import torch
8
  from huggingface_hub import snapshot_download
9
  from PIL import Image
 
67
  if version.parse(torchvision.__version__) > version.parse("0.16"):
68
  import sys
69
  import types
70
+
71
  import torchvision.transforms.functional as TF
72
 
73
+ functional_tensor = types.ModuleType(
74
+ "torchvision.transforms.functional_tensor"
75
+ )
76
  functional_tensor.rgb_to_grayscale = TF.rgb_to_grayscale
77
+ sys.modules["torchvision.transforms.functional_tensor"] = (
78
+ functional_tensor
79
+ )
80
 
81
  self.outscale = outscale
82
  self.upsampler = None
 
86
  model_path = snapshot_download(
87
  repo_id="xinjjj/RoboAssetGen", allow_patterns=f"{suffix}/*"
88
  )
89
+ model_path = os.path.join(
90
+ model_path, suffix, "RealESRGAN_x4plus.pth"
91
+ )
92
 
93
  self.model_path = model_path
94
+
95
  def _lazy_init(self):
96
  if self.upsampler is None:
97
  from basicsr.archs.rrdbnet_arch import RRDBNet
98
  from realesrgan import RealESRGANer
 
99
 
100
  model = RRDBNet(
101
  num_in_ch=3,
 
117
  @spaces.GPU
118
  def __call__(self, image: Union[Image.Image, np.ndarray]) -> Image.Image:
119
  self._lazy_init()
120
+
121
  if isinstance(image, Image.Image):
122
  image = np.array(image)
123
 
asset3d_gen/scripts/render_gs.py CHANGED
@@ -2,9 +2,10 @@ import argparse
2
  import logging
3
  import math
4
  import os
5
- import spaces
6
  import cv2
7
  import numpy as np
 
8
  import torch
9
  from tqdm import tqdm
10
  from asset3d_gen.data.utils import (
 
2
  import logging
3
  import math
4
  import os
5
+
6
  import cv2
7
  import numpy as np
8
+ import spaces
9
  import torch
10
  from tqdm import tqdm
11
  from asset3d_gen.data.utils import (
asset3d_gen/utils/process_media.py CHANGED
@@ -6,11 +6,12 @@ import subprocess
6
  from glob import glob
7
  from io import BytesIO
8
  from typing import Union
9
- import spaces
10
  import cv2
11
  import imageio
12
  import numpy as np
13
  import PIL.Image as Image
 
14
  from moviepy.editor import VideoFileClip, clips_array
15
 
16
  logging.basicConfig(level=logging.INFO)
 
6
  from glob import glob
7
  from io import BytesIO
8
  from typing import Union
9
+
10
  import cv2
11
  import imageio
12
  import numpy as np
13
  import PIL.Image as Image
14
+ import spaces
15
  from moviepy.editor import VideoFileClip, clips_array
16
 
17
  logging.basicConfig(level=logging.INFO)
asset3d_gen/validators/aesthetic_predictor.py CHANGED
@@ -1,8 +1,9 @@
1
  import os
2
- import spaces
3
  import clip
4
  import numpy as np
5
  import pytorch_lightning as pl
 
6
  import torch
7
  import torch.nn as nn
8
  from huggingface_hub import snapshot_download
 
1
  import os
2
+
3
  import clip
4
  import numpy as np
5
  import pytorch_lightning as pl
6
+ import spaces
7
  import torch
8
  import torch.nn as nn
9
  from huggingface_hub import snapshot_download
common.py CHANGED
@@ -11,7 +11,6 @@ import gradio as gr
11
  import numpy as np
12
  import spaces
13
  import torch
14
- import torch
15
  import torch.nn.functional as F
16
  import trimesh
17
  from easydict import EasyDict as edict
@@ -58,8 +57,11 @@ from thirdparty.TRELLIS.trellis.representations import (
58
  Gaussian,
59
  MeshExtractResult,
60
  )
61
- from thirdparty.TRELLIS.trellis.representations.gaussian.general_utils import inverse_sigmoid, strip_symmetric, build_scaling_rotation
62
-
 
 
 
63
  from thirdparty.TRELLIS.trellis.utils import postprocessing_utils
64
  from thirdparty.TRELLIS.trellis.utils.render_utils import (
65
  render_frames,
@@ -87,7 +89,9 @@ def patched_setup_functions(self):
87
  def inverse_softplus(x):
88
  return x + torch.log(-torch.expm1(-x))
89
 
90
- def build_covariance_from_scaling_rotation(scaling, scaling_modifier, rotation):
 
 
91
  L = build_scaling_rotation(scaling_modifier * scaling, rotation)
92
  actual_covariance = L @ L.transpose(1, 2)
93
  symm = strip_symmetric(actual_covariance)
@@ -105,10 +109,15 @@ def patched_setup_functions(self):
105
  self.inverse_opacity_activation = inverse_sigmoid
106
  self.rotation_activation = F.normalize
107
 
108
- self.scale_bias = self.inverse_scaling_activation(torch.tensor(self.scaling_bias)).to(self.device)
 
 
109
  self.rots_bias = torch.zeros((4)).to(self.device)
110
  self.rots_bias[0] = 1
111
- self.opacity_bias = self.inverse_opacity_activation(torch.tensor(self.opacity_bias)).to(self.device)
 
 
 
112
 
113
  Gaussian.setup_functions = patched_setup_functions
114
 
@@ -357,9 +366,7 @@ def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
357
  }
358
 
359
 
360
- # @spaces.GPU
361
  def unpack_state(state: dict, device: str = "cpu") -> tuple[Gaussian, dict]:
362
- print("debug11")
363
  gs = Gaussian(
364
  aabb=state["gaussian"]["aabb"],
365
  sh_degree=state["gaussian"]["sh_degree"],
@@ -369,7 +376,6 @@ def unpack_state(state: dict, device: str = "cpu") -> tuple[Gaussian, dict]:
369
  scaling_activation=state["gaussian"]["scaling_activation"],
370
  device=device,
371
  )
372
- print("debug12")
373
  gs._xyz = torch.tensor(state["gaussian"]["_xyz"], device=device)
374
  gs._features_dc = torch.tensor(
375
  state["gaussian"]["_features_dc"], device=device
@@ -382,7 +388,6 @@ def unpack_state(state: dict, device: str = "cpu") -> tuple[Gaussian, dict]:
382
  vertices=torch.tensor(state["mesh"]["vertices"], device=device),
383
  faces=torch.tensor(state["mesh"]["faces"], device=device),
384
  )
385
- print("debug13")
386
 
387
  return gs, mesh
388
 
@@ -484,21 +489,62 @@ def image_to_3d(
484
  return state, video_path
485
 
486
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  def extract_3d_representations_v2(
488
  state: dict,
489
  enable_delight: bool,
490
  req: gr.Request,
491
  ):
492
- print("debug1")
493
  output_root = TMP_DIR
494
  user_dir = os.path.join(output_root, str(req.session_hash))
495
  gs_model, mesh_model = unpack_state(state, device="cpu")
496
- print("debug2")
497
 
498
  filename = "sample"
499
  gs_path = os.path.join(user_dir, f"{filename}_gs.ply")
500
  gs_model.save_ply(gs_path)
501
- print("debug3")
502
 
503
  # Rotate mesh and GS by 90 degrees around Z-axis.
504
  rot_matrix = [[0, 0, -1], [0, 1, 0], [1, 0, 0]]
@@ -509,17 +555,14 @@ def extract_3d_representations_v2(
509
  gs_rot = np.array(gs_add_rot) @ np.array(rot_matrix)
510
  pose = GaussianOperator.trans_to_quatpose(gs_rot)
511
  aligned_gs_path = gs_path.replace(".ply", "_aligned.ply")
512
- print("debug4")
513
  GaussianOperator.resave_ply(
514
  in_ply=gs_path,
515
  out_ply=aligned_gs_path,
516
  instance_pose=pose,
517
  device="cpu",
518
  )
519
- print("debug5")
520
  color_path = os.path.join(user_dir, "color.png")
521
  render_gs_api(aligned_gs_path, color_path)
522
- print("debug6")
523
 
524
  mesh = trimesh.Trimesh(
525
  vertices=mesh_model.vertices.cpu().numpy(),
@@ -530,7 +573,7 @@ def extract_3d_representations_v2(
530
 
531
  mesh_obj_path = os.path.join(user_dir, f"{filename}.obj")
532
  mesh.export(mesh_obj_path)
533
- print("debug7")
534
  mesh = backproject_api(
535
  delight_model=DELIGHT,
536
  imagesr_model=IMAGESR_MODEL,
@@ -540,7 +583,6 @@ def extract_3d_representations_v2(
540
  skip_fix_mesh=False,
541
  delight=enable_delight,
542
  )
543
- print("debug8")
544
 
545
  mesh_glb_path = os.path.join(user_dir, f"{filename}.glb")
546
  mesh.export(mesh_glb_path)
@@ -560,7 +602,7 @@ def extract_urdf(
560
  output_root = TMP_DIR
561
  if req is not None:
562
  output_root = os.path.join(output_root, str(req.session_hash))
563
-
564
  # Convert to URDF and recover attrs by GPT.
565
  filename = "sample"
566
  urdf_convertor = URDFGenerator(GPT_CLIENT, render_view_num=4)
 
11
  import numpy as np
12
  import spaces
13
  import torch
 
14
  import torch.nn.functional as F
15
  import trimesh
16
  from easydict import EasyDict as edict
 
57
  Gaussian,
58
  MeshExtractResult,
59
  )
60
+ from thirdparty.TRELLIS.trellis.representations.gaussian.general_utils import (
61
+ build_scaling_rotation,
62
+ inverse_sigmoid,
63
+ strip_symmetric,
64
+ )
65
  from thirdparty.TRELLIS.trellis.utils import postprocessing_utils
66
  from thirdparty.TRELLIS.trellis.utils.render_utils import (
67
  render_frames,
 
89
  def inverse_softplus(x):
90
  return x + torch.log(-torch.expm1(-x))
91
 
92
+ def build_covariance_from_scaling_rotation(
93
+ scaling, scaling_modifier, rotation
94
+ ):
95
  L = build_scaling_rotation(scaling_modifier * scaling, rotation)
96
  actual_covariance = L @ L.transpose(1, 2)
97
  symm = strip_symmetric(actual_covariance)
 
109
  self.inverse_opacity_activation = inverse_sigmoid
110
  self.rotation_activation = F.normalize
111
 
112
+ self.scale_bias = self.inverse_scaling_activation(
113
+ torch.tensor(self.scaling_bias)
114
+ ).to(self.device)
115
  self.rots_bias = torch.zeros((4)).to(self.device)
116
  self.rots_bias[0] = 1
117
+ self.opacity_bias = self.inverse_opacity_activation(
118
+ torch.tensor(self.opacity_bias)
119
+ ).to(self.device)
120
+
121
 
122
  Gaussian.setup_functions = patched_setup_functions
123
 
 
366
  }
367
 
368
 
 
369
  def unpack_state(state: dict, device: str = "cpu") -> tuple[Gaussian, dict]:
 
370
  gs = Gaussian(
371
  aabb=state["gaussian"]["aabb"],
372
  sh_degree=state["gaussian"]["sh_degree"],
 
376
  scaling_activation=state["gaussian"]["scaling_activation"],
377
  device=device,
378
  )
 
379
  gs._xyz = torch.tensor(state["gaussian"]["_xyz"], device=device)
380
  gs._features_dc = torch.tensor(
381
  state["gaussian"]["_features_dc"], device=device
 
388
  vertices=torch.tensor(state["mesh"]["vertices"], device=device),
389
  faces=torch.tensor(state["mesh"]["faces"], device=device),
390
  )
 
391
 
392
  return gs, mesh
393
 
 
489
  return state, video_path
490
 
491
 
492
+ @spaces.GPU
493
+ def extract_3d_representations(
494
+ state: dict, enable_delight: bool, req: gr.Request
495
+ ):
496
+ output_root = TMP_DIR
497
+ output_root = os.path.join(output_root, str(req.session_hash))
498
+ gs_model, mesh_model = unpack_state(state)
499
+
500
+ mesh = postprocessing_utils.to_glb(
501
+ gs_model,
502
+ mesh_model,
503
+ simplify=0.9,
504
+ texture_size=1024,
505
+ verbose=True,
506
+ )
507
+ filename = "sample"
508
+ gs_path = os.path.join(output_root, f"{filename}_gs.ply")
509
+ gs_model.save_ply(gs_path)
510
+
511
+ # Rotate mesh and GS by 90 degrees around Z-axis.
512
+ rot_matrix = [[0, 0, -1], [0, 1, 0], [1, 0, 0]]
513
+ # Addtional rotation for GS to align mesh.
514
+ gs_rot = np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]]) @ np.array(
515
+ rot_matrix
516
+ )
517
+ pose = GaussianOperator.trans_to_quatpose(gs_rot)
518
+ aligned_gs_path = gs_path.replace(".ply", "_aligned.ply")
519
+ GaussianOperator.resave_ply(
520
+ in_ply=gs_path,
521
+ out_ply=aligned_gs_path,
522
+ instance_pose=pose,
523
+ )
524
+
525
+ mesh.vertices = mesh.vertices @ np.array(rot_matrix)
526
+ mesh_obj_path = os.path.join(output_root, f"{filename}.obj")
527
+ mesh.export(mesh_obj_path)
528
+ mesh_glb_path = os.path.join(output_root, f"{filename}.glb")
529
+ mesh.export(mesh_glb_path)
530
+
531
+ torch.cuda.empty_cache()
532
+
533
+ return mesh_glb_path, gs_path, mesh_obj_path, aligned_gs_path
534
+
535
+
536
  def extract_3d_representations_v2(
537
  state: dict,
538
  enable_delight: bool,
539
  req: gr.Request,
540
  ):
 
541
  output_root = TMP_DIR
542
  user_dir = os.path.join(output_root, str(req.session_hash))
543
  gs_model, mesh_model = unpack_state(state, device="cpu")
 
544
 
545
  filename = "sample"
546
  gs_path = os.path.join(user_dir, f"{filename}_gs.ply")
547
  gs_model.save_ply(gs_path)
 
548
 
549
  # Rotate mesh and GS by 90 degrees around Z-axis.
550
  rot_matrix = [[0, 0, -1], [0, 1, 0], [1, 0, 0]]
 
555
  gs_rot = np.array(gs_add_rot) @ np.array(rot_matrix)
556
  pose = GaussianOperator.trans_to_quatpose(gs_rot)
557
  aligned_gs_path = gs_path.replace(".ply", "_aligned.ply")
 
558
  GaussianOperator.resave_ply(
559
  in_ply=gs_path,
560
  out_ply=aligned_gs_path,
561
  instance_pose=pose,
562
  device="cpu",
563
  )
 
564
  color_path = os.path.join(user_dir, "color.png")
565
  render_gs_api(aligned_gs_path, color_path)
 
566
 
567
  mesh = trimesh.Trimesh(
568
  vertices=mesh_model.vertices.cpu().numpy(),
 
573
 
574
  mesh_obj_path = os.path.join(user_dir, f"{filename}.obj")
575
  mesh.export(mesh_obj_path)
576
+
577
  mesh = backproject_api(
578
  delight_model=DELIGHT,
579
  imagesr_model=IMAGESR_MODEL,
 
583
  skip_fix_mesh=False,
584
  delight=enable_delight,
585
  )
 
586
 
587
  mesh_glb_path = os.path.join(user_dir, f"{filename}.glb")
588
  mesh.export(mesh_glb_path)
 
602
  output_root = TMP_DIR
603
  if req is not None:
604
  output_root = os.path.join(output_root, str(req.session_hash))
605
+
606
  # Convert to URDF and recover attrs by GPT.
607
  filename = "sample"
608
  urdf_convertor = URDFGenerator(GPT_CLIENT, render_view_num=4)