gokaygokay commited on
Commit
abf941c
·
1 Parent(s): b385a4f

trellis first

Browse files
Files changed (1) hide show
  1. app.py +106 -229
app.py CHANGED
@@ -1,9 +1,13 @@
1
  import gradio as gr
2
  import spaces
3
  from gradio_litmodel3d import LitModel3D
4
-
5
  import os
6
  import shutil
 
 
 
 
 
7
  os.environ['SPCONV_ALGO'] = 'native'
8
  from typing import *
9
  import torch
@@ -15,51 +19,28 @@ from trellis.pipelines import TrellisImageTo3DPipeline
15
  from trellis.representations import Gaussian, MeshExtractResult
16
  from trellis.utils import render_utils, postprocessing_utils
17
 
18
-
19
  MAX_SEED = np.iinfo(np.int32).max
20
  TMP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
21
  os.makedirs(TMP_DIR, exist_ok=True)
22
 
 
 
 
 
23
 
24
  def start_session(req: gr.Request):
25
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
26
  os.makedirs(user_dir, exist_ok=True)
27
-
28
-
29
  def end_session(req: gr.Request):
30
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
31
  shutil.rmtree(user_dir)
32
 
33
-
34
  def preprocess_image(image: Image.Image) -> Image.Image:
35
- """
36
- Preprocess the input image.
37
-
38
- Args:
39
- image (Image.Image): The input image.
40
-
41
- Returns:
42
- Image.Image: The preprocessed image.
43
- """
44
- processed_image = pipeline.preprocess_image(image)
45
  return processed_image
46
 
47
-
48
- def preprocess_images(images: List[Tuple[Image.Image, str]]) -> List[Image.Image]:
49
- """
50
- Preprocess a list of input images.
51
-
52
- Args:
53
- images (List[Tuple[Image.Image, str]]): The input images.
54
-
55
- Returns:
56
- List[Image.Image]: The preprocessed images.
57
- """
58
- images = [image[0] for image in images]
59
- processed_images = [pipeline.preprocess_image(image) for image in images]
60
- return processed_images
61
-
62
-
63
  def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
64
  return {
65
  'gaussian': {
@@ -75,9 +56,8 @@ def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
75
  'faces': mesh.faces.cpu().numpy(),
76
  },
77
  }
