Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -41,7 +41,11 @@ def segment_image(image):
|
|
41 |
|
42 |
# Original dimensions
|
43 |
original_size = image.size
|
44 |
-
|
|
|
|
|
|
|
|
|
45 |
|
46 |
# Process image with model
|
47 |
inputs = seg_processor(images=model_image, return_tensors="pt")
|
@@ -64,29 +68,30 @@ def segment_image(image):
|
|
64 |
if cls_mask.sum() > binary_mask.sum():
|
65 |
binary_mask = cls_mask
|
66 |
|
67 |
-
#
|
68 |
-
|
69 |
-
|
|
|
70 |
kernel = np.ones((5, 5), np.uint8)
|
71 |
mask_cv = cv2.morphologyEx(mask_cv, cv2.MORPH_CLOSE, kernel)
|
72 |
mask_cv = cv2.morphologyEx(mask_cv, cv2.MORPH_OPEN, kernel)
|
73 |
|
74 |
-
# Apply Gaussian blur to smooth the edges
|
75 |
-
mask_cv = cv2.GaussianBlur(mask_cv, (
|
76 |
_, mask_cv = cv2.threshold(mask_cv, 128, 255, cv2.THRESH_BINARY)
|
77 |
|
78 |
-
# Resize back to original image size
|
79 |
-
|
80 |
-
|
81 |
|
82 |
-
#
|
83 |
-
mask_array = np.array(
|
84 |
|
85 |
-
# Create
|
86 |
-
|
87 |
-
|
88 |
|
89 |
-
return mask_array,
|
90 |
|
91 |
# Function to apply Gaussian blur to background
|
92 |
def apply_background_blur(image, mask, sigma=15):
|
@@ -106,9 +111,8 @@ def apply_background_blur(image, mask, sigma=15):
|
|
106 |
binary_mask = mask > 0
|
107 |
|
108 |
# Apply Gaussian blur to the entire image
|
109 |
-
|
110 |
-
|
111 |
-
blurred[:, :, c] = gaussian_filter(image_array[:, :, c], sigma=sigma)
|
112 |
|
113 |
# Combine original foreground with blurred background
|
114 |
result = np.copy(blurred)
|
@@ -128,7 +132,9 @@ def apply_depth_based_blur(image, mask=None, max_sigma=15):
|
|
128 |
|
129 |
# Original dimensions
|
130 |
original_size = image.size
|
131 |
-
|
|
|
|
|
132 |
model_image = image.resize(model_size, Image.LANCZOS)
|
133 |
|
134 |
# Process image for depth estimation
|
@@ -143,43 +149,56 @@ def apply_depth_based_blur(image, mask=None, max_sigma=15):
|
|
143 |
depth = predicted_depth.squeeze().cpu().numpy()
|
144 |
depth_map = (depth - depth.min()) / (depth.max() - depth.min())
|
145 |
|
146 |
-
#
|
147 |
-
|
148 |
-
depth_map_resized = np.array(depth_pil.resize(model_size, Image.LANCZOS))
|
149 |
|
150 |
# Invert depth map (closer objects should be less blurred)
|
151 |
-
inverted_depth_map = 1.0 -
|
152 |
|
153 |
# If mask is provided, ensure foreground is not blurred at all
|
154 |
if mask is not None:
|
155 |
# Resize mask to match model size
|
156 |
-
mask_pil = Image.fromarray((mask
|
157 |
mask_resized = np.array(mask_pil.resize(model_size, Image.LANCZOS)) > 128
|
158 |
# Set depth map to 0 (no blur) for foreground pixels
|
159 |
inverted_depth_map = inverted_depth_map * (1 - mask_resized)
|
160 |
|
161 |
-
#
|
162 |
-
|
163 |
-
result_array = np.zeros_like(original_array)
|
164 |
|
165 |
-
#
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
|
173 |
-
#
|
174 |
-
|
175 |
-
|
176 |
|
177 |
# Create colored depth map for visualization
|
178 |
depth_map_colored = plt.cm.viridis(depth_map)[:, :, :3]
|
179 |
depth_map_viz = Image.fromarray((depth_map_colored * 255).astype(np.uint8))
|
180 |
-
|
181 |
|
182 |
-
return np.array(
|
183 |
|
184 |
# Main processing function
|
185 |
def process_image(input_image, blur_type="Gaussian Blur", blur_intensity=15):
|
@@ -207,7 +226,11 @@ def process_image(input_image, blur_type="Gaussian Blur", blur_intensity=15):
|
|
207 |
if blur_type == "Gaussian Blur":
|
208 |
# Apply regular Gaussian blur
|
209 |
result = apply_background_blur(pil_img, mask_array, sigma=blur_intensity)
|
210 |
-
|
|
|
|
|
|
|
|
|
211 |
|
212 |
else: # "Depth-based Lens Blur"
|
213 |
# Apply depth-based blur
|
|
|
41 |
|
42 |
# Original dimensions
|
43 |
original_size = image.size
|
44 |
+
|
45 |
+
# Use higher resolution for better results while staying within model limits
|
46 |
+
# Most models work well with 640x640
|
47 |
+
model_size = (640, 640)
|
48 |
+
model_image = image.resize(model_size, Image.LANCZOS)
|
49 |
|
50 |
# Process image with model
|
51 |
inputs = seg_processor(images=model_image, return_tensors="pt")
|
|
|
68 |
if cls_mask.sum() > binary_mask.sum():
|
69 |
binary_mask = cls_mask
|
70 |
|
71 |
+
# Convert to uint8 for OpenCV processing
|
72 |
+
mask_cv = (binary_mask * 255).astype(np.uint8)
|
73 |
+
|
74 |
+
# Apply morphological operations to clean up the mask
|
75 |
kernel = np.ones((5, 5), np.uint8)
|
76 |
mask_cv = cv2.morphologyEx(mask_cv, cv2.MORPH_CLOSE, kernel)
|
77 |
mask_cv = cv2.morphologyEx(mask_cv, cv2.MORPH_OPEN, kernel)
|
78 |
|
79 |
+
# Apply Gaussian blur to smooth the edges - less aggressive
|
80 |
+
mask_cv = cv2.GaussianBlur(mask_cv, (7, 7), 0)
|
81 |
_, mask_cv = cv2.threshold(mask_cv, 128, 255, cv2.THRESH_BINARY)
|
82 |
|
83 |
+
# Resize back to original image size using bicubic interpolation for smoother results
|
84 |
+
mask_pil = Image.fromarray(mask_cv)
|
85 |
+
mask_resized = mask_pil.resize(original_size, Image.LANCZOS)
|
86 |
|
87 |
+
# Convert back to numpy
|
88 |
+
mask_array = np.array(mask_resized) > 128
|
89 |
|
90 |
+
# Create visualization of mask (red on black background)
|
91 |
+
mask_viz = np.zeros((mask_array.shape[0], mask_array.shape[1], 3), dtype=np.uint8)
|
92 |
+
mask_viz[:,:,0] = mask_array * 255 # Red channel
|
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):
|
|
|
111 |
binary_mask = mask > 0
|
112 |
|
113 |
# Apply Gaussian blur to the entire image
|
114 |
+
# Use OpenCV for better performance on larger images
|
115 |
+
blurred = cv2.GaussianBlur(image_array, (0, 0), sigma)
|
|
|
116 |
|
117 |
# Combine original foreground with blurred background
|
118 |
result = np.copy(blurred)
|
|
|
132 |
|
133 |
# Original dimensions
|
134 |
original_size = image.size
|
135 |
+
|
136 |
+
# Higher resolution for depth estimation
|
137 |
+
model_size = (640, 640)
|
138 |
model_image = image.resize(model_size, Image.LANCZOS)
|
139 |
|
140 |
# Process image for depth estimation
|
|
|
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 - depth_map_highres
|
157 |
|
158 |
# If mask is provided, ensure foreground is not blurred at all
|
159 |
if mask is not None:
|
160 |
# Resize mask to match model size
|
161 |
+
mask_pil = Image.fromarray((mask.astype(np.uint8) * 255))
|
162 |
mask_resized = np.array(mask_pil.resize(model_size, Image.LANCZOS)) > 128
|
163 |
# Set depth map to 0 (no blur) for foreground pixels
|
164 |
inverted_depth_map = inverted_depth_map * (1 - mask_resized)
|
165 |
|
166 |
+
# Convert to numpy array for processing
|
167 |
+
img_array = np.array(model_image)
|
|
|
168 |
|
169 |
+
# Create a progressive blur effect with multiple levels
|
170 |
+
result = np.copy(img_array)
|
171 |
+
|
172 |
+
# Apply multiple blur levels for smoother transitions
|
173 |
+
num_levels = 8
|
174 |
+
for i in range(num_levels):
|
175 |
+
# Calculate blur sigma for this level
|
176 |
+
level_sigma = max_sigma * (i + 1) / num_levels
|
177 |
+
|
178 |
+
# Create a blurred version of the image at this sigma level
|
179 |
+
level_blurred = cv2.GaussianBlur(img_array, (0, 0), level_sigma)
|
180 |
+
|
181 |
+
# Calculate where to apply this blur level
|
182 |
+
depth_min = i / num_levels
|
183 |
+
depth_max = (i + 1) / num_levels
|
184 |
+
|
185 |
+
# Create a mask for this depth range
|
186 |
+
level_mask = (inverted_depth_map >= depth_min) & (inverted_depth_map < depth_max)
|
187 |
+
|
188 |
+
# Apply this blur level
|
189 |
+
for c in range(3):
|
190 |
+
result[:,:,c] = np.where(level_mask, level_blurred[:,:,c], result[:,:,c])
|
191 |
|
192 |
+
# Convert result back to PIL and resize to original dimensions
|
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):
|
|
|
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
|