CoolFace
Apppublic

Jeevan-HM/blur_background

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
app.py176 linesDownload Raw Back to root
1import cv22import numpy as np3import gradio as gr4from PIL import Image5from scipy.ndimage import gaussian_filter6from transformers import (7    AutoImageProcessor,8    AutoModelForDepthEstimation,9)10import torch11 12 13def resize_to_512(img: Image.Image) -> Image.Image:14    return img.resize((512, 512)) if img.size != (512, 512) else img15 16 17def gaussian_blur(img: Image.Image, kernel_size: int):18    img = resize_to_512(img)19    img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)20    blurred = cv2.GaussianBlur(img_cv, (kernel_size | 1, kernel_size | 1), 0)21    return cv2.cvtColor(blurred, cv2.COLOR_BGR2RGB)22 23 24depth_model_id = "depth-anything/Depth-Anything-V2-Small-hf"25processor = AutoImageProcessor.from_pretrained(depth_model_id)26depth_model = AutoModelForDepthEstimation.from_pretrained(depth_model_id)27 28 29def lens_blur(img: Image.Image, max_blur_radius: int):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)36        predicted_depth = outputs.predicted_depth37 38    depth = (39        torch.nn.functional.interpolate(40            predicted_depth.unsqueeze(1),41            size=(512, 512),42            mode="bicubic",43            align_corners=False,44        )45        .squeeze()46        .cpu()47        .numpy()48    )49 50    depth_norm = (depth - depth.min()) / (depth.max() - depth.min())51    depth_inverted = 1.0 - depth_norm52 53    num_levels = 654    max_sigma = max_blur_radius / 2.055    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)61    depth_frac = depth_scaled - depth_int62 63    for i in range(num_levels - 1):64        mask = depth_int == i65        alpha = depth_frac[mask]66        for c in range(3):67            blended = (68                blurred_images[i][..., c][mask] * (1 - alpha)69                + blurred_images[i + 1][..., c][mask] * alpha70            )71            blurred_final[..., c][mask] = blended72 73    return np.clip(blurred_final, 0, 255).astype(np.uint8)74 75 76def 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 += 192 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[104                        blur_radius // 2, blur_radius // 2105                    ]106                except:107                    blurred_image[i, j] = original_rgb[i, j]108            else:109                blurred_image[i, j] = original_rgb[i, j]110 111    return blurred_image112 113 114def apply_all_blurs(img, g_kernel, lens_radius, synthetic_radius):115    g = gaussian_blur(img, g_kernel)116    l = lens_blur(img, lens_radius)117    s = synthetic_lens_blur(img, synthetic_radius)118    return g, l, s119 120 121def update_gaussian(img, kernel_size):122    return gaussian_blur(img, kernel_size)123 124 125def update_lens(img, radius):126    return lens_blur(img, radius)127 128 129def update_synthetic(img, radius):130    return synthetic_lens_blur(img, radius)131 132 133with gr.Blocks() as demo:134    gr.Markdown(135        "## ๐ŸŒ€ Blur Effects Comparison: Gaussian, Depth-Based, Synthetic (Depth Based Blur works with bottles)"136    )137 138    with gr.Row():139        image_input = gr.Image(type="pil", label="Upload Image")140 141    with gr.Row():142        g_slider = gr.Slider(1, 49, step=2, value=11, label="Gaussian Kernel Size")143        lens_slider = gr.Slider(144            1,145            50,146            step=1,147            value=15,148            label="Depth-Based Blur Intensity (Works with bottles)",149        )150        synth_slider = gr.Slider(1, 50, step=1, value=25, label="Synthetic Blur Radius")151 152    with gr.Row():153        g_output = gr.Image(label="Gaussian Blurred Image")154        l_output = gr.Image(label="Depth-Based Lens Blurred Image")155        s_output = gr.Image(label="Synthetic Depth Lens Blurred Image")156 157    # Initial image upload updates all three158    image_input.change(159        fn=apply_all_blurs,160        inputs=[image_input, g_slider, lens_slider, synth_slider],161        outputs=[g_output, l_output, s_output],162    )163 164    # Individual updates for each slider165    g_slider.change(166        fn=update_gaussian, inputs=[image_input, g_slider], outputs=g_output167    )168    lens_slider.change(169        fn=update_lens, inputs=[image_input, lens_slider], outputs=l_output170    )171    synth_slider.change(172        fn=update_synthetic, inputs=[image_input, synth_slider], outputs=s_output173    )174 175demo.launch()176