78
-
79
-
80
- def unpack_state(state: dict) -> Tuple[Gaussian, edict, str]:
81
  gs = Gaussian(
82
  aabb=state['gaussian']['aabb'],
83
  sh_degree=state['gaussian']['sh_degree'],
@@ -99,77 +79,69 @@ def unpack_state(state: dict) -> Tuple[Gaussian, edict, str]:
99
 
100
  return gs, mesh
101
 
102
-
103
  def get_seed(randomize_seed: bool, seed: int) -> int:
104
- """
105
- Get the random seed.
106
- """
107
  return np.random.randint(0, MAX_SEED) if randomize_seed else seed
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  @spaces.GPU
111
  def image_to_3d(
112
  image: Image.Image,
113
- multiimages: List[Tuple[Image.Image, str]],
114
- is_multiimage: bool,
115
  seed: int,
116
  ss_guidance_strength: float,
117
  ss_sampling_steps: int,
118
  slat_guidance_strength: float,
119
  slat_sampling_steps: int,
120
- multiimage_algo: Literal["multidiffusion", "stochastic"],
121
  req: gr.Request,
122
  ) -> Tuple[dict, str]:
123
- """
124
- Convert an image to a 3D model.
125
-
126
- Args:
127
- image (Image.Image): The input image.
128
- multiimages (List[Tuple[Image.Image, str]]): The input images in multi-image mode.
129
- is_multiimage (bool): Whether is in multi-image mode.
130
- seed (int): The random seed.
131
- ss_guidance_strength (float): The guidance strength for sparse structure generation.
132
- ss_sampling_steps (int): The number of sampling steps for sparse structure generation.
133
- slat_guidance_strength (float): The guidance strength for structured latent generation.
134
- slat_sampling_steps (int): The number of sampling steps for structured latent generation.
135
- multiimage_algo (Literal["multidiffusion", "stochastic"]): The algorithm for multi-image generation.
136
-
137
- Returns:
138
- dict: The information of the generated 3D model.
139
- str: The path to the video of the 3D model.
140
- """
141
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
142
- if not is_multiimage:
143
- outputs = pipeline.run(
144
- image,
145
- seed=seed,
146
- formats=["gaussian", "mesh"],
147
- preprocess_image=False,
148
- sparse_structure_sampler_params={
149
- "steps": ss_sampling_steps,
150
- "cfg_strength": ss_guidance_strength,
151
- },
152
- slat_sampler_params={
153
- "steps": slat_sampling_steps,
154
- "cfg_strength": slat_guidance_strength,
155
- },
156
- )
157
- else:
158
- outputs = pipeline.run_multi_image(
159
- [image[0] for image in multiimages],
160
- seed=seed,
161
- formats=["gaussian", "mesh"],
162
- preprocess_image=False,
163
- sparse_structure_sampler_params={
164
- "steps": ss_sampling_steps,
165
- "cfg_strength": ss_guidance_strength,
166
- },
167
- slat_sampler_params={
168
- "steps": slat_sampling_steps,
169
- "cfg_strength": slat_guidance_strength,
170
- },
171
- mode=multiimage_algo,
172
- )
173
  video = render_utils.render_video(outputs['gaussian'][0], num_frames=120)['color']
174
  video_geo = render_utils.render_video(outputs['mesh'][0], num_frames=120)['normal']
175
  video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
@@ -179,7 +151,6 @@ def image_to_3d(
179
  torch.cuda.empty_cache()
180
  return state, video_path
181
 
182
-
183
  @spaces.GPU(duration=90)
184
  def extract_glb(
185
  state: dict,
@@ -187,17 +158,6 @@ def extract_glb(
187
  texture_size: int,
188
  req: gr.Request,
189
  ) -> Tuple[str, str]:
190
- """
191
- Extract a GLB file from the 3D model.
192
-
193
- Args:
194
- state (dict): The state of the generated 3D model.
195
- mesh_simplify (float): The mesh simplification factor.
196
- texture_size (int): The texture resolution.
197
-
198
- Returns:
199
- str: The path to the extracted GLB file.
200
- """
201
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
202
  gs, mesh = unpack_state(state)
203
  glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
@@ -206,18 +166,8 @@ def extract_glb(
206
  torch.cuda.empty_cache()
207
  return glb_path, glb_path
208
 
209
-
210
  @spaces.GPU
211
  def extract_gaussian(state: dict, req: gr.Request) -> Tuple[str, str]:
212
- """
213
- Extract a Gaussian file from the 3D model.
214
-
215
- Args:
216
- state (dict): The state of the generated 3D model.
217
-
218
- Returns:
219
- str: The path to the extracted Gaussian file.
220
- """
221
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
222
  gs, _ = unpack_state(state)
223
  gaussian_path = os.path.join(user_dir, 'sample.ply')
@@ -225,61 +175,30 @@ def extract_gaussian(state: dict, req: gr.Request) -> Tuple[str, str]:
225
  torch.cuda.empty_cache()
226
  return gaussian_path, gaussian_path
227
 
228
-
229
- def prepare_multi_example() -> List[Image.Image]:
230
- multi_case = list(set([i.split('_')[0] for i in os.listdir("assets/example_multi_image")]))
231
- images = []
232
- for case in multi_case:
233
- _images = []
234
- for i in range(1, 4):
235
- img = Image.open(f'assets/example_multi_image/{case}_{i}.png')
236
- W, H = img.size
237
- img = img.resize((int(W / H * 512), 512))
238
- _images.append(np.array(img))
239
- images.append(Image.fromarray(np.concatenate(_images, axis=1)))
240
- return images
241
-
242
-
243
- def split_image(image: Image.Image) -> List[Image.Image]:
244
- """
245
- Split an image into multiple views.
246
- """
247
- image = np.array(image)
248
- alpha = image[..., 3]
249
- alpha = np.any(alpha>0, axis=0)
250
- start_pos = np.where(~alpha[:-1] & alpha[1:])[0].tolist()
251
- end_pos = np.where(alpha[:-1] & ~alpha[1:])[0].tolist()
252
- images = []
253
- for s, e in zip(start_pos, end_pos):
254
- images.append(Image.fromarray(image[:, s:e+1]))
255
- return [preprocess_image(image) for image in images]
256
-
257
-
258
- with gr.Blocks(delete_cache=(600, 600)) as demo:
259
  gr.Markdown("""
260
- ## Image to 3D Asset with [TRELLIS](https://trellis3d.github.io/)
261
- * Upload an image and click "Generate" to create a 3D asset. If the image has alpha channel, it be used as the mask. Otherwise, we use `rembg` to remove the background.
262
  * If you find the generated 3D asset satisfactory, click "Extract GLB" to extract the GLB file and download it.
263
-
264
- ✨New: 1) Experimental multi-image support. 2) Gaussian file extraction.
265
  """)
266
 
267
  with gr.Row():
268
  with gr.Column():
269
- with gr.Tabs() as input_tabs:
270
- with gr.Tab(label="Single Image", id=0) as single_image_input_tab:
271
- image_prompt = gr.Image(label="Image Prompt", format="png", image_mode="RGBA", type="pil", height=300)
272
- with gr.Tab(label="Multiple Images", id=1) as multiimage_input_tab:
273
- multiimage_prompt = gr.Gallery(label="Image Prompt", format="png", type="pil", height=300, columns=3)
274
- gr.Markdown("""
275
- Input different views of the object in separate images.
276
-
277
- *NOTE: this is an experimental algorithm without training a specialized model. It may not produce the best results for all images, especially those having different poses or inconsistent details.*
278
- """)
279
-
280
- with gr.Accordion(label="Generation Settings", open=False):
281
- seed = gr.Slider(0, MAX_SEED, label="Seed", value=0, step=1)
282
  randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
 
 
 
 
 
 
 
 
 
283
  gr.Markdown("Stage 1: Sparse Structure Generation")
284
  with gr.Row():
285
  ss_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=7.5, step=0.1)
@@ -288,97 +207,45 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
288
  with gr.Row():
289
  slat_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=3.0, step=0.1)
290
  slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
291
- multiimage_algo = gr.Radio(["stochastic", "multidiffusion"], label="Multi-image Algorithm", value="stochastic")
292
 
293
  generate_btn = gr.Button("Generate")
294
 
295
- with gr.Accordion(label="GLB Extraction Settings", open=False):
296
  mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify", value=0.95, step=0.01)
297
  texture_size = gr.Slider(512, 2048, label="Texture Size", value=1024, step=512)
298
 
299
  with gr.Row():
300
  extract_glb_btn = gr.Button("Extract GLB", interactive=False)
301
  extract_gs_btn = gr.Button("Extract Gaussian", interactive=False)
302
- gr.Markdown("""
303
- *NOTE: Gaussian file can be very large (~50MB), it will take a while to display and download.*
304
- """)
305
 
306
  with gr.Column():
307
- video_output = gr.Video(label="Generated 3D Asset", autoplay=True, loop=True, height=300)
308
- model_output = LitModel3D(label="Extracted GLB/Gaussian", exposure=10.0, height=300)
 
309
 
310
  with gr.Row():
311
  download_glb = gr.DownloadButton(label="Download GLB", interactive=False)
312
- download_gs = gr.DownloadButton(label="Download Gaussian", interactive=False)
313
-
314
- is_multiimage = gr.State(False)
315
- output_buf = gr.State()
316
 
317
- # Example images at the bottom of the page
318
- with gr.Row() as single_image_example:
319
- examples = gr.Examples(
320
- examples=[
321
- f'assets/example_image/{image}'
322
- for image in os.listdir("assets/example_image")
323
- ],
324
- inputs=[image_prompt],
325
- fn=preprocess_image,
326
- outputs=[image_prompt],
327
- run_on_click=True,
328
- examples_per_page=64,
329
- )
330
- with gr.Row(visible=False) as multiimage_example:
331
- examples_multi = gr.Examples(
332
- examples=prepare_multi_example(),
333
- inputs=[image_prompt],
334
- fn=split_image,
335
- outputs=[multiimage_prompt],
336
- run_on_click=True,
337
- examples_per_page=8,
338
- )
339
 
340
- # Handlers
341
  demo.load(start_session)
342
  demo.unload(end_session)
343
-
344
- single_image_input_tab.select(
345
- lambda: tuple([False, gr.Row.update(visible=True), gr.Row.update(visible=False)]),
346
- outputs=[is_multiimage, single_image_example, multiimage_example]
347
- )
348
- multiimage_input_tab.select(
349
- lambda: tuple([True, gr.Row.update(visible=False), gr.Row.update(visible=True)]),
350
- outputs=[is_multiimage, single_image_example, multiimage_example]
351
- )
352
-
353
- image_prompt.upload(
354
- preprocess_image,
355
- inputs=[image_prompt],
356
- outputs=[image_prompt],
357
- )
358
- multiimage_prompt.upload(
359
- preprocess_images,
360
- inputs=[multiimage_prompt],
361
- outputs=[multiimage_prompt],
362
- )
363
 
364
  generate_btn.click(
365
- get_seed,
366
- inputs=[randomize_seed, seed],
367
- outputs=[seed],
368
  ).then(
369
  image_to_3d,
370
- inputs=[image_prompt, multiimage_prompt, is_multiimage, seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps, multiimage_algo],
371
  outputs=[output_buf, video_output],
372
  ).then(
373
  lambda: tuple([gr.Button(interactive=True), gr.Button(interactive=True)]),
374
  outputs=[extract_glb_btn, extract_gs_btn],
375
  )
376
 
377
- video_output.clear(
378
- lambda: tuple([gr.Button(interactive=False), gr.Button(interactive=False)]),
379
- outputs=[extract_glb_btn, extract_gs_btn],
380
- )
381
-
382
  extract_glb_btn.click(
383
  extract_glb,
384
  inputs=[output_buf, mesh_simplify, texture_size],
@@ -401,14 +268,24 @@ with gr.Blocks(delete_cache=(600, 600)) as demo:
401
  lambda: gr.Button(interactive=False),
402
  outputs=[download_glb],
403
  )
404
-
405
 
406
- # Launch the Gradio app
407
  if __name__ == "__main__":
408
- pipeline = TrellisImageTo3DPipeline.from_pretrained("JeffreyXiang/TRELLIS-image-large")
409
- pipeline.cuda()
 
 
 
 
 
 
 
 
 
 
410
  try:
411
- pipeline.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8))) # Preload rembg
412
  except:
