Surn commited on
Commit
375c110
·
1 Parent(s): 7cff785

Advanced 3D settings

Browse files
.gitignore CHANGED
@@ -163,7 +163,7 @@ cython_debug/
163
  /.vs
164
  /src/__pycache__
165
  /utils/__pycache__
166
- /__pycache__
167
  /temp_models
168
  /.vscode/settings.json
169
  **/*.pyc
 
163
  /.vs
164
  /src/__pycache__
165
  /utils/__pycache__
166
+ **/__pycache__
167
  /temp_models
168
  /.vscode/settings.json
169
  **/*.pyc
app.py CHANGED
@@ -613,7 +613,7 @@ def combine_images_with_lerp(input_image, output_image, alpha):
613
  print(f"Combining images with alpha: {alpha}")
614
  return lerp_imagemath(in_image, out_image, alpha)
615
 
616
- def add_border(image, mask_width, mask_height, blank_color):
617
  bordered_image_output = Image.open(image).convert("RGBA")
618
  margin_color = detect_color_format(blank_color)
619
  print(f"Adding border to image with width: {mask_width}, height: {mask_height}, color: {margin_color}")
@@ -751,47 +751,54 @@ def generate_3d_asset_part1(depth_image_source, randomize_seed, seed, input_imag
751
  # Determine the final seed using default MAX_SEED from constants
752
  final_seed = np.random.randint(0, constants.MAX_SEED) if randomize_seed else seed
753
  # Process the image for depth estimation
754
- depth_img = depth_process_image(image_path, resized_width=1536, z_scale=332)
755
  depth_img = resize_image_with_aspect_ratio(depth_img, 1536, 1536)
756
 
757
  return depth_img, image_path, output_name, final_seed
758
 
759
  @spaces.GPU(duration=150,progress=gr.Progress(track_tqdm=True))
760
- def generate_3d_asset_part2(depth_img, image_path, output_name, seed, req: gr.Request, progress=gr.Progress(track_tqdm=True)):
761
  # Open image using standardized defaults
762
  image_raw = Image.open(image_path).convert("RGB")
763
- resized_image = resize_image_with_aspect_ratio(image_raw, 1536, 1536)
764
  depth_img = Image.open(depth_img).convert("RGBA")
765
  # Preprocess and run the Trellis pipeline with fixed sampler settings
766
- processed_image = TRELLIS_PIPELINE.preprocess_image(resized_image, max_resolution=1536)
767
- outputs = TRELLIS_PIPELINE.run(
768
- processed_image,
769
- seed=seed,
770
- formats=["gaussian", "mesh"],
771
- preprocess_image=False,
772
- sparse_structure_sampler_params={
773
- "steps": 15,
774
- "cfg_strength": 7.5,
775
- },
776
- slat_sampler_params={
777
- "steps": 15,
778
- "cfg_strength": 3.0,
779
- },
780
- )
 
781
 
782
- # Validate the mesh
783
- mesh = outputs['mesh'][0]
784
- meshisdict = isinstance(mesh, dict)
785
- if meshisdict:
786
- vertices = mesh['vertices']
787
- faces = mesh['faces']
788
- else:
789
- vertices = mesh.vertices
790
- faces = mesh.faces
791
 
792
- print(f"Mesh vertices: {vertices.shape}, faces: {faces.shape}")
793
- if faces.max() >= vertices.shape[0]:
794
- raise ValueError(f"Invalid mesh: face index {faces.max()} exceeds vertex count {vertices.shape[0]}")
 
 
 
 
 
 
795
 
796
  # Ensure data is on GPU and has correct type
797
  if not vertices.is_cuda or not faces.is_cuda:
@@ -807,9 +814,13 @@ def generate_3d_asset_part2(depth_img, image_path, output_name, seed, req: gr.Re
807
  user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
808
  os.makedirs(user_dir, exist_ok=True)
809
 
810
- video = render_utils.render_video(outputs['gaussian'][0], resolution=576, num_frames=64, r=1, fov=45)['color']
811
- video_geo = render_utils.render_video(outputs['mesh'][0], resolution=576, num_frames=64, r=1, fov=45)['normal']
812
- video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
 
 
 
 
813
  video_path = os.path.join(user_dir, f'{output_name}.mp4')
814
  imageio.mimsave(video_path, video, fps=8)
815
 
@@ -818,7 +829,9 @@ def generate_3d_asset_part2(depth_img, image_path, output_name, seed, req: gr.Re
818
  depth_snapshot = depth_img
819
 
820
  state = pack_state(outputs['gaussian'][0], outputs['mesh'][0], output_name)
821
- torch.cuda.empty_cache()
 
 
822
  return [state, video_path, depth_snapshot]
823
 
824
 
@@ -845,7 +858,9 @@ def extract_glb(
845
  glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
846
  glb_path = os.path.join(user_dir, f'{name}.glb')
847
  glb.export(glb_path)
 
848
  torch.cuda.empty_cache()
 
849
  return glb_path, glb_path
850
 
851
  @spaces.GPU(progress=gr.Progress(track_tqdm=True))
@@ -863,7 +878,9 @@ def extract_gaussian(state: dict, req: gr.Request, progress=gr.Progress(track_tq
863
  gs, _, name = unpack_state(state)
864
  gaussian_path = os.path.join(user_dir, f'{name}.ply')
865
  gs.save_ply(gaussian_path)
 
866
  torch.cuda.empty_cache()
 
867
  return gaussian_path, gaussian_path
868
 
869
 
@@ -1171,16 +1188,21 @@ with gr.Blocks(css_paths="style_20250128.css", title=title, theme='Surn/beeuty',
1171
 
1172
  with gr.Accordion("Height Maps and 3D", open=False):
1173
  with gr.Row():
1174
- with gr.Column():
1175
- # Use standard seed settings only
1176
- seed_3d = gr.Slider(0, constants.MAX_SEED, label="Seed (3D Generation)", value=0, step=1, randomize=True)
1177
- randomize_seed_3d = gr.Checkbox(label="Randomize Seed (3D Generation)", value=True)
1178
- with gr.Column():
1179
- depth_image_source = gr.Radio(
1180
- label="Depth Image Source",
1181
- choices=["Input Image", "Output Image", "Overlay Image", "Image with Margins"],
1182
- value="Input Image"
1183
- )
 
 
 
 
 
1184
  with gr.Row():
1185
  generate_3d_asset_button = gr.Button("Generate 3D Asset", elem_classes="solid", variant="secondary")
1186
  with gr.Row():
@@ -1196,9 +1218,16 @@ with gr.Blocks(css_paths="style_20250128.css", title=title, theme='Surn/beeuty',
1196
  extract_glb_btn = gr.Button("Extract GLB", interactive=False)
1197
  extract_gaussian_btn = gr.Button("Extract Gaussian", interactive=False)
1198
  with gr.Row():
1199
- model_output = gr.Model3D(label="Extracted 3D Model", clear_color=[1.0, 1.0, 1.0, 1.0],
 
1200
  elem_classes="centered solid imgcontainer", interactive=True)
1201
- model_file = gr.File(label="3D GLTF", elem_classes="solid small centered")
 
 
 
 
 
 
1202
  is_multiimage = gr.State(False)
1203
  output_buf = gr.State()
1204
  ddd_image_path = gr.State("./images/images/Beeuty-1.png")
@@ -1320,7 +1349,7 @@ with gr.Blocks(css_paths="style_20250128.css", title=title, theme='Surn/beeuty',
1320
  scroll_to_output=True
1321
  ).then(
1322
  fn=generate_3d_asset_part2,
1323
- inputs=[depth_output, ddd_image_path, ddd_file_name, seed_3d ],
1324
  outputs=[output_buf, video_output, depth_output],
1325
  scroll_to_output=True
1326
  ).then(
@@ -1332,19 +1361,19 @@ with gr.Blocks(css_paths="style_20250128.css", title=title, theme='Surn/beeuty',
1332
  extract_glb_btn.click(
1333
  fn=extract_glb,
1334
  inputs=[output_buf, mesh_simplify, texture_size],
1335
- outputs=[model_output, model_file]
1336
  ).then(
1337
  lambda: gr.Button(interactive=True),
1338
- outputs=[model_file]
1339
  )
1340
 
1341
  extract_gaussian_btn.click(
1342
  fn=extract_gaussian,
1343
  inputs=[output_buf],
1344
- outputs=[model_output, model_file]
1345
  ).then(
1346
  lambda: gr.Button(interactive=True),
1347
- outputs=[model_file]
1348
  )
1349
 
1350
  if __name__ == "__main__":
 
613
  print(f"Combining images with alpha: {alpha}")
614
  return lerp_imagemath(in_image, out_image, alpha)
615
 
616
+ def add_border(image, mask_width, mask_height, blank_color):
617
  bordered_image_output = Image.open(image).convert("RGBA")
618
  margin_color = detect_color_format(blank_color)
619
  print(f"Adding border to image with width: {mask_width}, height: {mask_height}, color: {margin_color}")
 
751
  # Determine the final seed using default MAX_SEED from constants
752
  final_seed = np.random.randint(0, constants.MAX_SEED) if randomize_seed else seed
753
  # Process the image for depth estimation
754
+ depth_img = depth_process_image(image_path, resized_width=1536, z_scale=336)
755
  depth_img = resize_image_with_aspect_ratio(depth_img, 1536, 1536)
756
 
757
  return depth_img, image_path, output_name, final_seed
758
 
759
  @spaces.GPU(duration=150,progress=gr.Progress(track_tqdm=True))
760
+ def generate_3d_asset_part2(depth_img, image_path, output_name, seed, steps, model_resolution, video_resolution, req: gr.Request, progress=gr.Progress(track_tqdm=True)):
761
  # Open image using standardized defaults
762
  image_raw = Image.open(image_path).convert("RGB")
763
+ resized_image = resize_image_with_aspect_ratio(image_raw, model_resolution, model_resolution)
764
  depth_img = Image.open(depth_img).convert("RGBA")
765
  # Preprocess and run the Trellis pipeline with fixed sampler settings
766
+ try:
767
+ processed_image = TRELLIS_PIPELINE.preprocess_image(resized_image, max_resolution=model_resolution)
768
+ outputs = TRELLIS_PIPELINE.run(
769
+ processed_image,
770
+ seed=seed,
771
+ formats=["gaussian", "mesh"],
772
+ preprocess_image=False,
773
+ sparse_structure_sampler_params={
774
+ "steps": steps,
775
+ "cfg_strength": 7.5,
776
+ },
777
+ slat_sampler_params={
778
+ "steps": steps,
779
+ "cfg_strength": 3.0,
780
+ },
781
+ )
782
 
783
+ # Validate the mesh
784
+ mesh = outputs['mesh'][0]
785
+ meshisdict = isinstance(mesh, dict)
786
+ if meshisdict:
787
+ vertices = mesh['vertices']
788
+ faces = mesh['faces']
789
+ else:
790
+ vertices = mesh.vertices
791
+ faces = mesh.faces
792
 
793
+ print(f"Mesh vertices: {vertices.shape}, faces: {faces.shape}")
794
+ if faces.max() >= vertices.shape[0]:
795
+ raise ValueError(f"Invalid mesh: face index {faces.max()} exceeds vertex count {vertices.shape[0]}")
796
+ except Exception as e:
797
+ gr.Warning(f"Error generating 3D asset: {e}")
798
+ print(f"Error generating 3D asset: {e}")
799
+ torch.cuda.empty_cache()
800
+ torch.cuda.ipc_collect()
801
+ return None,None, depth_img
802
 
803
  # Ensure data is on GPU and has correct type
804
  if not vertices.is_cuda or not faces.is_cuda:
 
814
  user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
815
  os.makedirs(user_dir, exist_ok=True)
816
 
817
+ video = render_utils.render_video(outputs['gaussian'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['color']
818
+ try:
819
+ video_geo = render_utils.render_video(outputs['mesh'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['normal']
820
+ video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
821
+ except Exception as e:
822
+ gr.Info(f"Error rendering video: {e}")
823
+ print(f"Error rendering video: {e}")
824
  video_path = os.path.join(user_dir, f'{output_name}.mp4')
825
  imageio.mimsave(video_path, video, fps=8)
826
 
 
829
  depth_snapshot = depth_img
830
 
831
  state = pack_state(outputs['gaussian'][0], outputs['mesh'][0], output_name)
832
+ if torch.cuda.is_available():
833
+ torch.cuda.empty_cache()
834
+ torch.cuda.ipc_collect()
835
  return [state, video_path, depth_snapshot]
836
 
837
 
 
858
  glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
859
  glb_path = os.path.join(user_dir, f'{name}.glb')
860
  glb.export(glb_path)
861
+
862
  torch.cuda.empty_cache()
863
+ torch.cuda.ipc_collect()
864
  return glb_path, glb_path
865
 
866
  @spaces.GPU(progress=gr.Progress(track_tqdm=True))
 
878
  gs, _, name = unpack_state(state)
879
  gaussian_path = os.path.join(user_dir, f'{name}.ply')
880
  gs.save_ply(gaussian_path)
881
+
882
  torch.cuda.empty_cache()
883
+ torch.cuda.ipc_collect()
884
  return gaussian_path, gaussian_path
885
 
886
 
 
1188
 
1189
  with gr.Accordion("Height Maps and 3D", open=False):
1190
  with gr.Row():
1191
+ depth_image_source = gr.Radio(
1192
+ label="Depth Image Source",
1193
+ choices=["Input Image", "Hexagon Grid Image", "Overlay Image", "Image with Margins"],
1194
+ value="Input Image"
1195
+ )
1196
+ with gr.Accordion("Advanced 3D Generation Settings", open=False):
1197
+ with gr.Row():
1198
+ with gr.Column():
1199
+ # Use standard seed settings only
1200
+ seed_3d = gr.Slider(0, constants.MAX_SEED, label="Seed (3D Generation)", value=0, step=1, randomize=True)
1201
+ randomize_seed_3d = gr.Checkbox(label="Randomize Seed (3D Generation)", value=True)
1202
+ with gr.Column():
1203
+ steps = gr.Slider(6, 36, value=12, step=1, label="Image Sampling Steps", interactive=True)
1204
+ video_resolution = gr.Slider(384, 768, value=480, step=32, label="Video Resolution (*danger*)", interactive=True)
1205
+ model_resolution = gr.Slider(512, 2304, value=1024, step=64, label="3D Model Resolution", interactive=True)
1206
  with gr.Row():
1207
  generate_3d_asset_button = gr.Button("Generate 3D Asset", elem_classes="solid", variant="secondary")
1208
  with gr.Row():
 
1218
  extract_glb_btn = gr.Button("Extract GLB", interactive=False)
1219
  extract_gaussian_btn = gr.Button("Extract Gaussian", interactive=False)
1220
  with gr.Row():
1221
+ with gr.Column(scale=2):
1222
+ model_output = gr.Model3D(label="Extracted 3D Model", clear_color=[1.0, 1.0, 1.0, 1.0],
1223
  elem_classes="centered solid imgcontainer", interactive=True)
1224
+ with gr.Column(scale=1):
1225
+ glb_file = gr.File(label="3D GLTF", elem_classes="solid small centered", height=250)
1226
+ gaussian_file = gr.File(label="Gaussian", elem_classes="solid small centered", height=250)
1227
+ gr.Markdown("""
1228
+ ### Files over 10 MB may not display in the 3D model viewer
1229
+ """, elem_id="file_size_info", elem_classes="intro" )
1230
+
1231
  is_multiimage = gr.State(False)
1232
  output_buf = gr.State()
1233
  ddd_image_path = gr.State("./images/images/Beeuty-1.png")
 
1349
  scroll_to_output=True
1350
  ).then(
1351
  fn=generate_3d_asset_part2,
1352
+ inputs=[depth_output, ddd_image_path, ddd_file_name, seed_3d, steps, model_resolution, video_resolution ],
1353
  outputs=[output_buf, video_output, depth_output],
1354
  scroll_to_output=True
1355
  ).then(
 
1361
  extract_glb_btn.click(
1362
  fn=extract_glb,
1363
  inputs=[output_buf, mesh_simplify, texture_size],
1364
+ outputs=[model_output, glb_file]
1365
  ).then(
1366
  lambda: gr.Button(interactive=True),
1367
+ outputs=[glb_file]
1368
  )
1369
 
1370
  extract_gaussian_btn.click(
1371
  fn=extract_gaussian,
1372
  inputs=[output_buf],
1373
+ outputs=[model_output, gaussian_file]
1374
  ).then(
1375
  lambda: gr.Button(interactive=True),
1376
+ outputs=[gaussian_file]
1377
  )
1378
 
1379
  if __name__ == "__main__":
trellis/modules/transformer/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (216 Bytes)
 
trellis/modules/transformer/__pycache__/blocks.cpython-312.pyc DELETED
Binary file (9.18 kB)
 
trellis/modules/transformer/__pycache__/modulated.cpython-312.pyc DELETED
Binary file (7.64 kB)