Spaces:
Running on Zero
Running on Zero
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
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 |
-
|
| 72 |
-
|
|
|
|
| 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 |
-
|
| 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 |
-
|
| 93 |
-
logger.info("CorridorKey.
|
| 94 |
-
except Exception
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 321 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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 |
-
|
| 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,
|