413
  pass
414
- demo.launch()
 
 
1
  import gradio as gr
2
  import spaces
3
  from gradio_litmodel3d import LitModel3D
 
4
  import os
5
  import shutil
6
+ import random
7
+ import uuid
8
+ from datetime import datetime
9
+ from diffusers import DiffusionPipeline
10
+
11
  os.environ['SPCONV_ALGO'] = 'native'
12
  from typing import *
13
  import torch
 
19
  from trellis.representations import Gaussian, MeshExtractResult
20
  from trellis.utils import render_utils, postprocessing_utils
21
 
22
+ # Constants
23
  MAX_SEED = np.iinfo(np.int32).max
24
  TMP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
25
  os.makedirs(TMP_DIR, exist_ok=True)
26
 
27
+ # Create permanent storage directory for Flux generated images
28
+ SAVE_DIR = "saved_images"
29
+ if not os.path.exists(SAVE_DIR):
30
+ os.makedirs(SAVE_DIR, exist_ok=True)
31
 
32
  def start_session(req: gr.Request):
33
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
34
  os.makedirs(user_dir, exist_ok=True)
35
+
 
36
  def end_session(req: gr.Request):
37
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
38
  shutil.rmtree(user_dir)
39
 
 
40
  def preprocess_image(image: Image.Image) -> Image.Image:
