import gradio as gr import numpy as np from transformers import BeitImageProcessor, BeitForSemanticSegmentation, DPTImageProcessor, DPTForDepthEstimation from PIL import Image, ImageFilter import torch import cv2 # Load the updated BeitImageProcessor for segmentation segmentation_processor = BeitImageProcessor.from_pretrained("microsoft/beit-base-finetuned-ade-640-640") segmentation_model = BeitForSemanticSegmentation.from_pretrained("microsoft/beit-base-finetuned-ade-640-640") # Load the updated DPTImageProcessor for depth estimation depth_feature_extractor = DPTImageProcessor.from_pretrained("Intel/dpt-large") depth_model = DPTForDepthEstimation.from_pretrained("Intel/dpt-large") def apply_gaussian_blur(image): # Resize and preprocess the image image = image.resize((512, 512)).convert("RGB") inputs = segmentation_processor(image, return_tensors="pt") # Perform semantic segmentation using the model with torch.no_grad(): outputs = segmentation_model(**inputs) logits = outputs.logits # Get the predicted class for each pixel segmentation = torch.argmax(logits, dim=1)[0] # Shape: [height, width] # Create a binary mask for the 'person' class person_index = 12 # Assuming 12 is the 'person' class index binary_mask = (segmentation == person_index).numpy().astype(np.uint8) * 255 # Convert to 0 and 255 # Resize the mask to match the image size (512x512) binary_mask = cv2.resize(binary_mask, (512, 512), interpolation=cv2.INTER_NEAREST) # Convert the original image to a numpy array image_np = np.array(image) # Apply Gaussian blur to the entire image blurred_image = cv2.GaussianBlur(image_np, (0, 0), sigmaX=15, sigmaY=15) # Normalize the mask to range between 0 and 1 normalized_mask = binary_mask / 255.0 normalized_mask = np.expand_dims(normalized_mask, axis=-1) # Add channel dimension # Create the composite image with the blurred background final_image = (image_np * normalized_mask + blurred_image * (1 - normalized_mask)).astype(np.uint8) # Convert back to PIL Image final_image_pil = Image.fromarray(final_image) return final_image_pil def apply_lens_blur(image): # Resize and preprocess the image image = image.resize((512, 512)).convert("RGB") depth_inputs = depth_feature_extractor(images=image, return_tensors="pt") # Perform depth estimation with torch.no_grad(): depth_outputs = depth_model(**depth_inputs) predicted_depth = depth_outputs.predicted_depth[0].cpu().numpy() # Normalize and invert the depth map min_depth = predicted_depth.min() max_depth = predicted_depth.max() normalized_depth = (predicted_depth - min_depth) / (max_depth - min_depth) inverted_depth = 1 - normalized_depth # Resize the depth map to match the original image size depth_weight_resized = Image.fromarray((inverted_depth * 255).astype(np.uint8)).resize((512, 512)) depth_weight_resized = np.array(depth_weight_resized) / 255.0 depth_weight_resized = depth_weight_resized[:, :, np.newaxis] # Apply maximum Gaussian blur to the original image blurred_image = image.filter(ImageFilter.GaussianBlur(radius=15)) # Convert images to numpy arrays original_np = np.array(image).astype(np.float32) blurred_np = np.array(blurred_image).astype(np.float32) # Blend the images based on the resized depth map output_np = (1 - depth_weight_resized) * original_np + depth_weight_resized * blurred_np # Convert back to uint8 output_np = np.clip(output_np, 0, 255).astype(np.uint8) return Image.fromarray(output_np) # Define a function to call the correct blurring function based on user selection def apply_blur(effect, image): if effect == "Gaussian Blur": return apply_gaussian_blur(image) elif effect == "Lens Blur": return apply_lens_blur(image) # Define the Gradio interface interface = gr.Interface( fn=apply_blur, inputs=[ gr.Dropdown(choices=["Gaussian Blur", "Lens Blur"], label="Select Blur Effect"), gr.Image(type="pil") ], outputs=gr.Image(type="pil"), title="Blur Effects with Hugging Face", description="Apply Gaussian Blur or Lens Blur to images using semantic segmentation or depth estimation." ) # Launch the Gradio interface interface.launch()