File size: 3,996 Bytes
da08054
 
 
 
 
 
 
 
 
 
 
 
949b21d
 
 
 
 
da08054
949b21d
da08054
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a38f9d
da08054
 
 
 
 
 
 
a2d6b95
da08054
3d0e8ab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import gradio as gr
from PIL import Image, ImageFilter
import numpy as np
import torch
import cv2
from transformers import AutoImageProcessor, AutoModelForDepthEstimation

# Load depth estimation model
image_processor = AutoImageProcessor.from_pretrained("depth-anything/Depth-Anything-V2-Small-hf")
model = AutoModelForDepthEstimation.from_pretrained("depth-anything/Depth-Anything-V2-Small-hf")

def apply_gaussian_blur(image, mask):
    """Applies Gaussian blur to the background based on a user-drawn mask."""
    
    if mask is None:
        return image  # If no mask is provided, return the original image
    
    # Ensure mask is grayscale and resized to match image dimensions
    mask_pil = Image.fromarray(mask).convert("L").resize(image.size)
    mask_array = np.array(mask_pil)

    # Create a blurred background
    blurred_background = image.filter(ImageFilter.GaussianBlur(radius=15))

    # Convert images to NumPy arrays
    img_array = np.array(image)
    blurred_array = np.array(blurred_background)

    # Create a boolean mask (foreground = True, background = False)
    foreground_mask = mask_array > 0
    foreground_mask_3d = np.stack([foreground_mask] * 3, axis=-1)

    # Blend the original image with the blurred background
    final_image_array = np.where(foreground_mask_3d, img_array, blurred_array)
    final_image = Image.fromarray(final_image_array.astype(np.uint8))

    return final_image

def apply_lens_blur(image):
    """Applies depth-based lens blur using a pre-trained model."""
    
    # Resize image to 512x512 for processing
    resized_image = image.resize((512, 512))
    image_np = np.array(resized_image)

    # Prepare image for the model
    inputs = image_processor(images=resized_image, return_tensors="pt")

    with torch.no_grad():
        outputs = model(**inputs)
        predicted_depth = outputs.predicted_depth

    # Interpolate depth map to match the image size
    prediction = torch.nn.functional.interpolate(
        predicted_depth.unsqueeze(1),
        size=resized_image.size[::-1],
        mode="bicubic",
        align_corners=False,
    ).squeeze() 

    # Convert prediction to a NumPy array
    depth_map = prediction.cpu().numpy()

    # Normalize the depth map
    depth_norm = (depth_map - np.min(depth_map)) / (np.max(depth_map) - np.min(depth_map))

    num_blur_levels = 5  
    blurred_layers = []
    for i in range(num_blur_levels):
        sigma = i * 0.5
        if sigma == 0:
            blurred = image_np
        else:
            blurred = cv2.GaussianBlur(image_np, (15, 15), sigmaX=sigma, sigmaY=sigma, borderType=cv2.BORDER_REPLICATE)
        blurred_layers.append(blurred)

    depth_indices = ((1 - depth_norm) * (num_blur_levels - 1)).astype(np.uint8)

    final_blurred_image = np.zeros_like(image_np)
    for y in range(image_np.shape[0]):
        for x in range(image_np.shape[1]):
            depth_index = depth_indices[y, x]
            final_blurred_image[y, x] = blurred_layers[depth_index][y, x]

    # Convert the final blurred image back to a PIL Image
    final_blurred_pil_image = Image.fromarray(final_blurred_image)

    return final_blurred_pil_image

def process_image(image, mask, blur_type):
    """Processes the image based on the selected blur type."""
    if blur_type == "Gaussian Blur":
        return apply_gaussian_blur(image, mask)
    elif blur_type == "Lens Blur":
        return apply_lens_blur(image)
    else:
        return image

interface = gr.Interface(
    fn=process_image,
    inputs=[
        gr.Image(type="pil", label="Upload an Image"),
        gr.Sketchpad(height=256, width=256, label="Draw Mask (Only for Gaussian Blur)"),
        gr.Radio(["Gaussian Blur", "Lens Blur"], label="Choose Blur Effect")
    ],
    outputs=gr.Image(type="pil"),
    title="Gaussian & Lens Blur Effects",
    description="Upload an image and select either Gaussian blur (with mask) or depth-based lens blur."
)


if __name__ == "__main__":
    interface.launch(share=True)