41
+ processed_image = trellis_pipeline.preprocess_image(image)
 
 
 
 
 
 
 
 
 
42
  return processed_image
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  def pack_state(gs: Gaussian, mesh: MeshExtractResult) -> dict:
45
  return {
46
  'gaussian': {
 
56
  'faces': mesh.faces.cpu().numpy(),
57
  },
58
  }
59
+
60
+ def unpack_state(state: dict) -> Tuple[Gaussian, edict]:
 
61
  gs = Gaussian(
62
  aabb=state['gaussian']['aabb'],
63
  sh_degree=state['gaussian']['sh_degree'],
 
79
 
80
  return gs, mesh
81
 
 
82
  def get_seed(randomize_seed: bool, seed: int) -> int:
 
 
 
83
  return np.random.randint(0, MAX_SEED) if randomize_seed else seed
84
 
85
+ def generate_flux_image(
86
+ prompt: str,
87
+ seed: int,
88
+ randomize_seed: bool,
89
+ width: int,
90
+ height: int,
91
+ guidance_scale: float,
92
+ num_inference_steps: int,
93
+ lora_scale: float,
94
+ progress: gr.Progress = gr.Progress(track_tqdm=True),
95
+ ) -> Image.Image:
96
+ """Generate image using Flux pipeline"""
97
+ if randomize_seed:
98
+ seed = random.randint(0, MAX_SEED)
99
+ generator = torch.Generator(device=device).manual_seed(seed)
100
+
101
+ image = flux_pipeline(
102
+ prompt=prompt,
103
+ guidance_scale=guidance_scale,
104
+ num_inference_steps=num_inference_steps,
105
+ width=width,
106
+ height=height,
107
+ generator=generator,
108
+ joint_attention_kwargs={"scale": lora_scale},
109
+ ).images[0]
110
+
111
+ # Save the generated image
112
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
113
+ unique_id = str(uuid.uuid4())[:8]
114
+ filename = f"{timestamp}_{unique_id}.png"
115
+ filepath = os.path.join(SAVE_DIR, filename)
116
+ image.save(filepath)
117
+
118
+ return image
119
 
120
  @spaces.GPU
121
  def image_to_3d(
122
  image: Image.Image,
 
 
123
  seed: int,
124
  ss_guidance_strength: float,
125
  ss_sampling_steps: int,
126
  slat_guidance_strength: float,
127
  slat_sampling_steps: int,
 
128
  req: gr.Request,
129
  ) -> Tuple[dict, str]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
131
+ outputs = trellis_pipeline.run(
132
+ image,
133
+ seed=seed,
134
+ formats=["gaussian", "mesh"],
135
+ preprocess_image=False,
136
+ sparse_structure_sampler_params={
137
+ "steps": ss_sampling_steps,
138
+ "cfg_strength": ss_guidance_strength,
139
+ },
140
+ slat_sampler_params={
141
+ "steps": slat_sampling_steps,
142
+ "cfg_strength": slat_guidance_strength,
143
+ },
144
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  video = render_utils.render_video(outputs['gaussian'][0], num_frames=120)['color']
146
  video_geo = render_utils.render_video(outputs['mesh'][0], num_frames=120)['normal']
147
  video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
 
151
  torch.cuda.empty_cache()
152
  return state, video_path
153
 
 
154
  @spaces.GPU(duration=90)
155
  def extract_glb(
156
  state: dict,
 
158
  texture_size: int,
159
  req: gr.Request,
160
  ) -> Tuple[str, str]:
 
 
 
 
 
 
 
 
 
 
 
161
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
162
  gs, mesh = unpack_state(state)
163
  glb = postprocessing_utils.to_glb(gs, mesh, simplify=mesh_simplify, texture_size=texture_size, verbose=False)
 
166
  torch.cuda.empty_cache()
167
  return glb_path, glb_path
168
 
 
169
  @spaces.GPU
170
  def extract_gaussian(state: dict, req: gr.Request) -> Tuple[str, str]:
 
 
 
 
 
 
 
 
 
171
  user_dir = os.path.join(TMP_DIR, str(req.session_hash))
172
  gs, _ = unpack_state(state)
173
  gaussian_path = os.path.join(user_dir, 'sample.ply')
 
175
  torch.cuda.empty_cache()
176
  return gaussian_path, gaussian_path
177
 
178
+ # Gradio Interface
179
+ with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  gr.Markdown("""
181
+ ## Game Asset Generation to 3D with FLUX and TRELLIS
182
+ * Enter a prompt to generate a game asset image, then convert it to 3D
183
  * If you find the generated 3D asset satisfactory, click "Extract GLB" to extract the GLB file and download it.
 
 
184
  """)
185
 
186
  with gr.Row():
187
  with gr.Column():
188
+ # Flux image generation inputs
189
+ prompt = gr.Text(label="Prompt", placeholder="Enter your game asset description")
190
+ with gr.Accordion("Generation Settings", open=False):
191
+ seed = gr.Slider(0, MAX_SEED, label="Seed", value=42, step=1)
 
 
 
 
 
 
 
 
 
192
  randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
193
+ with gr.Row():
194
+ width = gr.Slider(256, 1024, label="Width", value=768, step=32)
195
+ height = gr.Slider(256, 1024, label="Height", value=768, step=32)
196
+ with gr.Row():
197
+ guidance_scale = gr.Slider(0.0, 10.0, label="Guidance Scale", value=3.5, step=0.1)
198
+ num_inference_steps = gr.Slider(1, 50, label="Steps", value=30, step=1)
199
+ lora_scale = gr.Slider(0.0, 1.0, label="LoRA Scale", value=1.0, step=0.1)
200
+
201
+ with gr.Accordion("3D Generation Settings", open=False):
202
  gr.Markdown("Stage 1: Sparse Structure Generation")
203
  with gr.Row():
204
  ss_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=7.5, step=0.1)
 
207
  with gr.Row():
208
  slat_guidance_strength = gr.Slider(0.0, 10.0, label="Guidance Strength", value=3.0, step=0.1)
209
  slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
 
210
 
211
  generate_btn = gr.Button("Generate")
212
 
213
+ with gr.Accordion("GLB Extraction Settings", open=False):
214
  mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify", value=0.95, step=0.01)
215
  texture_size = gr.Slider(512, 2048, label="Texture Size", value=1024, step=512)
216
 
217
  with gr.Row():
218
  extract_glb_btn = gr.Button("Extract GLB", interactive=False)
219
  extract_gs_btn = gr.Button("Extract Gaussian", interactive=False)
 
 
 
220
 
221
  with gr.Column():
222
+ generated_image = gr.Image(label="Generated Asset", type="pil")
223
+ video_output = gr.Video(label="Generated 3D Asset", autoplay=True, loop=True)
224
+ model_output = LitModel3D(label="Extracted GLB/Gaussian")
225
 
226
  with gr.Row():
227
  download_glb = gr.DownloadButton(label="Download GLB", interactive=False)
228
+ download_gs = gr.DownloadButton(label="Download Gaussian", interactive=False)
 
 
 
229
 
230
+ output_buf = gr.State()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
 
232
+ # Event handlers
233
  demo.load(start_session)
234
  demo.unload(end_session)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  generate_btn.click(
237
+ generate_flux_image,
238
+ inputs=[prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps, lora_scale],
239
+ outputs=[generated_image],
240
  ).then(
241
  image_to_3d,
242
+ inputs=[generated_image, seed, ss_guidance_strength, ss_sampling_steps, slat_guidance_strength, slat_sampling_steps],
243
  outputs=[output_buf, video_output],
244
  ).then(
245
  lambda: tuple([gr.Button(interactive=True), gr.Button(interactive=True)]),
246
  outputs=[extract_glb_btn, extract_gs_btn],
247
  )
248
 
 
 
 
 
 
249
  extract_glb_btn.click(
250
  extract_glb,
251
  inputs=[output_buf, mesh_simplify, texture_size],
 
268
  lambda: gr.Button(interactive=False),
269
  outputs=[download_glb],
270
  )
 
271
 
272
+ # Initialize both pipelines
273
  if __name__ == "__main__":
274
+ # Initialize Flux pipeline
275
+ device = "cuda" if torch.cuda.is_available() else "cpu"
276
+ flux_pipeline = DiffusionPipeline.from_pretrained(
277
+ "black-forest-labs/FLUX.1-dev",
278
+ torch_dtype=torch.bfloat16
279
+ )
280
+ flux_pipeline.load_lora_weights("gokaygokay/Flux-Game-Assets-LoRA-v2")
281
+ flux_pipeline = flux_pipeline.to(device)
282
+
283
+ # Initialize Trellis pipeline
284
+ trellis_pipeline = TrellisImageTo3DPipeline.from_pretrained("JeffreyXiang/TRELLIS-image-large")
285
+ trellis_pipeline.cuda()
286
  try:
287
+ trellis_pipeline.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8)))
288
  except:
289
  pass
290
+
291
+ demo.launch()