Nekochu commited on
Commit
33e616b
·
1 Parent(s): 1363975

safetensors loading, Phase 0 4x faster (uint8), total time in status

Browse files

- Prefer .safetensors over .pth (faster load, no pickle)
- Phase 0: save uint8 RGB (25MB/frame) instead of float32 (99MB/frame) — 4x less disk I/O
- Status now shows total wall time

Files changed (1) hide show
  1. app.py +33 -20
app.py CHANGED
@@ -68,8 +68,9 @@ CORRIDORKEY_MODELS = {
68
  "1024": os.path.join(MODELS_DIR, "corridorkey_1024.onnx"),
69
  "2048": os.path.join(MODELS_DIR, "corridorkey_2048.onnx"),
70
  }
71
- CORRIDORKEY_PTH_REPO = "nikopueringer/CorridorKey_v1.0"
72
- CORRIDORKEY_PTH_FILE = "CorridorKey_v1.0.pth"
 
73
  IMAGENET_MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32).reshape(1, 1, 3)
74
  IMAGENET_STD = np.array([0.229, 0.224, 0.225], dtype=np.float32).reshape(1, 1, 3)
75
  MAX_DURATION_CPU = 5
@@ -82,17 +83,21 @@ HAS_CUDA = "CUDAExecutionProvider" in ort.get_available_providers()
82
  # ---------------------------------------------------------------------------
83
  logger.info("Preloading model files at startup...")
84
  _preloaded_birefnet_path = None
85
- _preloaded_pth_path = None
86
  try:
87
  _preloaded_birefnet_path = hf_hub_download(repo_id=BIREFNET_REPO, filename=BIREFNET_FILE)
88
  logger.info("BiRefNet cached: %s", _preloaded_birefnet_path)
89
  except Exception as e:
90
  logger.warning("BiRefNet preload failed (will retry later): %s", e)
91
  try:
92
- _preloaded_pth_path = hf_hub_download(repo_id=CORRIDORKEY_PTH_REPO, filename=CORRIDORKEY_PTH_FILE)
93
- logger.info("CorridorKey.pth cached: %s", _preloaded_pth_path)
94
- except Exception as e:
95
- logger.warning("CorridorKey.pth preload failed (will retry later): %s", e)
 
 
 
 
96
 
97
  # Batch sizes for GPU inference (conservative for H200 80GB)
98
  GPU_BATCH_SIZES = {"1024": 32, "2048": 16} # 2048 uses only 5.7GB/batch=2, so 16 easily fits in 69.8GB
@@ -306,7 +311,13 @@ def _load_greenformer(img_size):
306
  import torch.nn.functional as F
307
  from CorridorKeyModule.core.model_transformer import GreenFormer
308
 
309
- checkpoint_path = _preloaded_pth_path or hf_hub_download(repo_id=CORRIDORKEY_PTH_REPO, filename=CORRIDORKEY_PTH_FILE)
 
 
 
 
 
 
310
  logger.info("Using checkpoint: %s", checkpoint_path)
311
 
312
  logger.info("Initializing GreenFormer (img_size=%d)...", img_size)
@@ -316,9 +327,13 @@ def _load_greenformer(img_size):
316
  use_refiner=True,
317
  )
318
 
319
- # Load weights
320
- checkpoint = torch.load(checkpoint_path, map_location="cpu", weights_only=True)
321
- state_dict = checkpoint.get("state_dict", checkpoint)
 
 
 
 
322
 
323
  # Fix compiled model prefix & handle PosEmbed mismatch
324
  new_state_dict = {}
