gberton commited on
Commit
2ddc4d2
Β·
1 Parent(s): 0c6ed61

load selected variant inside gpu calls, fix get_cmap removal

Browse files
Files changed (1) hide show
  1. app.py +27 -24
app.py CHANGED
@@ -4,7 +4,6 @@ import colorsys
4
  import os
5
 
6
  import gradio as gr
7
- import matplotlib.cm as cm
8
  import matplotlib.pyplot as plt
9
  import numpy as np
10
  import spaces
@@ -347,9 +346,14 @@ def _ensure_ade20k_embs():
347
  print("Pascal Context text embeddings computed.")
348
 
349
 
350
- def _init_model():
351
- """Load model + move to GPU + compute text embeddings."""
352
- load_variant(_model["name"] or DEFAULT_VARIANT)
 
 
 
 
 
353
  _move_models_to_device()
354
  _ensure_ade20k_embs()
355
 
@@ -464,7 +468,7 @@ def vis_depth(spatial):
464
  h, w = spatial.shape[0], spatial.shape[1]
465
  depth = PCA(n_components=1).fit_transform(feat).reshape(h, w)
466
  depth = (depth - depth.min()) / (depth.max() - depth.min() + 1e-8)
467
- colored = cm.get_cmap("inferno")(depth)[:, :, :3].astype(np.float32)
468
  return to_uint8(colored)
469
 
470
 
@@ -573,7 +577,7 @@ def vis_depth_dpt(depth_map, h, w):
573
  """Colour a depth map with the turbo colormap β†’ PIL Image."""
574
  d = depth_map.squeeze()
575
  d = (d - d.min()) / (d.max() - d.min() + 1e-8)
576
- colored = cm.get_cmap("turbo")(d)[:, :, :3].astype(np.float32)
577
  return to_uint8(upsample(colored, h, w))
578
 
579
 
@@ -643,11 +647,10 @@ def vis_segmentation_dpt(seg_map, orig_image):
643
  # ── Gradio callbacks ────────────────────────────────────────────────────────
644
 
645
 
