Jeevan-HM commited on
Commit
ecb27c6
Β·
1 Parent(s): 313c477

Update to add synthetic blur

Browse files
Files changed (2) hide show
  1. .DS_Store +0 -0
  2. app.py +64 -40
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
app.py CHANGED
@@ -21,7 +21,6 @@ def gaussian_blur(img: Image.Image, kernel_size: int):
21
  return cv2.cvtColor(blurred, cv2.COLOR_BGR2RGB)
22
 
23
 
24
- # Load model once globally
25
  depth_model_id = "depth-anything/Depth-Anything-V2-Small-hf"
26
  processor = AutoImageProcessor.from_pretrained(depth_model_id)
27
  depth_model = AutoModelForDepthEstimation.from_pretrained(depth_model_id)
@@ -31,7 +30,6 @@ def lens_blur(img: Image.Image, max_blur_radius: int):
31
  img = resize_to_512(img)
32
  original = np.array(img).astype(np.float32)
33
 
34
- # Get depth map
35
  inputs = processor(images=img, return_tensors="pt")
36
  with torch.no_grad():
37
  outputs = depth_model(**inputs)
@@ -49,19 +47,14 @@ def lens_blur(img: Image.Image, max_blur_radius: int):
49
  .numpy()
50
  )
51
 
52
- # Normalize and invert depth
53
  depth_norm = (depth - depth.min()) / (depth.max() - depth.min())
54
  depth_inverted = 1.0 - depth_norm
55
 
56
- # Dynamically scale blur strength using the slider
57
- num_levels = 6 # More levels for smoother transitions
58
- max_sigma = (
59
- max_blur_radius / 2.0
60
- ) # Scale down to reasonable range (e.g. 0–25 β†’ 0–12.5 sigma)
61
  blur_levels = np.linspace(0, max_sigma, num_levels)
62
  blurred_images = [gaussian_filter(original, sigma=(s, s, 0)) for s in blur_levels]
63
 
64
- # Blend based on depth
65
  blurred_final = np.zeros_like(original, dtype=np.float32)
66
  depth_scaled = depth_inverted * (num_levels - 1)
67
  depth_int = np.floor(depth_scaled).astype(int)
@@ -80,56 +73,87 @@ def lens_blur(img: Image.Image, max_blur_radius: int):
80
  return np.clip(blurred_final, 0, 255).astype(np.uint8)
81
 
82
 
83
- # Separate update functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  def update_gaussian(img, kernel_size):
85
  return gaussian_blur(img, kernel_size)
86
 
87
 
88
- def update_lens(img, max_blur_radius):
89
- return lens_blur(img, max_blur_radius)
90
 
91
 
92
- def apply_blurs(img, kernel_size, max_blur_radius):
93
- g_blurred = gaussian_blur(img, kernel_size)
94
- l_blurred = lens_blur(img, max_blur_radius)
95
- return g_blurred, l_blurred
96
 
97
 
98
  with gr.Blocks() as demo:
99
- gr.Markdown("## πŸŒ€ Apply Gaussian and Depth-Based Lens Blur")
100
 
101
  with gr.Row():
102
  image_input = gr.Image(type="pil", label="Upload Image")
103
 
104
  with gr.Row():
105
- kernel_slider = gr.Slider(1, 49, step=2, value=11, label="Gaussian Kernel Size")
106
- lens_slider = gr.Slider(
107
- 1, 50, step=1, value=15, label="Max Lens Blur Intensity"
108
- )
109
 
110
  with gr.Row():
111
- gaussian_output = gr.Image(label="Gaussian Blurred Image")
112
- lens_output = gr.Image(label="Depth-Based Lens Blurred Image")
 
113
 
114
- # Trigger both when image changes
115
  image_input.change(
116
- fn=apply_blurs,
117
- inputs=[image_input, kernel_slider, lens_slider],
118
- outputs=[gaussian_output, lens_output],
119
- )
120
-
121
- # Trigger only gaussian blur
122
- kernel_slider.change(
123
- fn=update_gaussian,
124
- inputs=[image_input, kernel_slider],
125
- outputs=gaussian_output,
126
  )
127
 
128
- # Trigger only lens blur
129
- lens_slider.change(
130
- fn=update_lens,
131
- inputs=[image_input, lens_slider],
132
- outputs=lens_output,
133
- )
134
 
135
  demo.launch()
 
21
  return cv2.cvtColor(blurred, cv2.COLOR_BGR2RGB)
22
 
23
 
 
24
  depth_model_id = "depth-anything/Depth-Anything-V2-Small-hf"
25
  processor = AutoImageProcessor.from_pretrained(depth_model_id)
26
  depth_model = AutoModelForDepthEstimation.from_pretrained(depth_model_id)
 
30
  img = resize_to_512(img)
31
  original = np.array(img).astype(np.float32)
32
 
 
33
  inputs = processor(images=img, return_tensors="pt")
34
  with torch.no_grad():
