|
import gradio as gr |
|
|
|
import gradio as gr |
|
import numpy as np |
|
import torch |
|
import cv2 |
|
from PIL import Image |
|
from transformers import ( |
|
AutoImageProcessor, |
|
SegformerForSemanticSegmentation, |
|
DPTImageProcessor, |
|
DPTForDepthEstimation |
|
) |
|
|
|
|
|
seg_processor = AutoImageProcessor.from_pretrained("nvidia/segformer-b0-finetuned-ade-512-512") |
|
seg_model = SegformerForSemanticSegmentation.from_pretrained("nvidia/segformer-b0-finetuned-ade-512-512") |
|
|
|
depth_processor = DPTImageProcessor.from_pretrained("Intel/dpt-hybrid-midas") |
|
depth_model = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas") |
|
|
|
|
|
def segmentation_blur(image): |
|
inputs = seg_processor(images=image, return_tensors="pt") |
|
with torch.no_grad(): |
|
outputs = seg_model(**inputs) |
|
pred = outputs.logits.argmax(dim=1)[0].cpu().numpy() |
|
|
|
mask = (pred == 12).astype(np.uint8) * 255 |
|
mask_resized = cv2.resize(mask, image.size, interpolation=cv2.INTER_NEAREST) |
|
|
|
image_np = np.array(image) |
|
mask_3ch = np.stack([mask_resized] * 3, axis=-1) // 255 |
|
blurred = cv2.GaussianBlur(image_np, (0, 0), sigmaX=15) |
|
combined = np.where(mask_3ch == 1, image_np, blurred) |
|
|
|
return Image.fromarray(combined) |
|
|
|
|
|
def apply_depth_based_blur(image_np, depth_map_norm, max_blur=25): |
|
h, w = depth_map_norm.shape |
|
blurred_image = np.zeros_like(image_np) |
|
image_np = image_np.astype(np.float32) |
|
|
|
for i in range(1, max_blur+1, 2): |
|
mask = ((depth_map_norm >= (i / max_blur)) & (depth_map_norm < ((i + 2) / max_blur))).astype(np.uint8) |
|
if np.sum(mask) == 0: |
|
continue |
|
blurred = cv2.GaussianBlur(image_np, (i, i), 0) |
|
mask_3ch = np.stack([mask]*3, axis=-1) |
|
blurred_image = np.where(mask_3ch == 1, blurred, blurred_image) |
|
|
|
sharpest_mask = (depth_map_norm < 0.1).astype(np.uint8) |
|
sharpest_mask_3ch = np.stack([sharpest_mask]*3, axis=-1) |
|
final_image = np.where(sharpest_mask_3ch == 1, image_np, blurred_image) |
|
|
|
return final_image.astype(np.uint8) |
|
|
|
def depth_blur(image): |
|
inputs = depth_processor(images=image, return_tensors="pt") |
|
with torch.no_grad(): |
|
outputs = depth_model(**inputs) |
|
|
|
depth_map = outputs.predicted_depth[0].cpu().numpy() |
|
depth_map = cv2.resize(depth_map, image.size) |
|
norm_depth = (depth_map - depth_map.min()) / (depth_map.max() - depth_map.min()) |
|
|
|
image_np = np.array(image) |
|
blurred_image = apply_depth_based_blur(image_np, norm_depth) |
|
return Image.fromarray(blurred_image) |
|
|
|
|
|
def process(image, mode): |
|
if mode == "Segmentation Blur": |
|
return segmentation_blur(image) |
|
else: |
|
return depth_blur(image) |
|
|
|
demo = gr.Interface( |
|
fn=process, |
|
inputs=[ |
|
gr.Image(type="pil", label="Upload Image"), |
|
gr.Radio(["Segmentation Blur", "Depth Blur"], value="Segmentation Blur", label="Blur Mode") |
|
], |
|
outputs=gr.Image(label="Output"), |
|
title="Image Blur Effects (Segmentation & Depth)", |
|
description="Upload an image and apply either Zoom-style background blur or DSLR-style depth blur." |
|
) |
|
|
|
demo.launch() |
|
|