646
- @spaces.GPU
647
- def on_variant_change(variant_name):
648
- load_variant(variant_name)
649
- _move_models_to_device()
650
- _ensure_ade20k_embs()
651
  return (
652
  None,
653
  None,
@@ -661,10 +664,10 @@ def on_variant_change(variant_name):
661
 
662
 
663
  @spaces.GPU
664
- def on_pca_extract(image, resolution, _pca_state):
665
  if image is None:
666
  return None, None, None, None
667
- _init_model()
668
  resolution = int(resolution)
669
  spatial = extract_features(image, resolution)
670
  h, w = image.shape[:2]
@@ -681,11 +684,11 @@ def on_pca_extract(image, resolution, _pca_state):
681
 
682
 
683
  @spaces.GPU
684
- def on_recluster(image, resolution, n_clusters, pca_state):
685
  if image is None:
686
  gr.Warning("Upload an image first.")
687
  return None, pca_state
688
- _init_model()
689
  resolution = int(resolution)
690
  if (
691
  pca_state is not None
@@ -706,11 +709,11 @@ def on_recluster(image, resolution, n_clusters, pca_state):
706
 
707
 
708
  @spaces.GPU
709
- def on_zeroseg_custom(image, resolution, class_names_str):
710
  if image is None or not class_names_str or not class_names_str.strip():
711
  gr.Warning("Upload an image and enter at least one class name.")
712
  return None, None, "", ""
713
- _init_model()
714
  resolution = int(resolution)
715
  classes = [c.strip() for c in class_names_str.split(",") if c.strip()]
716
  if not classes:
@@ -740,11 +743,11 @@ def on_zeroseg_custom(image, resolution, class_names_str):
740
 
741
 
742
  @spaces.GPU
743
- def on_depth_normals_predict(image, dpt_variant, resolution): # noqa: ARG001
744
  """Run DPT depth and normals prediction."""
745
  if image is None:
746
  return None, None
747
- _init_model()
748
  dev = _device()
749
 
750
  h, w = image.shape[:2]
@@ -761,11 +764,11 @@ def on_depth_normals_predict(image, dpt_variant, resolution): # noqa: ARG001
761
 
762
 
763
  @spaces.GPU
764
- def on_segmentation_predict(image, dpt_variant, resolution): # noqa: ARG001
765
  """Run DPT segmentation prediction."""
766
  if image is None:
767
  return None
768
- _init_model()
769
  dev = _device()
770
 
771
  img = Image.fromarray(image).convert("RGB")
@@ -998,12 +1001,12 @@ with gr.Blocks(head=head, title="TIPSv2 Feature Explorer", css=custom_css) as de
998
 
999
  pca_btn.click(
1000
  fn=on_pca_extract,
1001
- inputs=[pca_input, resolution_dd, pca_state],
1002
  outputs=[pca_out, depth_out, kmeans_out, pca_state],
1003
  )
1004
  recluster_btn.click(
1005
  fn=on_recluster,
1006
- inputs=[pca_input, resolution_dd, n_clusters, pca_state],
1007
  outputs=[kmeans_out, pca_state],
1008
  )
1009
 
@@ -1021,7 +1024,7 @@ with gr.Blocks(head=head, title="TIPSv2 Feature Explorer", css=custom_css) as de
1021
 
1022
  custom_btn.click(
1023
  fn=on_zeroseg_custom,
1024
- inputs=[custom_input, resolution_dd, custom_classes],
1025
  outputs=[custom_overlay, custom_mask, custom_detected, custom_undetected],
1026
  )
1027
 
 
4
  import os
5
 
6
  import gradio as gr
 
7
  import matplotlib.pyplot as plt
8
  import numpy as np
9
  import spaces
 
346
  print("Pascal Context text embeddings computed.")
347
 
348
 
349
+ def _init_model(name=None):
350
+ """Load model + move to GPU + compute text embeddings.
351
+
352
+ Must be called with the requested variant inside each @spaces.GPU function:
353
+ on ZeroGPU those run in a forked worker, so global state mutated in one call
354
+ (e.g. by a dropdown handler) does not survive into the next.
355
+ """
356
+ load_variant(name or _model["name"] or DEFAULT_VARIANT)
357
  _move_models_to_device()
358
  _ensure_ade20k_embs()
359
 
 
468
  h, w = spatial.shape[0], spatial.shape[1]
469
  depth = PCA(n_components=1).fit_transform(feat).reshape(h, w)
470
  depth = (depth - depth.min()) / (depth.max() - depth.min() + 1e-8)
471
+ colored = plt.get_cmap("inferno")(depth)[:, :, :3].astype(np.float32)
472
  return to_uint8(colored)
473
 
474
 
 
577
  """Colour a depth map with the turbo colormap β†’ PIL Image."""
578
  d = depth_map.squeeze()
579
  d = (d - d.min()) / (d.max() - d.min() + 1e-8)
580
+ colored = plt.get_cmap("turbo")(d)[:, :, :3].astype(np.float32)
581
  return to_uint8(upsample(colored, h, w))
582
 
583
 
 
647
  # ── Gradio callbacks ────────────────────────────────────────────────────────
648
 
649
 
650
+ def on_variant_change(variant_name): # noqa: ARG001
651
+ # Only clears stale outputs. The variant is loaded inside the inference
652
+ # handlers themselves β€” loading it here would happen in a ZeroGPU worker
653
+ # whose state is thrown away when the call returns.
 
654
  return (
655
  None,
656
  None,
 
664
 
665
 
666
  @spaces.GPU
667
+ def on_pca_extract(image, variant, resolution, _pca_state):
668
  if image is None:
669
  return None, None, None, None
670
+ _init_model(variant)
671
  resolution = int(resolution)
672
  spatial = extract_features(image, resolution)
673
  h, w = image.shape[:2]
 
684
 
685
 
686
  @spaces.GPU
687
+ def on_recluster(image, variant, resolution, n_clusters, pca_state):
688
  if image is None:
689
  gr.Warning("Upload an image first.")
690
  return None, pca_state
691
+ _init_model(variant)
692
  resolution = int(resolution)
693
  if (
694
  pca_state is not None
 
709
 
710
 
711
  @spaces.GPU
712
+ def on_zeroseg_custom(image, variant, resolution, class_names_str):
713
  if image is None or not class_names_str or not class_names_str.strip():
714
  gr.Warning("Upload an image and enter at least one class name.")
715
  return None, None, "", ""
716
+ _init_model(variant)
717
  resolution = int(resolution)
718
  classes = [c.strip() for c in class_names_str.split(",") if c.strip()]
719
  if not classes:
 
743
 
744
 
745
  @spaces.GPU
746
+ def on_depth_normals_predict(image, dpt_variant, resolution):
747
  """Run DPT depth and normals prediction."""
748
  if image is None:
749
  return None, None
750
+ _init_model(dpt_variant)
751
  dev = _device()
752
 
753
  h, w = image.shape[:2]
 
764
 
765
 
766
  @spaces.GPU
767
+ def on_segmentation_predict(image, dpt_variant, resolution):
768
  """Run DPT segmentation prediction."""
769
  if image is None:
770
  return None
771
+ _init_model(dpt_variant)
772
  dev = _device()
773
 
774
  img = Image.fromarray(image).convert("RGB")
 
1001
 
1002
  pca_btn.click(
1003
  fn=on_pca_extract,
1004
+ inputs=[pca_input, variant_dd, resolution_dd, pca_state],
1005
  outputs=[pca_out, depth_out, kmeans_out, pca_state],
1006
  )
1007
  recluster_btn.click(
1008
  fn=on_recluster,
1009
+ inputs=[pca_input, variant_dd, resolution_dd, n_clusters, pca_state],
1010
  outputs=[kmeans_out, pca_state],
1011
  )
1012
 
 
1024
 
1025
  custom_btn.click(
1026
  fn=on_zeroseg_custom,
1027
+ inputs=[custom_input, variant_dd, resolution_dd, custom_classes],
1028
  outputs=[custom_overlay, custom_mask, custom_detected, custom_undetected],
1029
  )
1030