TIMBOVILL commited on
Commit
0e61409
·
verified ·
1 Parent(s): 6bdc2eb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -38
app.py CHANGED
@@ -2,59 +2,56 @@ import gradio as gr
2
  from PIL import Image
3
  import numpy as np
4
 
5
- def brightness_to_opacity_overlay(foreground_img, background_img, invert_opacity=False):
6
- if foreground_img is None or background_img is None:
7
  return None
8
 
9
- # Ensure images are RGBA and same size
10
- bg = background_img.convert("RGBA")
11
- fg = foreground_img.convert("RGB").resize(bg.size)
12
 
13
- # Convert to luminance (brightness)
14
- fg_np = np.array(fg)
15
- brightness = np.dot(fg_np[..., :3], [0.299, 0.587, 0.114]).astype(np.uint8)
16
 
17
- # Optionally invert
18
- alpha = 255 - brightness if invert_opacity else brightness
 
 
 
 
19
 
20
- # Create white RGBA with computed alpha
21
- white_rgb = np.full_like(fg_np, 255)
22
- overlay_rgba = np.dstack((white_rgb, alpha)).astype(np.uint8)
23
- overlay = Image.fromarray(overlay_rgba, mode="RGBA")
24
 
25
- # Use the alpha from overlay as a mask on the background
26
- bg_np = np.array(bg).astype(np.float32)
27
- ov_np = np.array(overlay).astype(np.float32)
28
 
29
- alpha_fg = ov_np[..., 3:4] / 255.0
30
- alpha_bg = bg_np[..., 3:4] / 255.0
 
 
 
31
 
32
- # Blend RGB
33
- out_rgb = (ov_np[..., :3] * alpha_fg + bg_np[..., :3] * alpha_bg * (1 - alpha_fg))
34
- out_alpha = alpha_fg + alpha_bg * (1 - alpha_fg)
35
-
36
- # Avoid divide-by-zero
37
- out_rgb = np.divide(out_rgb, out_alpha, where=(out_alpha != 0))
38
-
39
- # Combine back to RGBA
40
- out_rgba = np.dstack((out_rgb, out_alpha)) * 255
41
- result = Image.fromarray(out_rgba.astype(np.uint8), mode="RGBA")
42
-
43
- return result
44
 
45
  # Gradio UI
46
  iface = gr.Interface(
47
  fn=brightness_to_opacity_overlay,
48
  inputs=[
49
- gr.Image(type="pil", label="Mask Source (Brightness to Alpha)"),
50
- gr.Image(type="pil", label="Background Image (with transparency OK)"),
51
- gr.Checkbox(label="Invert Opacity", value=False)
52
  ],
53
- outputs=gr.Image(type="pil", label="Composite Result"),
54
- title="Brightness-to-Alpha Overlay (Transparent-Safe)",
55
  description=(
56
- "Uses the brightness of one image as an alpha mask and overlays it "
57
- "on a background image works properly even when background has transparency."
58
  )
59
  )
60
 
 
2
  from PIL import Image
3
  import numpy as np
4
 
5
+ def brightness_to_opacity_overlay(fg_img, bg_img, invert_opacity=False):
6
+ if fg_img is None or bg_img is None:
7
  return None
8
 
9
+ # Convert images
10
+ fg = fg_img.convert("RGB")
11
+ bg = bg_img.convert("RGBA")
12
 
13
+ # Resize fg to match bg
14
+ fg = fg.resize(bg.size)
 
15
 
16
+ # Convert to brightness
17
+ fg_np = np.array(fg).astype(np.float32)
18
+ luminance = np.dot(fg_np[..., :3], [0.299, 0.587, 0.114])
19
+ if invert_opacity:
20
+ luminance = 255 - luminance
21
+ alpha = (luminance / 255.0).clip(0, 1)
22
 
23
+ # Make white RGB with computed alpha
24
+ overlay_rgb = np.ones_like(fg_np) * 255
25
+ overlay_rgba = np.dstack((overlay_rgb, alpha * 255)).astype(np.uint8)
 
26
 
27
+ # Convert both to float for blending
28
+ overlay = overlay_rgba.astype(np.float32) / 255.0
29
+ bg_np = np.array(bg).astype(np.float32) / 255.0
30
 
31
+ # Premultiplied alpha blend
32
+ fg_a = overlay[..., 3:4]
33
+ bg_a = bg_np[..., 3:4]
34
+ out_a = fg_a + bg_a * (1 - fg_a)
35
+ out_rgb = (overlay[..., :3] * fg_a + bg_np[..., :3] * bg_a * (1 - fg_a)) / np.maximum(out_a, 1e-6)
36
 
37
+ # Final image
38
+ result_np = np.dstack((out_rgb, out_a)).clip(0, 1) * 255
39
+ result_img = Image.fromarray(result_np.astype(np.uint8), mode="RGBA")
40
+ return result_img
 
 
 
 
 
 
 
 
41
 
42
  # Gradio UI
43
  iface = gr.Interface(
44
  fn=brightness_to_opacity_overlay,
45
  inputs=[
46
+ gr.Image(type="pil", label="Alpha From Brightness (Foreground)"),
47
+ gr.Image(type="pil", label="Background Image (May Have Transparency)"),
48
+ gr.Checkbox(label="Invert Brightness", value=False)
49
  ],
50
+ outputs=gr.Image(type="pil", label="Composite Output"),
51
+ title="⚡ Accurate Brightness-to-Alpha Overlay",
52
  description=(
53
+ "This tool uses brightness as alpha, resizes to match background, "
54
+ "and blends correctly — even with transparent backgrounds."
55
  )
56
  )
57