aiqtech commited on
Commit
d88c997
Β·
verified Β·
1 Parent(s): 1f3fd7c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -93
app.py CHANGED
@@ -23,6 +23,7 @@ from typing import Tuple, Dict, Any # Tuple import μΆ”κ°€
23
  import transformers
24
  from transformers import pipeline as transformers_pipeline
25
  from transformers import Pipeline
 
26
 
27
  # μ „μ—­ λ³€μˆ˜ μ΄ˆκΈ°ν™”
28
  class GlobalVars:
@@ -81,7 +82,8 @@ torch.backends.cuda.matmul.allow_tf32 = True
81
  torch.backends.cudnn.benchmark = True
82
 
83
  # ν™˜κ²½ λ³€μˆ˜ μ„€μ •
84
- os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:256,garbage_collection_threshold:0.8"
 
85
  os.environ['SPCONV_ALGO'] = 'native'
86
  os.environ['SPARSE_BACKEND'] = 'native'
87
  os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
@@ -89,7 +91,6 @@ os.environ['XFORMERS_FORCE_DISABLE_TRITON'] = '1'
89
  os.environ['XFORMERS_ENABLE_FLASH_ATTENTION'] = '1'
90
  os.environ['TORCH_CUDA_MEMORY_ALLOCATOR'] = 'native'
91
  os.environ['PYTORCH_NO_CUDA_MEMORY_CACHING'] = '1'
92
- os.environ['CUDA_VISIBLE_DEVICES'] = '0'
93
 
94
  # CUDA μ΄ˆκΈ°ν™” 방지
95
  torch.set_grad_enabled(False)
