Spaces:
Sleeping
Sleeping
fixed errors
Browse files
app.py
CHANGED
@@ -77,87 +77,184 @@ def apply_gaussian_blur_to_background(image_np, mask, sigma=15):
|
|
77 |
return result
|
78 |
|
79 |
# Normalize depth map
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
def normalize_depth_map(depth_map):
|
|
|
81 |
depth_min = depth_map.min()
|
82 |
depth_max = depth_map.max()
|
|
|
|
|
83 |
normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)
|
84 |
return normalized_depth
|
85 |
|
86 |
# Apply depth-based blur
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
def apply_depth_based_blur(image, depth_map, max_blur=25):
|
|
|
88 |
# Create output image
|
89 |
result = np.zeros_like(image)
|
90 |
|
|
|
|
|
|
|
91 |
# Apply blur with intensity proportional to depth
|
92 |
for blur_size in range(1, max_blur + 1, 2): # Odd numbers for kernel size
|
93 |
# Create a mask for pixels that should receive this blur level
|
94 |
if blur_size == 1:
|
95 |
-
mask = (
|
96 |
else:
|
97 |
lower_bound = (blur_size - 2) / max_blur
|
98 |
upper_bound = blur_size / max_blur
|
99 |
-
mask = ((
|
100 |
|
101 |
# Skip if no pixels in this range
|
102 |
if not np.any(mask):
|
103 |
continue
|
104 |
|
105 |
# Apply Gaussian blur with current kernel size
|
106 |
-
if blur_size > 1:
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
110 |
else:
|
|
|
111 |
mask_3d = np.stack([mask] * 3, axis=2)
|
112 |
result += (image * mask_3d).astype(np.uint8)
|
113 |
|
114 |
return result
|
115 |
|
116 |
# Process function for Gradio
|
117 |
-
def process_image(input_image, blur_effect_type, blur_strength, target_class):
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
|
123 |
-
|
124 |
-
|
125 |
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
|
131 |
-
|
132 |
-
|
133 |
|
134 |
-
|
135 |
-
|
136 |
|
137 |
-
|
138 |
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
|
147 |
-
|
148 |
-
|
149 |
|
150 |
-
|
151 |
-
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
|
157 |
-
|
158 |
|
159 |
-
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
|
162 |
# Create Gradio interface
|
163 |
demo = gr.Blocks(title="Image Blur Effects")
|
@@ -198,6 +295,8 @@ with demo:
|
|
198 |
outputs=output_image
|
199 |
)
|
200 |
|
|
|
|
|
201 |
gr.Markdown("""
|
202 |
## How to use:
|
203 |
1. Upload an image with a clear foreground subject
|
@@ -213,4 +312,4 @@ with demo:
|
|
213 |
segmenter, depth_estimator = load_models()
|
214 |
|
215 |
# Launch the app
|
216 |
-
demo.launch()
|
|
|
77 |
return result
|
78 |
|
79 |
# Normalize depth map
|
80 |
+
# def normalize_depth_map(depth_map):
|
81 |
+
# depth_min = depth_map.min()
|
82 |
+
# depth_max = depth_map.max()
|
83 |
+
# normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)
|
84 |
+
# return normalized_depth
|
85 |
+
|
86 |
def normalize_depth_map(depth_map):
|
87 |
+
"""Normalize depth map to range [0, 1]"""
|
88 |
depth_min = depth_map.min()
|
89 |
depth_max = depth_map.max()
|
90 |
+
if depth_min == depth_max:
|
91 |
+
return np.zeros_like(depth_map) # Handle uniform depth
|
92 |
normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)
|
93 |
return normalized_depth
|
94 |
|
95 |
# Apply depth-based blur
|
96 |
+
# def apply_depth_based_blur(image, depth_map, max_blur=25):
|
97 |
+
# # Create output image
|
98 |
+
# result = np.zeros_like(image)
|
99 |
+
|
100 |
+
# # Apply blur with intensity proportional to depth
|
101 |
+
# for blur_size in range(1, max_blur + 1, 2): # Odd numbers for kernel size
|
102 |
+
# # Create a mask for pixels that should receive this blur level
|
103 |
+
# if blur_size == 1:
|
104 |
+
# mask = (depth_map <= blur_size / max_blur).astype(np.float32)
|
105 |
+
# else:
|
106 |
+
# lower_bound = (blur_size - 2) / max_blur
|
107 |
+
# upper_bound = blur_size / max_blur
|
108 |
+
# mask = ((depth_map > lower_bound) & (depth_map <= upper_bound)).astype(np.float32)
|
109 |
+
|
110 |
+
# # Skip if no pixels in this range
|
111 |
+
# if not np.any(mask):
|
112 |
+
# continue
|
113 |
+
|
114 |
+
# # Apply Gaussian blur with current kernel size
|
115 |
+
# if blur_size > 1:
|
116 |
+
# blurred = cv2.GaussianBlur(image, (blur_size, blur_size), 0)
|
117 |
+
# mask_3d = np.stack([mask] * 3, axis=2)
|
118 |
+
# result += (blurred * mask_3d).astype(np.uint8)
|
119 |
+
# else:
|
120 |
+
# mask_3d = np.stack([mask] * 3, axis=2)
|
121 |
+
# result += (image * mask_3d).astype(np.uint8)
|
122 |
+
|
123 |
+
# return result
|
124 |
+
|
125 |
def apply_depth_based_blur(image, depth_map, max_blur=25):
|
126 |
+
"""Apply variable Gaussian blur based on depth"""
|
127 |
# Create output image
|
128 |
result = np.zeros_like(image)
|
129 |
|
130 |
+
# Normalize depth map
|
131 |
+
normalized_depth = normalize_depth_map(depth_map)
|
132 |
+
|
133 |
# Apply blur with intensity proportional to depth
|
134 |
for blur_size in range(1, max_blur + 1, 2): # Odd numbers for kernel size
|
135 |
# Create a mask for pixels that should receive this blur level
|
136 |
if blur_size == 1:
|
137 |
+
mask = (normalized_depth <= blur_size / max_blur).astype(np.float32)
|
138 |
else:
|
139 |
lower_bound = (blur_size - 2) / max_blur
|
140 |
upper_bound = blur_size / max_blur
|
141 |
+
mask = ((normalized_depth > lower_bound) & (normalized_depth <= upper_bound)).astype(np.float32)
|
142 |
|
143 |
# Skip if no pixels in this range
|
144 |
if not np.any(mask):
|
145 |
continue
|
146 |
|
147 |
# Apply Gaussian blur with current kernel size
|
148 |
+
if blur_size > 1: # No need to blur with kernel size 1
|
149 |
+
try:
|
150 |
+
blurred = cv2.GaussianBlur(image, (blur_size, blur_size), 0)
|
151 |
+
# Add blurred result to output image
|
152 |
+
mask_3d = np.stack([mask] * 3, axis=2)
|
153 |
+
result += (blurred * mask_3d).astype(np.uint8)
|
154 |
+
except Exception as e:
|
155 |
+
print(f"Error applying blur with size {blur_size}: {e}")
|
156 |
+
continue
|
157 |
else:
|
158 |
+
# For blur_size=1, just copy the original pixels
|
159 |
mask_3d = np.stack([mask] * 3, axis=2)
|
160 |
result += (image * mask_3d).astype(np.uint8)
|
161 |
|
162 |
return result
|
163 |
|
164 |
# Process function for Gradio
|
165 |
+
# def process_image(input_image, blur_effect_type, blur_strength, target_class):
|
166 |
+
# # Load models if not already loaded
|
167 |
+
# if not hasattr(process_image, "models_loaded"):
|
168 |
+
# process_image.segmenter, process_image.depth_estimator = load_models()
|
169 |
+
# process_image.models_loaded = True
|
170 |
|
171 |
+
# # Convert to numpy array
|
172 |
+
# image_np = np.array(input_image)
|
173 |
|
174 |
+
# # Process based on selected effect
|
175 |
+
# if blur_effect_type == "Gaussian Background Blur":
|
176 |
+
# # Segment the image
|
177 |
+
# segmentation_results = process_image.segmenter(input_image)
|
178 |
|
179 |
+
# # Create binary mask
|
180 |
+
# binary_mask = create_binary_mask(segmentation_results, image_np, target_class)
|
181 |
|
182 |
+
# # Apply Gaussian blur to background
|
183 |
+
# result = apply_gaussian_blur_to_background(image_np, binary_mask, sigma=blur_strength)
|
184 |
|
185 |
+
# return result
|
186 |
|
187 |
+
# elif blur_effect_type == "Depth-Based Lens Blur":
|
188 |
+
# # Resize for depth estimation
|
189 |
+
# depth_input = cv2.resize(image_np, (512, 512))
|
190 |
|
191 |
+
# # Get depth map
|
192 |
+
# depth_result = process_image.depth_estimator(depth_input)
|
193 |
+
# depth_map = np.array(depth_result["depth"])
|
194 |
|
195 |
+
# # Normalize depth map
|
196 |
+
# normalized_depth = normalize_depth_map(depth_map)
|
197 |
|
198 |
+
# # Apply depth-based blur
|
199 |
+
# result = apply_depth_based_blur(depth_input, normalized_depth, max_blur=blur_strength)
|
200 |
|
201 |
+
# # Resize back to original dimensions if needed
|
202 |
+
# if image_np.shape[:2] != (512, 512):
|
203 |
+
# result = cv2.resize(result, (image_np.shape[1], image_np.shape[0]))
|
204 |
|
205 |
+
# return result
|
206 |
|
207 |
+
# else:
|
208 |
+
# return image_np # Return original if no effect selected
|
209 |
+
|
210 |
+
def process_image(input_image, blur_effect_type, blur_strength, target_class):
|
211 |
+
try:
|
212 |
+
# Load models if not already loaded
|
213 |
+
if not hasattr(process_image, "models_loaded"):
|
214 |
+
process_image.segmenter, process_image.depth_estimator = load_models()
|
215 |
+
process_image.models_loaded = True
|
216 |
+
|
217 |
+
# Convert to numpy array
|
218 |
+
image_np = np.array(input_image)
|
219 |
+
|
220 |
+
# Process based on selected effect
|
221 |
+
if blur_effect_type == "Gaussian Background Blur":
|
222 |
+
# Segment the image
|
223 |
+
segmentation_results = process_image.segmenter(input_image)
|
224 |
+
|
225 |
+
# Create binary mask
|
226 |
+
binary_mask = create_binary_mask(segmentation_results, image_np, target_class)
|
227 |
+
|
228 |
+
# Apply Gaussian blur to background
|
229 |
+
result = apply_gaussian_blur_to_background(image_np, binary_mask, sigma=blur_strength)
|
230 |
+
|
231 |
+
return result
|
232 |
+
|
233 |
+
elif blur_effect_type == "Depth-Based Lens Blur":
|
234 |
+
# Resize for depth estimation
|
235 |
+
depth_input = cv2.resize(image_np, (512, 512))
|
236 |
+
|
237 |
+
# Get depth map
|
238 |
+
depth_result = process_image.depth_estimator(depth_input)
|
239 |
+
depth_map = np.array(depth_result["depth"])
|
240 |
+
|
241 |
+
# Apply depth-based blur
|
242 |
+
result = apply_depth_based_blur(depth_input, depth_map, max_blur=blur_strength)
|
243 |
+
|
244 |
+
# Resize back to original dimensions if needed
|
245 |
+
if image_np.shape[:2] != (512, 512):
|
246 |
+
result = cv2.resize(result, (image_np.shape[1], image_np.shape[0]))
|
247 |
+
|
248 |
+
return result
|
249 |
+
|
250 |
+
else:
|
251 |
+
return image_np # Return original if no effect selected
|
252 |
+
|
253 |
+
except Exception as e:
|
254 |
+
print(f"Error in process_image: {e}")
|
255 |
+
# Return the original image if there's an error
|
256 |
+
return input_image
|
257 |
+
|
258 |
|
259 |
# Create Gradio interface
|
260 |
demo = gr.Blocks(title="Image Blur Effects")
|
|
|
295 |
outputs=output_image
|
296 |
)
|
297 |
|
298 |
+
error_output = gr.Textbox(label="Error Information", visible=False)
|
299 |
+
|
300 |
gr.Markdown("""
|
301 |
## How to use:
|
302 |
1. Upload an image with a clear foreground subject
|
|
|
312 |
segmenter, depth_estimator = load_models()
|
313 |
|
314 |
# Launch the app
|
315 |
+
demo.launch(show_error = True)
|