Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -93,6 +93,42 @@ def segment_image(image):
|
|
93 |
|
94 |
return mask_array, mask_viz
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
# Function to apply Gaussian blur to background
|
97 |
def apply_background_blur(image, mask, sigma=15):
|
98 |
"""Apply Gaussian blur to background while keeping foreground sharp"""
|
@@ -121,10 +157,10 @@ def apply_background_blur(image, mask, sigma=15):
|
|
121 |
|
122 |
return result
|
123 |
|
124 |
-
# Function for depth
|
125 |
-
def apply_depth_based_blur(image, mask
|
126 |
-
"""Apply depth-based blur using
|
127 |
-
print(f"
|
128 |
|
129 |
# Convert to PIL Image if needed
|
130 |
if not isinstance(image, Image.Image):
|
@@ -133,38 +169,32 @@ def apply_depth_based_blur(image, mask=None, max_sigma=15):
|
|
133 |
# Original dimensions
|
134 |
original_size = image.size
|
135 |
|
136 |
-
#
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
inputs = depth_processor(images=model_image, return_tensors="pt")
|
142 |
-
|
143 |
-
# Run inference
|
144 |
-
with torch.no_grad():
|
145 |
-
outputs = depth_model(**inputs)
|
146 |
-
predicted_depth = outputs.predicted_depth
|
147 |
-
|
148 |
-
# Process depth map
|
149 |
-
depth = predicted_depth.squeeze().cpu().numpy()
|
150 |
-
depth_map = (depth - depth.min()) / (depth.max() - depth.min())
|
151 |
-
|
152 |
-
# Create high-res depth map
|
153 |
-
depth_map_highres = cv2.resize(depth_map, (model_size[0], model_size[1]), interpolation=cv2.INTER_CUBIC)
|
154 |
|
155 |
# Invert depth map (closer objects should be less blurred)
|
156 |
-
inverted_depth_map = 1.0 -
|
157 |
|
158 |
-
#
|
159 |
if mask is not None:
|
160 |
-
#
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
# Set depth map to 0 (no blur) for foreground pixels
|
164 |
-
inverted_depth_map = inverted_depth_map * (1 -
|
165 |
|
166 |
# Convert to numpy array for processing
|
167 |
-
img_array = np.array(
|
168 |
|
169 |
# Create a progressive blur effect with multiple levels
|
170 |
result = np.copy(img_array)
|
@@ -189,16 +219,7 @@ def apply_depth_based_blur(image, mask=None, max_sigma=15):
|
|
189 |
for c in range(3):
|
190 |
result[:,:,c] = np.where(level_mask, level_blurred[:,:,c], result[:,:,c])
|
191 |
|
192 |
-
|
193 |
-
result_pil = Image.fromarray(result.astype(np.uint8))
|
194 |
-
result_resized = result_pil.resize(original_size, Image.LANCZOS)
|
195 |
-
|
196 |
-
# Create colored depth map for visualization
|
197 |
-
depth_map_colored = plt.cm.viridis(depth_map)[:, :, :3]
|
198 |
-
depth_map_viz = Image.fromarray((depth_map_colored * 255).astype(np.uint8))
|
199 |
-
depth_map_viz_resized = depth_map_viz.resize(original_size, Image.LANCZOS)
|
200 |
-
|
201 |
-
return np.array(depth_map_viz_resized), np.array(result_resized)
|
202 |
|
203 |
# Main processing function
|
204 |
def process_image(input_image, blur_type="Gaussian Blur", blur_intensity=15):
|
@@ -222,19 +243,16 @@ def process_image(input_image, blur_type="Gaussian Blur", blur_intensity=15):
|
|
222 |
# Step 1: Get segmentation mask
|
223 |
mask_array, mask_viz = segment_image(pil_img)
|
224 |
|
225 |
-
# Step 2:
|
|
|
|
|
|
|
226 |
if blur_type == "Gaussian Blur":
|
227 |
# Apply regular Gaussian blur
|
228 |
result = apply_background_blur(pil_img, mask_array, sigma=blur_intensity)
|
229 |
-
# Create placeholder for depth map (black image)
|
230 |
-
depth_viz = np.zeros_like(img)
|
231 |
-
# Add text saying "Depth map not used for Gaussian blur"
|
232 |
-
font = cv2.FONT_HERSHEY_SIMPLEX
|
233 |
-
cv2.putText(depth_viz, "Depth map not used", (50, 50), font, 1, (255, 255, 255), 2)
|
234 |
-
|
235 |
else: # "Depth-based Lens Blur"
|
236 |
# Apply depth-based blur
|
237 |
-
|
238 |
|
239 |
return result, mask_viz, depth_viz
|
240 |
|
@@ -296,8 +314,9 @@ with gr.Blocks(title="Image Blur Effects") as demo:
|
|
296 |
gr.Markdown("")
|
297 |
gr.Markdown("### Notes")
|
298 |
gr.Markdown("- The red areas in the Foreground Mask show what will remain sharp")
|
299 |
-
gr.Markdown("- Depth
|
300 |
-
gr.Markdown("-
|
|
|
301 |
gr.Markdown("- Created for EEE 515 Assignment (Problem 2, Part 6)")
|
302 |
|
303 |
# Launch the demo
|
|
|
93 |
|
94 |
return mask_array, mask_viz
|
95 |
|
96 |
+
# Function to get depth map
|
97 |
+
def get_depth_map(image):
|
98 |
+
"""Get depth map from image using DPT model"""
|
99 |
+
print("Running depth estimation...")
|
100 |
+
|
101 |
+
# Convert to PIL Image if needed
|
102 |
+
if not isinstance(image, Image.Image):
|
103 |
+
image = Image.fromarray(image)
|
104 |
+
|
105 |
+
# Original dimensions
|
106 |
+
original_size = image.size
|
107 |
+
|
108 |
+
# Higher resolution for depth estimation
|
109 |
+
model_size = (640, 640)
|
110 |
+
model_image = image.resize(model_size, Image.LANCZOS)
|
111 |
+
|
112 |
+
# Process image for depth estimation
|
113 |
+
inputs = depth_processor(images=model_image, return_tensors="pt")
|
114 |
+
|
115 |
+
# Run inference
|
116 |
+
with torch.no_grad():
|
117 |
+
outputs = depth_model(**inputs)
|
118 |
+
predicted_depth = outputs.predicted_depth
|
119 |
+
|
120 |
+
# Process depth map
|
121 |
+
depth = predicted_depth.squeeze().cpu().numpy()
|
122 |
+
depth_map = (depth - depth.min()) / (depth.max() - depth.min())
|
123 |
+
|
124 |
+
# Create colored depth map for visualization
|
125 |
+
depth_map_colored = plt.cm.viridis(depth_map)[:, :, :3]
|
126 |
+
depth_map_viz = Image.fromarray((depth_map_colored * 255).astype(np.uint8))
|
127 |
+
depth_map_viz_resized = depth_map_viz.resize(original_size, Image.LANCZOS)
|
128 |
+
|
129 |
+
# Return both visualization and raw depth map
|
130 |
+
return np.array(depth_map_viz_resized), depth_map
|
131 |
+
|
132 |
# Function to apply Gaussian blur to background
|
133 |
def apply_background_blur(image, mask, sigma=15):
|
134 |
"""Apply Gaussian blur to background while keeping foreground sharp"""
|
|
|
157 |
|
158 |
return result
|
159 |
|
160 |
+
# Function for depth-based blur
|
161 |
+
def apply_depth_based_blur(image, mask, depth_map, max_sigma=15):
|
162 |
+
"""Apply depth-based blur using provided depth map"""
|
163 |
+
print(f"Applying depth-based blur with max_sigma={max_sigma}...")
|
164 |
|
165 |
# Convert to PIL Image if needed
|
166 |
if not isinstance(image, Image.Image):
|
|
|
169 |
# Original dimensions
|
170 |
original_size = image.size
|
171 |
|
172 |
+
# Resize depth map to match image size if needed
|
173 |
+
if depth_map.shape[:2] != image.size[::-1]:
|
174 |
+
depth_map_resized = cv2.resize(depth_map, original_size, interpolation=cv2.INTER_CUBIC)
|
175 |
+
else:
|
176 |
+
depth_map_resized = depth_map
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
|
178 |
# Invert depth map (closer objects should be less blurred)
|
179 |
+
inverted_depth_map = 1.0 - depth_map_resized
|
180 |
|
181 |
+
# Apply mask to ensure foreground is not blurred
|
182 |
if mask is not None:
|
183 |
+
# Ensure mask has proper dimensions
|
184 |
+
if isinstance(mask, np.ndarray):
|
185 |
+
if mask.ndim == 3:
|
186 |
+
binary_mask = mask[:,:,0] > 0
|
187 |
+
else:
|
188 |
+
binary_mask = mask > 0
|
189 |
+
else:
|
190 |
+
# Convert to numpy if needed
|
191 |
+
binary_mask = np.array(mask) > 0
|
192 |
+
|
193 |
# Set depth map to 0 (no blur) for foreground pixels
|
194 |
+
inverted_depth_map = inverted_depth_map * (1 - binary_mask)
|
195 |
|
196 |
# Convert to numpy array for processing
|
197 |
+
img_array = np.array(image)
|
198 |
|
199 |
# Create a progressive blur effect with multiple levels
|
200 |
result = np.copy(img_array)
|
|
|
219 |
for c in range(3):
|
220 |
result[:,:,c] = np.where(level_mask, level_blurred[:,:,c], result[:,:,c])
|
221 |
|
222 |
+
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
# Main processing function
|
225 |
def process_image(input_image, blur_type="Gaussian Blur", blur_intensity=15):
|
|
|
243 |
# Step 1: Get segmentation mask
|
244 |
mask_array, mask_viz = segment_image(pil_img)
|
245 |
|
246 |
+
# Step 2: Always get depth map (for both blur types)
|
247 |
+
depth_viz, depth_map = get_depth_map(pil_img)
|
248 |
+
|
249 |
+
# Step 3: Apply appropriate blur effect
|
250 |
if blur_type == "Gaussian Blur":
|
251 |
# Apply regular Gaussian blur
|
252 |
result = apply_background_blur(pil_img, mask_array, sigma=blur_intensity)
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
else: # "Depth-based Lens Blur"
|
254 |
# Apply depth-based blur
|
255 |
+
result = apply_depth_based_blur(pil_img, mask_array, depth_map, max_sigma=blur_intensity)
|
256 |
|
257 |
return result, mask_viz, depth_viz
|
258 |
|
|
|
314 |
gr.Markdown("")
|
315 |
gr.Markdown("### Notes")
|
316 |
gr.Markdown("- The red areas in the Foreground Mask show what will remain sharp")
|
317 |
+
gr.Markdown("- The Depth Map shows estimated distances (yellow=far, blue=close)")
|
318 |
+
gr.Markdown("- Gaussian Blur applies uniform blur to the background")
|
319 |
+
gr.Markdown("- Depth-based Blur varies blur intensity based on distance")
|
320 |
gr.Markdown("- Created for EEE 515 Assignment (Problem 2, Part 6)")
|
321 |
|
322 |
# Launch the demo
|