misla122 commited on
Commit
92dd353
·
verified ·
1 Parent(s): 7e61b50

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +28 -46
app.py CHANGED
@@ -1,97 +1,80 @@
1
-
2
  import os
3
- # Ensure Hugging Face runs in PyTorch mode
4
- os.environ["TRANSFORMERS_NO_TF"] = "1"
5
 
6
  import numpy as np
7
  from PIL import Image, ImageFilter
8
  import gradio as gr
9
-
10
- # Torch is imported lazily so the Space can boot even if torch takes time to install
11
  import torch
12
  from transformers import pipeline
13
 
14
- # Device selection: GPU if available; otherwise CPU (-1)
15
  DEVICE = 0 if torch.cuda.is_available() else -1
 
 
 
16
 
17
- # Model identifiers
18
- SEG_MODEL_NAME = "nvidia/segformer-b0-finetuned-ade-512-512"
19
- DEPTH_MODEL_NAME = "Intel/dpt-hybrid-midas"
20
- TARGET_SIZE = (512, 512)
21
-
22
- # Pipelines: loaded once on process start
23
- seg_pipe = pipeline("image-segmentation", model=SEG_MODEL_NAME, device=DEVICE, framework="pt")
24
- depth_pipe = pipeline("depth-estimation", model=DEPTH_MODEL_NAME, device=DEVICE, framework="pt")
25
 
26
- def resize_center_crop(img: Image.Image, size=(512, 512)) -> Image.Image:
27
- """Resize with aspect ratio, center-crop to size."""
28
  img = img.convert("RGB")
29
  w, h = img.size
30
  tw, th = size
31
- scale = max(tw / w, th / h)
32
- nw, nh = int(round(w * scale)), int(round(h * scale))
33
  img = img.resize((nw, nh), Image.BICUBIC)
34
  left, top = (nw - tw) // 2, (nh - th) // 2
35
  return img.crop((left, top, left + tw, top + th))
36
 
37
  def person_mask(img_512: Image.Image) -> Image.Image:
38
- """Return a binary mask (L mode) with person=255, background=0; black if no person."""
39
  results = seg_pipe(img_512)
40
- person = None
41
- for r in results:
42
- if r.get("label", "").lower() == "person":
43
- person = r; break
44
  if person is None:
45
- for r in results:
46
- if "person" in r.get("label", "").lower():
47
- person = r; break
48
  if person is None:
49
- return Image.new("L", img_512.size, 0)
50
  m = person["mask"].convert("L")
51
  m = (np.array(m) > 127).astype(np.uint8) * 255
52
  return Image.fromarray(m, mode="L")
53
 
54
  def gaussian_bg_blur(img_512: Image.Image, sigma: int = 15) -> Image.Image:
55
- """Blur only the background (person stays sharp)."""
56
  m = person_mask(img_512)
57
  blurred = img_512.filter(ImageFilter.GaussianBlur(radius=int(sigma)))
58
- return Image.composite(img_512, blurred, m)
59
 
60
  def depth_lens_blur(img_512: Image.Image, max_radius: int = 15, keep_subject: bool = True) -> Image.Image:
61
- """Apply per-pixel blur proportional to depth (farther = more blur)."""
62
  out = depth_pipe(img_512)
63
- d = out["depth"].resize(TARGET_SIZE, Image.BICUBIC)
64
  dnp = np.array(d).astype(np.float32)
65
- d01 = (dnp - dnp.min()) / (dnp.max() - dnp.min() + 1e-8) # 0..1 (brighter≈closer)
66
- far = 1.0 - d01 # larger = farther
67
  if keep_subject:
68
  m = person_mask(img_512)
69
  m01 = (np.array(m) > 127).astype(np.float32)
70
- far = far * (1.0 - 0.85 * m01) # suppress blur on subject
71
- # Build blurred pyramid and gather
72
  max_radius = int(max(0, min(30, max_radius)))
73
- radii = np.arange(max_radius + 1, dtype=np.int32)
74
  idx = np.clip(np.rint(far * max_radius).astype(np.int32), 0, max_radius)
75
- stack = []
76
- for r in radii:
77
- stack.append(img_512 if r == 0 else img_512.filter(ImageFilter.GaussianBlur(radius=int(r))))
78
  stack_np = np.stack([np.array(im) for im in stack], axis=0) # [R+1,H,W,3]
79
  H, W = idx.shape
80
- h = np.arange(H)[:, None]
81
- w = np.arange(W)[None, :]
82
  out_np = stack_np[idx, h, w]
83
  return Image.fromarray(out_np.astype(np.uint8))
84
 
85
- def run(image: Image.Image, effect: str, sigma: int, max_radius: int, keep_subject: bool):
86
  if image is None:
87
  return None, None
88
- img_512 = resize_center_crop(image, TARGET_SIZE)
89
  if effect == "Gaussian Background Blur (subject sharp)":
90
  out = gaussian_bg_blur(img_512, sigma=int(sigma))
91
  else:
92
- out = depth_lens_blur(img_512, max_radius=int(max_radius), keep_subject=keep_subject)
93
  return img_512, out
94
 
 
95
  with gr.Blocks(title="Gaussian & Lens Blur Lab") as demo:
96
  gr.Markdown("# Gaussian & Lens Blur Lab\nUpload an image and compare effects.")
97
  with gr.Row():
@@ -99,8 +82,7 @@ with gr.Blocks(title="Gaussian & Lens Blur Lab") as demo:
99
  in_img = gr.Image(type="pil", label="Upload image")
