Spaces:
Sleeping
Sleeping
Update to add synthetic blur
Browse files
.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 |
-
|
| 57 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
def update_gaussian(img, kernel_size):
|
| 85 |
return gaussian_blur(img, kernel_size)
|
| 86 |
|
| 87 |
|
| 88 |
-
def update_lens(img,
|
| 89 |
-
return lens_blur(img,
|
| 90 |
|
| 91 |
|
| 92 |
-
def
|
| 93 |
-
|
| 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("## 🌀
|
| 100 |
|
| 101 |
with gr.Row():
|
| 102 |
image_input = gr.Image(type="pil", label="Upload Image")
|
| 103 |
|
| 104 |
with gr.Row():
|
| 105 |
-
|
| 106 |
-
lens_slider = gr.Slider(
|
| 107 |
-
|
| 108 |
-
)
|
| 109 |
|
| 110 |
with gr.Row():
|
| 111 |
-
|
| 112 |
-
|
|
|
|
| 113 |
|
| 114 |
-
#
|
| 115 |
image_input.change(
|
| 116 |
-
fn=
|
| 117 |
-
inputs=[image_input,
|
| 118 |
-
outputs=[
|
| 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 |
-
#
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 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()
|