|
import gradio as gr |
|
import torch |
|
import numpy as np |
|
from PIL import Image |
|
from scipy.ndimage import gaussian_filter |
|
from transformers import pipeline |
|
|
|
def preprocess_image(image): |
|
"""Resize and convert image to PIL format if needed.""" |
|
if isinstance(image, np.ndarray): |
|
image = Image.fromarray(image) |
|
|
|
|
|
image = image.resize((512, 512)) |
|
return image |
|
|
|
def segment_image(image, model_name="yolov8n-seg"): |
|
""" |
|
Perform instance segmentation on the input image using YOLO segmentation model. |
|
""" |
|
from ultralytics import YOLO |
|
|
|
|
|
model = YOLO(model_name) |
|
|
|
|
|
results = model(image) |
|
|
|
|
|
mask = np.zeros((image.size[1], image.size[0]), dtype=np.uint8) |
|
|
|
|
|
for result in results: |
|
if result.masks is not None: |
|
for single_mask in result.masks: |
|
|
|
mask_array = single_mask.data.cpu().numpy().squeeze() |
|
mask_array = (mask_array > 0.5).astype(np.uint8) |
|
|
|
|
|
if mask_array.shape != mask.shape: |
|
mask_array = np.array( |
|
Image.fromarray(mask_array).resize( |
|
(image.size[0], image.size[1]), |
|
Image.NEAREST |
|
) |
|
) |
|
|
|
|
|
mask = np.maximum(mask, mask_array) |
|
|
|
return mask |
|
|
|
def apply_gaussian_blur(image, sigma=15): |
|
"""Apply Gaussian blur to the background.""" |
|
|
|
image_array = np.array(image) |
|
|
|
|
|
foreground_mask = segment_image(image) |
|
|
|
|
|
blurred = np.zeros_like(image_array) |
|
for channel in range(3): |
|
blurred[:, :, channel] = gaussian_filter(image_array[:, :, channel], sigma=sigma) |
|
|
|
|
|
mask_3d = np.stack([foreground_mask] * 3, axis=2) |
|
result = image_array * mask_3d + blurred * (1 - mask_3d) |
|
|
|
return Image.fromarray(result.astype(np.uint8)) |
|
|
|
def estimate_depth(image, model_name="depth-anything/Depth-Anything-V2-Small-hf"): |
|
"""Estimate depth of the image.""" |
|
depth_estimator = pipeline( |
|
task="depth-estimation", |
|
model=model_name, |
|
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32 |
|
) |
|
|
|
depth_output = depth_estimator(image) |
|
depth_map = np.array(depth_output["depth"]) |
|
|
|
|
|
depth_map = (depth_map - depth_map.min()) / (depth_map.max() - depth_map.min()) |
|
|
|
return depth_map |
|
|
|
def apply_depth_aware_blur(image, max_sigma=15, min_sigma=0): |
|
"""Apply depth-aware blur with farther objects more blurred.""" |
|
|
|
depth_map = estimate_depth(image) |
|
|
|
|
|
depth_map = 1 - depth_map |
|
|
|
image_array = np.array(image) |
|
|
|
|
|
max_blurred = np.zeros_like(image_array, dtype=np.float32) |
|
for channel in range(3): |
|
max_blurred[:, :, channel] = gaussian_filter( |
|
image_array[:, :, channel].astype(np.float32), |
|
sigma=max_sigma |
|
) |
|
|
|
|
|
depth_3d = np.stack([depth_map] * 3, axis=2) |
|
|
|
|
|
result = image_array * (1 - depth_3d) + max_blurred * depth_3d |
|
|
|
return Image.fromarray(result.astype(np.uint8)) |
|
|
|
def process_image(image, blur_type, sigma=15): |
|
"""Process image based on blur type.""" |
|
|
|
pil_image = preprocess_image(image) |
|
|
|
|
|
if blur_type == "Gaussian Background Blur": |
|
result = apply_gaussian_blur(pil_image, sigma) |
|
elif blur_type == "Depth-Aware Lens Blur": |
|
result = apply_depth_aware_blur(pil_image, max_sigma=sigma) |
|
else: |
|
result = pil_image |
|
|
|
return result |
|
|
|
|
|
def create_blur_app(): |
|
with gr.Blocks() as demo: |
|
gr.Markdown("# Image Blur Effects") |
|
|
|
with gr.Row(): |
|
input_image = gr.Image(label="Input Image", type="pil") |
|
output_image = gr.Image(label="Processed Image") |
|
|
|
with gr.Row(): |
|
blur_type = gr.Dropdown( |
|
choices=[ |
|
"Gaussian Background Blur", |
|
"Depth-Aware Lens Blur" |
|
], |
|
label="Blur Type" |
|
) |
|
sigma = gr.Slider( |
|
minimum=0, |
|
maximum=30, |
|
value=15, |
|
label="Blur Intensity" |
|
) |
|
|
|
process_btn = gr.Button("Apply Blur Effect") |
|
|
|
process_btn.click( |
|
fn=process_image, |
|
inputs=[input_image, blur_type, sigma], |
|
outputs=output_image |
|
) |
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
demo = create_blur_app() |
|
demo.launch() |