@@ -643,15 +658,13 @@ def _gpu_phase(video_path, resolution, despill_val, mask_mode,
643
  break
644
 
645
  if use_precomputed:
646
- frame_f32 = np.load(os.path.join(precompute_dir, f"frame_{frame_idx:05d}.npy"))
 
647
  mask_path = os.path.join(precompute_dir, f"mask_{frame_idx:05d}.npy")
648
  if os.path.exists(mask_path):
649
  mask = np.load(mask_path)
650
  fast_n += 1
651
  else:
652
- # BiRefNet fallback — load original RGB, run on GPU
653
- rgb_path = os.path.join(precompute_dir, f"rgb_{frame_idx:05d}.npy")
654
- frame_rgb = np.load(rgb_path)
655
  tm = time.time()
656
  mask = birefnet_frame(birefnet, frame_rgb)
657
  t_mask += time.time() - tm
@@ -800,6 +813,7 @@ def _gpu_phase(video_path, resolution, despill_val, mask_mode,
800
  def process_video(video_path, resolution, despill_val, mask_mode,
801
  auto_despeckle, despeckle_size, progress=gr.Progress()):
802
  """Orchestrator: precompute fast masks (CPU) → GPU inference → CPU I/O."""
 
803
  if video_path is None:
804
  raise gr.Error("Please upload a video.")
805
 
@@ -830,12 +844,9 @@ def process_video(video_path, resolution, despill_val, mask_mode,
830
  else:
831
  mask = None
832
  needs_birefnet = True
833
- # Save as compressed numpy (fast to load, no serialization overhead)
834
- np.save(os.path.join(precompute_dir, f"frame_{frame_count:05d}.npy"), frame_f32)
835
  if mask is not None:
836
  np.save(os.path.join(precompute_dir, f"mask_{frame_count:05d}.npy"), mask)
837
- if mask is None:
838
- np.save(os.path.join(precompute_dir, f"rgb_{frame_count:05d}.npy"), frame_rgb)
839
  frame_count += 1
840
  cap.release()
841
  logger.info("[Phase 0] %d frames saved to %s in %.1fs (needs_birefnet=%s)",
@@ -886,9 +897,11 @@ def process_video(video_path, resolution, despill_val, mask_mode,
886
  n = len(frame_times)
887
  avg = np.mean(frame_times) if frame_times else 0
888
  engine = "PyTorch GPU" if use_gpu else "ONNX CPU"
 
889
  status = (f"Processed {n} frames ({w}x{h}) at {resolution}px | "
890
  f"{avg:.2f}s/frame | {engine}" +
891
- (f" batch={batch_size}" if use_gpu else ""))
 
892
 
893
  return (
894
  comp_video if os.path.exists(comp_video) else None,
 
68
  "1024": os.path.join(MODELS_DIR, "corridorkey_1024.onnx"),
69
  "2048": os.path.join(MODELS_DIR, "corridorkey_2048.onnx"),
70
  }
71
+ CORRIDORKEY_REPO = "nikopueringer/CorridorKey_v1.0"
72
+ CORRIDORKEY_SAFETENSORS = "CorridorKey_v1.0.safetensors"
73
+ CORRIDORKEY_PTH_FALLBACK = "CorridorKey_v1.0.pth"
74
  IMAGENET_MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32).reshape(1, 1, 3)
75
  IMAGENET_STD = np.array([0.229, 0.224, 0.225], dtype=np.float32).reshape(1, 1, 3)
76
  MAX_DURATION_CPU = 5
 
83
  # ---------------------------------------------------------------------------
84
  logger.info("Preloading model files at startup...")
85
  _preloaded_birefnet_path = None
86
+ _preloaded_ckpt_path = None
87
  try:
88
  _preloaded_birefnet_path = hf_hub_download(repo_id=BIREFNET_REPO, filename=BIREFNET_FILE)
89
  logger.info("BiRefNet cached: %s", _preloaded_birefnet_path)
90
  except Exception as e:
91
  logger.warning("BiRefNet preload failed (will retry later): %s", e)
92
  try:
93
+ _preloaded_ckpt_path = hf_hub_download(repo_id=CORRIDORKEY_REPO, filename=CORRIDORKEY_SAFETENSORS)
94
+ logger.info("CorridorKey.safetensors cached: %s", _preloaded_ckpt_path)
95
+ except Exception:
96
+ try:
97
+ _preloaded_ckpt_path = hf_hub_download(repo_id=CORRIDORKEY_REPO, filename=CORRIDORKEY_PTH_FALLBACK)
98
+ logger.info("CorridorKey.pth fallback cached: %s", _preloaded_ckpt_path)
99
+ except Exception as e:
100
+ logger.warning("CorridorKey preload failed (will retry later): %s", e)
101
 
102
  # Batch sizes for GPU inference (conservative for H200 80GB)
103
  GPU_BATCH_SIZES = {"1024": 32, "2048": 16} # 2048 uses only 5.7GB/batch=2, so 16 easily fits in 69.8GB
 
311
  import torch.nn.functional as F
312
  from CorridorKeyModule.core.model_transformer import GreenFormer
313
 
314
+ if _preloaded_ckpt_path:
315
+ checkpoint_path = _preloaded_ckpt_path
316
+ else:
317
+ try:
318
+ checkpoint_path = hf_hub_download(repo_id=CORRIDORKEY_REPO, filename=CORRIDORKEY_SAFETENSORS)
319
+ except Exception:
320
+ checkpoint_path = hf_hub_download(repo_id=CORRIDORKEY_REPO, filename=CORRIDORKEY_PTH_FALLBACK)
321
  logger.info("Using checkpoint: %s", checkpoint_path)
322
 
323
  logger.info("Initializing GreenFormer (img_size=%d)...", img_size)
 
327
  use_refiner=True,
328
  )
329
 
330
+ # Load weights (safetensors preferred, .pth fallback)
331
+ if checkpoint_path.endswith(".safetensors"):
332
+ from safetensors.torch import load_file
333
+ state_dict = load_file(checkpoint_path, device="cpu")
334
+ else:
335
+ checkpoint = torch.load(checkpoint_path, map_location="cpu", weights_only=True)
336
+ state_dict = checkpoint.get("state_dict", checkpoint)
337
 
338
  # Fix compiled model prefix & handle PosEmbed mismatch
339
  new_state_dict = {}
 
658
  break
659
 
660
  if use_precomputed:
661
+ frame_rgb = np.load(os.path.join(precompute_dir, f"frame_{frame_idx:05d}.npy"))
662
+ frame_f32 = frame_rgb.astype(np.float32) / 255.0
663
  mask_path = os.path.join(precompute_dir, f"mask_{frame_idx:05d}.npy")
664
  if os.path.exists(mask_path):
665
  mask = np.load(mask_path)
666
  fast_n += 1
667
  else:
 
 
 
668
  tm = time.time()
669
  mask = birefnet_frame(birefnet, frame_rgb)
670
  t_mask += time.time() - tm
 
813
  def process_video(video_path, resolution, despill_val, mask_mode,
814
  auto_despeckle, despeckle_size, progress=gr.Progress()):
815
  """Orchestrator: precompute fast masks (CPU) → GPU inference → CPU I/O."""
816
+ t_total = time.time()
817
  if video_path is None:
818
  raise gr.Error("Please upload a video.")
819
 
 
844
  else:
845
  mask = None
846
  needs_birefnet = True
847
+ np.save(os.path.join(precompute_dir, f"frame_{frame_count:05d}.npy"), frame_rgb)
 
848
  if mask is not None:
849
  np.save(os.path.join(precompute_dir, f"mask_{frame_count:05d}.npy"), mask)
 
 
850
  frame_count += 1
851
  cap.release()
852
  logger.info("[Phase 0] %d frames saved to %s in %.1fs (needs_birefnet=%s)",
 
897
  n = len(frame_times)
898
  avg = np.mean(frame_times) if frame_times else 0
899
  engine = "PyTorch GPU" if use_gpu else "ONNX CPU"
900
+ wall = time.time() - t_total
901
  status = (f"Processed {n} frames ({w}x{h}) at {resolution}px | "
902
  f"{avg:.2f}s/frame | {engine}" +
903
+ (f" batch={batch_size}" if use_gpu else "") +
904
+ f" | {wall:.0f}s total")
905
 
906
  return (
907
  comp_video if os.path.exists(comp_video) else None,