35
  outputs = depth_model(**inputs)
 
47
  .numpy()
48
  )
49
 
 
50
  depth_norm = (depth - depth.min()) / (depth.max() - depth.min())
51
  depth_inverted = 1.0 - depth_norm
52
 
53
+ num_levels = 6
54
+ max_sigma = max_blur_radius / 2.0
 
 
 
55
  blur_levels = np.linspace(0, max_sigma, num_levels)
56
  blurred_images = [gaussian_filter(original, sigma=(s, s, 0)) for s in blur_levels]
57
 
 
58
  blurred_final = np.zeros_like(original, dtype=np.float32)
59
  depth_scaled = depth_inverted * (num_levels - 1)
60
  depth_int = np.floor(depth_scaled).astype(int)
 
73
  return np.clip(blurred_final, 0, 255).astype(np.uint8)
74
 
75
 
76
+ def synthetic_lens_blur(img: Image.Image, max_blur_radius: int):
77
+ img = resize_to_512(img)
78
+ original = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
79
+ original_rgb = cv2.cvtColor(original, cv2.COLOR_BGR2RGB)
80
+
81
+ depth_norm = np.zeros((original.shape[0], original.shape[1]), dtype=np.float32)
82
+ cv2.circle(depth_norm, (original.shape[1] // 2, original.shape[0] // 2), 100, 1, -1)
83
+ depth_norm = cv2.GaussianBlur(depth_norm, (21, 21), 0)
84
+
85
+ blurred_image = np.zeros_like(original_rgb)
86
+
87
+ for i in range(original.shape[0]):
88
+ for j in range(original.shape[1]):
89
+ blur_radius = int(depth_norm[i, j] * max_blur_radius)
90
+ if blur_radius % 2 == 0:
91
+ blur_radius += 1
92
+
93
+ x_min = max(j - blur_radius, 0)
94
+ x_max = min(j + blur_radius, original.shape[1])
95
+ y_min = max(i - blur_radius, 0)
96
+ y_max = min(i + blur_radius, original.shape[0])
97
+
98
+ roi = original_rgb[y_min:y_max, x_min:x_max]
99
+
100
+ if blur_radius > 1:
101
+ blurred_roi = cv2.GaussianBlur(roi, (blur_radius, blur_radius), 0)
102
+ try:
103
+ blurred_image[i, j] = blurred_roi[blur_radius // 2, blur_radius // 2]
104
+ except:
105
+ blurred_image[i, j] = original_rgb[i, j]
106
+ else:
107
+ blurred_image[i, j] = original_rgb[i, j]
108
+
109
+ return blurred_image
110
+
111
+
112
+ def apply_all_blurs(img, g_kernel, lens_radius, synthetic_radius):
113
+ g = gaussian_blur(img, g_kernel)
114
+ l = lens_blur(img, lens_radius)
115
+ s = synthetic_lens_blur(img, synthetic_radius)
116
+ return g, l, s
117
+
118
+
119
  def update_gaussian(img, kernel_size):
120
  return gaussian_blur(img, kernel_size)
121
 
122
 
123
+ def update_lens(img, radius):
124
+ return lens_blur(img, radius)
125
 
126
 
127
+ def update_synthetic(img, radius):
128
+ return synthetic_lens_blur(img, radius)
 
 
129
 
130
 
131
  with gr.Blocks() as demo:
132
+ gr.Markdown("## πŸŒ€ Blur Effects Comparison: Gaussian, Depth-Based, Synthetic")
133
 
134
  with gr.Row():
135
  image_input = gr.Image(type="pil", label="Upload Image")
136
 
137
  with gr.Row():
138
+ g_slider = gr.Slider(1, 49, step=2, value=11, label="Gaussian Kernel Size")
139
+ lens_slider = gr.Slider(1, 50, step=1, value=15, label="Depth-Based Blur Intensity")
140
+ synth_slider = gr.Slider(1, 50, step=1, value=25, label="Synthetic Blur Radius")
 
141
 
142
  with gr.Row():
143
+ g_output = gr.Image(label="Gaussian Blurred Image")
144
+ l_output = gr.Image(label="Depth-Based Lens Blurred Image")
145
+ s_output = gr.Image(label="Synthetic Depth Lens Blurred Image")
146
 
147
+ # Initial image upload updates all three
148
  image_input.change(
149
+ fn=apply_all_blurs,
150
+ inputs=[image_input, g_slider, lens_slider, synth_slider],
151
+ outputs=[g_output, l_output, s_output],
 
 
 
 
 
 
 
152
  )
153
 
154
+ # Individual updates for each slider
155
+ g_slider.change(fn=update_gaussian, inputs=[image_input, g_slider], outputs=g_output)
156
+ lens_slider.change(fn=update_lens, inputs=[image_input, lens_slider], outputs=l_output)
157
+ synth_slider.change(fn=update_synthetic, inputs=[image_input, synth_slider], outputs=s_output)
 
 
158
 
159
  demo.launch()