gchallar's picture
Update app.py
949b21d verified
raw
history blame
3.98 kB
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(shape=(256, 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()