@@ -207,9 +208,7 @@ def image_to_3d(trial_id: str, seed: int, randomize_seed: bool, ss_guidance_stre
207
  return None, None
208
 
209
  try:
210
- # CUDA λ©”λͺ¨λ¦¬ μ΄ˆκΈ°ν™”
211
- torch.cuda.empty_cache()
212
- torch.cuda.synchronize()
213
 
214
  if randomize_seed:
215
  seed = np.random.randint(0, MAX_SEED)
@@ -232,88 +231,69 @@ def image_to_3d(trial_id: str, seed: int, randomize_seed: bool, ss_guidance_stre
232
  image = image.resize(new_size, Image.LANCZOS)
233
  print(f"Resized image to: {image.size}")
234
 
235
- # GPU μž‘μ—… μ‹œμž‘
236
- with torch.cuda.device(0):
237
- try:
238
- # λͺ¨λΈμ„ GPU둜 이동
239
- move_to_device(g.trellis_pipeline, 'cuda')
240
- torch.cuda.synchronize()
241
-
242
- with torch.inference_mode(), torch.cuda.amp.autocast():
243
- # λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ μ΅œμ ν™”λ₯Ό μœ„ν•œ 배치 크기 μ„€μ •
244
- torch.cuda.set_per_process_memory_fraction(0.8) # GPU λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ μ œν•œ
245
-
246
- # 3D 생성
247
- outputs = g.trellis_pipeline.run(
248
- image,
249
- seed=seed,
250
- formats=["gaussian", "mesh"],
251
- preprocess_image=False,
252
- sparse_structure_sampler_params={
253
- "steps": min(ss_sampling_steps, 20), # μŠ€ν… 수 μ œν•œ
254
- "cfg_strength": ss_guidance_strength,
255
- },
256
- slat_sampler_params={
257
- "steps": min(slat_sampling_steps, 20), # μŠ€ν… 수 μ œν•œ
258
- "cfg_strength": slat_guidance_strength,
259
- },
260
- )
261
- torch.cuda.synchronize()
262
-
263
- # λΉ„λ””μ˜€ λ Œλ”λ§μ„ μœ„ν•œ λ©”λͺ¨λ¦¬ 확보
264
- torch.cuda.empty_cache()
265
-
266
- # λΉ„λ””μ˜€ λ Œλ”λ§
267
- with torch.cuda.amp.autocast():
268
- video = render_utils.render_video(
269
- outputs['gaussian'][0],
270
- num_frames=60, # ν”„λ ˆμž„ 수 κ°μ†Œ
271
- resolution=512 # 해상도 μ œν•œ
272
- )['color']
273
- torch.cuda.synchronize()
274
-
275
- video_geo = render_utils.render_video(
276
- outputs['mesh'][0],
277
- num_frames=60, # ν”„λ ˆμž„ 수 κ°μ†Œ
278
- resolution=512 # 해상도 μ œν•œ
279
- )['normal']
280
- torch.cuda.synchronize()
281
-
282
- # CPU둜 데이터 이동 및 ν›„μ²˜λ¦¬
283
- video = [v.cpu().numpy() if torch.is_tensor(v) else v for v in video]
284
- video_geo = [v.cpu().numpy() if torch.is_tensor(v) else v for v in video_geo]
285
-
286
- video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
287
- new_trial_id = str(uuid.uuid4())
288
- video_path = f"{TMP_DIR}/{new_trial_id}.mp4"
289
- os.makedirs(os.path.dirname(video_path), exist_ok=True)
290
- imageio.mimsave(video_path, video, fps=15)
291
-
292
- # μƒνƒœ μ €μž₯
293
- state = pack_state(outputs['gaussian'][0], outputs['mesh'][0], new_trial_id)
294
-
295
- return state, video_path
296
-
297
- finally:
298
- # 정리 μž‘μ—…
299
- move_to_device(g.trellis_pipeline, 'cpu')
300
- torch.cuda.empty_cache()
301
- torch.cuda.synchronize()
302
-
303
  except Exception as e:
304
  print(f"Error in image_to_3d: {str(e)}")
305
- if hasattr(g.trellis_pipeline, 'to'):
306
- move_to_device(g.trellis_pipeline, 'cpu')
307
- torch.cuda.empty_cache()
308
- torch.cuda.synchronize()
309
  return None, None
 
 
 
 
310
 
311
  def clear_gpu_memory():
312
  """GPU λ©”λͺ¨λ¦¬λ₯Ό μ •λ¦¬ν•˜λŠ” μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜"""
313
- if torch.cuda.is_available():
314
- torch.cuda.empty_cache()
315
- torch.cuda.synchronize()
316
- gc.collect() # 가비지 μ»¬λ ‰μ…˜ μ‹€ν–‰
 
 
 
 
317
 
318
  def move_to_device(model, device):
319
  """λͺ¨λΈμ„ μ•ˆμ „ν•˜κ²Œ λ””λ°”μ΄μŠ€λ‘œ μ΄λ™ν•˜λŠ” ν•¨μˆ˜"""
@@ -346,26 +326,27 @@ def deactivate_button() -> gr.Button:
346
  @spaces.GPU
347
  def text_to_image(prompt: str, height: int, width: int, steps: int, scales: float, seed: int) -> Image.Image:
348
  try:
349
- # CUDA λ©”λͺ¨λ¦¬ 정리
350
- if torch.cuda.is_available():
351
- torch.cuda.empty_cache()
352
-
353
  # ν•œκΈ€ 감지 및 λ²ˆμ—­
354
  def contains_korean(text):
355
  return any(ord('κ°€') <= ord(c) <= ord('힣') for c in text)
356
 
357
- # ν”„λ‘¬ν”„νŠΈ μ „μ²˜λ¦¬
358
  if contains_korean(prompt):
359
  translated = g.translator(prompt)[0]['translation_text']
360
  prompt = translated
361
 
362
- # ν”„λ‘¬ν”„νŠΈ ν˜•μ‹ κ°•μ œ
363
  formatted_prompt = f"wbgmsst, 3D, {prompt}, white background"
364
 
365
- with torch.inference_mode(), torch.autocast("cuda", dtype=torch.bfloat16):
 
 
 
 
 
366
  generated_image = g.flux_pipe(
367
  prompt=[formatted_prompt],
368
- generator=torch.Generator().manual_seed(int(seed)),
369
  num_inference_steps=int(steps),
370
  guidance_scale=float(scales),
371
  height=int(height),
@@ -375,7 +356,9 @@ def text_to_image(prompt: str, height: int, width: int, steps: int, scales: floa
375
 
376
  if generated_image is not None:
377
  trial_id = str(uuid.uuid4())
378
- generated_image.save(f"{TMP_DIR}/{trial_id}.png")
 
 
379
  return generated_image
380
  else:
381
  print("Error: Generated image is None")
@@ -384,6 +367,8 @@ def text_to_image(prompt: str, height: int, width: int, steps: int, scales: floa
384
  except Exception as e:
385
  print(f"Error in image generation: {str(e)}")
386
  return None
 
 
387
 
388
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
389
  gr.Markdown("""## Craft3D""")
@@ -480,9 +465,9 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
480
  label="Click an image to use it",
481
  show_label=True,
482
  elem_id="gallery",
483
- columns=12, # ν•œ 쀄에 12개
484
- rows=2, # 2쀄
485
- height=300, # 높이 μ‘°μ •
486
  allow_preview=True,
487
  object_fit="contain" # 이미지 λΉ„μœ¨ μœ μ§€
488
  )
 
23
  import transformers
24
  from transformers import pipeline as transformers_pipeline
25
  from transformers import Pipeline
26
+ import gc # 파일 상단에 μΆ”κ°€
27
 
28
  # μ „μ—­ λ³€μˆ˜ μ΄ˆκΈ°ν™”
29
  class GlobalVars:
 
82
  torch.backends.cudnn.benchmark = True
83
 
84
  # ν™˜κ²½ λ³€μˆ˜ μ„€μ •
85
+ # ν™˜κ²½ λ³€μˆ˜ μ„€μ •
86
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
87
  os.environ['SPCONV_ALGO'] = 'native'
88
  os.environ['SPARSE_BACKEND'] = 'native'
89
  os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
 
91
  os.environ['XFORMERS_ENABLE_FLASH_ATTENTION'] = '1'
92
  os.environ['TORCH_CUDA_MEMORY_ALLOCATOR'] = 'native'
93
  os.environ['PYTORCH_NO_CUDA_MEMORY_CACHING'] = '1'
 
94
 
95
  # CUDA μ΄ˆκΈ°ν™” 방지
96
  torch.set_grad_enabled(False)
 
208
  return None, None
209
 
210
  try:
211
+ clear_gpu_memory()
 
 
212
 
213
  if randomize_seed:
214
  seed = np.random.randint(0, MAX_SEED)
 
231
  image = image.resize(new_size, Image.LANCZOS)
232
  print(f"Resized image to: {image.size}")
233
 
234
+ with spaces.GPU(), torch.inference_mode():
235
+ # 3D 생성
236
+ g.trellis_pipeline.to('cuda')
237
+ outputs = g.trellis_pipeline.run(
238
+ image,
239
+ seed=seed,
240
+ formats=["gaussian", "mesh"],
241
+ preprocess_image=False,
242
+ sparse_structure_sampler_params={
243
+ "steps": min(ss_sampling_steps, 12),
244
+ "cfg_strength": ss_guidance_strength,
245
+ },
246
+ slat_sampler_params={
247
+ "steps": min(slat_sampling_steps, 12),
248
+ "cfg_strength": slat_guidance_strength,
249
+ },
250
+ )
251
+
252
+ # λΉ„λ””μ˜€ λ Œλ”λ§
253
+ video = render_utils.render_video(
254
+ outputs['gaussian'][0],
255
+ num_frames=60,
256
+ resolution=512
257
+ )['color']
258
+
259
+ video_geo = render_utils.render_video(
260
+ outputs['mesh'][0],
261
+ num_frames=60,
262
+ resolution=512
263
+ )['normal']
264
+
265
+ # CPU둜 데이터 이동
266
+ video = [v.cpu().numpy() if torch.is_tensor(v) else v for v in video]
267
+ video_geo = [v.cpu().numpy() if torch.is_tensor(v) else v for v in video_geo]
268
+
269
+ video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
270
+ new_trial_id = str(uuid.uuid4())
271
+ video_path = f"{TMP_DIR}/{new_trial_id}.mp4"
272
+ os.makedirs(os.path.dirname(video_path), exist_ok=True)
273
+ imageio.mimsave(video_path, video, fps=15)
274
+
275
+ state = pack_state(outputs['gaussian'][0], outputs['mesh'][0], new_trial_id)
276
+
277
+ return state, video_path
278
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  except Exception as e:
280
  print(f"Error in image_to_3d: {str(e)}")
 
 
 
 
281
  return None, None
282
+ finally:
283
+ if hasattr(g.trellis_pipeline, 'to'):
284
+ g.trellis_pipeline.to('cpu')
285
+ clear_gpu_memory()
286
 
287
  def clear_gpu_memory():
288
  """GPU λ©”λͺ¨λ¦¬λ₯Ό μ •λ¦¬ν•˜λŠ” μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜"""
289
+ try:
290
+ if torch.cuda.is_available():
291
+ with torch.cuda.device('cuda'):
292
+ torch.cuda.empty_cache()
293
+ torch.cuda.synchronize()
294
+ gc.collect()
295
+ except Exception as e:
296
+ print(f"Error clearing GPU memory: {e}")
297
 
298
  def move_to_device(model, device):
299
  """λͺ¨λΈμ„ μ•ˆμ „ν•˜κ²Œ λ””λ°”μ΄μŠ€λ‘œ μ΄λ™ν•˜λŠ” ν•¨μˆ˜"""
 
326
  @spaces.GPU
327
  def text_to_image(prompt: str, height: int, width: int, steps: int, scales: float, seed: int) -> Image.Image:
328
  try:
329
+ clear_gpu_memory()
330
+
 
 
331
  # ν•œκΈ€ 감지 및 λ²ˆμ—­
332
  def contains_korean(text):
333
  return any(ord('κ°€') <= ord(c) <= ord('힣') for c in text)
334
 
 
335
  if contains_korean(prompt):
336
  translated = g.translator(prompt)[0]['translation_text']
337
  prompt = translated
338
 
 
339
  formatted_prompt = f"wbgmsst, 3D, {prompt}, white background"
340
 
341
+ # 크기 μ œν•œ
342
+ height = min(height, 512)
343
+ width = min(width, 512)
344
+ steps = min(steps, 12)
345
+
346
+ with spaces.GPU(), torch.inference_mode():
347
  generated_image = g.flux_pipe(
348
  prompt=[formatted_prompt],
349
+ generator=torch.Generator('cuda').manual_seed(int(seed)),
350
  num_inference_steps=int(steps),
351
  guidance_scale=float(scales),
352
  height=int(height),
 
356
 
357
  if generated_image is not None:
358
  trial_id = str(uuid.uuid4())
359
+ save_path = f"{TMP_DIR}/{trial_id}.png"
360
+ generated_image.save(save_path)
361
+ print(f"Saved generated image to: {save_path}")
362
  return generated_image
363
  else:
364
  print("Error: Generated image is None")
 
367
  except Exception as e:
368
  print(f"Error in image generation: {str(e)}")
369
  return None
370
+ finally:
371
+ clear_gpu_memory()
372
 
373
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
374
  gr.Markdown("""## Craft3D""")
 
465
  label="Click an image to use it",
466
  show_label=True,
467
  elem_id="gallery",
468
+ columns=11, # ν•œ 쀄에 12개
469
+ rows=3, # 2쀄
470
+ height=400, # 높이 μ‘°μ •
471
  allow_preview=True,
472
  object_fit="contain" # 이미지 λΉ„μœ¨ μœ μ§€
473
  )