|
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="facebook/mask2former-swin-large-cityscapes-semantic"): |
|
"""Perform semantic segmentation on the input image.""" |
|
from transformers import AutoImageProcessor, Mask2FormerForUniversalSegmentation |
|
|
|
|
|
processor = AutoImageProcessor.from_pretrained(model_name) |
|
model = Mask2FormerForUniversalSegmentation.from_pretrained(model_name) |
|
|
|
|
|
inputs = processor(images=image, return_tensors="pt") |
|
|
|
|
|
with torch.no_grad(): |
|
outputs = model(**inputs) |
|
|
|
|
|
semantic_map = processor.post_process_semantic_segmentation( |
|
outputs, |
|
target_sizes=[image.size[::-1]] |
|
)[0] |
|
|
|
|
|
semantic_map = semantic_map.numpy() |
|
return semantic_map |
|
|
|
def apply_gaussian_blur(image, sigma=15): |
|
"""Apply Gaussian blur to the background.""" |
|
|
|
image_array = np.array(image) |
|
|
|
|
|
segmentation_mask = segment_image(image) |
|
|
|
|
|
foreground_mask = (segmentation_mask == 24).astype(np.uint8) |
|
|
|
|
|
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=10, min_sigma=0): |
|
"""Apply depth-aware blur to the image.""" |
|
|
|
depth_map = estimate_depth(image) |
|
|
|
image_array = np.array(image) |
|
blurred = np.zeros_like(image_array, dtype=np.float32) |
|
|
|
|
|
sigmas = np.interp(depth_map, [0, 1], [min_sigma, max_sigma]) |
|
|
|
|
|
blur_stack = {} |
|
for sigma in np.unique(sigmas): |
|
if sigma > 0: |
|
blurred_layer = np.zeros_like(image_array, dtype=np.float32) |
|
for channel in range(3): |
|
blurred_layer[:, :, channel] = gaussian_filter( |
|
image_array[:, :, channel].astype(np.float32), |
|
sigma=sigma |
|
) |
|
blur_stack[sigma] = blurred_layer |
|
|
|
|
|
for sigma in np.unique(sigmas): |
|
if sigma > 0: |
|
mask = (sigmas == sigma) |
|
mask_3d = np.stack([mask] * 3, axis=2) |
|
blurred += mask_3d * blur_stack[sigma] |
|
else: |
|
mask = (sigmas == 0) |
|
mask_3d = np.stack([mask] * 3, axis=2) |
|
blurred += mask_3d * image_array |
|
|
|
return Image.fromarray(blurred.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() |