100
  effect = gr.Radio(
101
  ["Gaussian Background Blur (subject sharp)", "Depth-based Lens Blur"],
102
- value="Gaussian Background Blur (subject sharp)",
103
- label="Effect"
104
  )
105
  sigma = gr.Slider(1, 40, value=15, step=1, label="Gaussian sigma")
106
  max_r = gr.Slider(4, 30, value=15, step=1, label="Max blur radius (lens blur)")
 
 
1
  import os
2
+ os.environ["TRANSFORMERS_NO_TF"] = "1" # force PyTorch-only pipelines
 
3
 
4
  import numpy as np
5
  from PIL import Image, ImageFilter
6
  import gradio as gr
 
 
7
  import torch
8
  from transformers import pipeline
9
 
10
+ # ---- Config ----
11
  DEVICE = 0 if torch.cuda.is_available() else -1
12
+ SEG_MODEL = "nvidia/segformer-b0-finetuned-ade-512-512"
13
+ DEPTH_MODEL = "Intel/dpt-hybrid-midas"
14
+ SIZE = (512, 512)
15
 
16
+ # ---- Pipelines (loaded once) ----
17
+ seg_pipe = pipeline("image-segmentation", model=SEG_MODEL, device=DEVICE, framework="pt")
18
+ depth_pipe = pipeline("depth-estimation", model=DEPTH_MODEL, device=DEVICE, framework="pt")
 
 
 
 
 
19
 
20
+ # ---- Helpers ----
21
+ def resize_center_crop(img: Image.Image, size=SIZE) -> Image.Image:
22
  img = img.convert("RGB")
23
  w, h = img.size
24
  tw, th = size
25
+ s = max(tw / w, th / h)
26
+ nw, nh = int(round(w * s)), int(round(h * s))
27
  img = img.resize((nw, nh), Image.BICUBIC)
28
  left, top = (nw - tw) // 2, (nh - th) // 2
29
  return img.crop((left, top, left + tw, top + th))
30
 
31
  def person_mask(img_512: Image.Image) -> Image.Image:
 
32
  results = seg_pipe(img_512)
33
+ person = next((r for r in results if r.get("label", "").lower() == "person"), None)
 
 
 
34
  if person is None:
35
+ person = next((r for r in results if "person" in r.get("label", "").lower()), None)
 
 
36
  if person is None:
37
+ return Image.new("L", img_512.size, 0) # no person detected
38
  m = person["mask"].convert("L")
39
  m = (np.array(m) > 127).astype(np.uint8) * 255
40
  return Image.fromarray(m, mode="L")
41
 
42
  def gaussian_bg_blur(img_512: Image.Image, sigma: int = 15) -> Image.Image:
 
43
  m = person_mask(img_512)
44
  blurred = img_512.filter(ImageFilter.GaussianBlur(radius=int(sigma)))
45
+ return Image.composite(img_512, blurred, m) # white=person -> keep sharp
46
 
47
  def depth_lens_blur(img_512: Image.Image, max_radius: int = 15, keep_subject: bool = True) -> Image.Image:
 
48
  out = depth_pipe(img_512)
49
+ d = out["depth"].resize(SIZE, Image.BICUBIC)
50
  dnp = np.array(d).astype(np.float32)
51
+ d01 = (dnp - dnp.min()) / (dnp.max() - dnp.min() + 1e-8) # 0..1
52
+ far = 1.0 - d01 # larger=farther -> more blur
53
  if keep_subject:
54
  m = person_mask(img_512)
55
  m01 = (np.array(m) > 127).astype(np.float32)
56
+ far = far * (1.0 - 0.85 * m01) # suppress blur on detected subject
 
57
  max_radius = int(max(0, min(30, max_radius)))
 
58
  idx = np.clip(np.rint(far * max_radius).astype(np.int32), 0, max_radius)
59
+ stack = [img_512 if r == 0 else img_512.filter(ImageFilter.GaussianBlur(radius=r))
60
+ for r in range(max_radius + 1)]
 
61
  stack_np = np.stack([np.array(im) for im in stack], axis=0) # [R+1,H,W,3]
62
  H, W = idx.shape
63
+ h = np.arange(H)[:, None]; w = np.arange(W)[None, :]
 
64
  out_np = stack_np[idx, h, w]
65
  return Image.fromarray(out_np.astype(np.uint8))
66
 
67
+ def run(image, effect, sigma, max_radius, keep_subject):
68
  if image is None:
69
  return None, None
70
+ img_512 = resize_center_crop(image, SIZE)
71
  if effect == "Gaussian Background Blur (subject sharp)":
72
  out = gaussian_bg_blur(img_512, sigma=int(sigma))
73
  else:
74
+ out = depth_lens_blur(img_512, max_radius=int(max_radius), keep_subject=bool(keep_subject))
75
  return img_512, out
76
 
77
+ # ---- UI ----
78
  with gr.Blocks(title="Gaussian & Lens Blur Lab") as demo:
79
  gr.Markdown("# Gaussian & Lens Blur Lab\nUpload an image and compare effects.")
80
  with gr.Row():
 
82
  in_img = gr.Image(type="pil", label="Upload image")
83
  effect = gr.Radio(
84
  ["Gaussian Background Blur (subject sharp)", "Depth-based Lens Blur"],
85
+ value="Gaussian Background Blur (subject sharp)", label="Effect"
 
86
  )
87
  sigma = gr.Slider(1, 40, value=15, step=1, label="Gaussian sigma")
88
  max_r = gr.Slider(4, 30, value=15, step=1, label="Max blur radius (lens blur)")