DL / app.py
sjagird1's picture
Update app.py
45e8db4 verified
try:
import torch
import torchvision
except ImportError:
import subprocess
import sys
subprocess.check_call([sys.executable, "-m", "pip", "install", "torch", "torchvision"])
import torch
import torchvision
import gradio as gr
import numpy as np
from PIL import Image
import torchvision.transforms as transforms
from transformers import pipeline
from scipy.ndimage import gaussian_filter
def preprocess_image(image, target_size=(512, 512)):
"""Preprocess the input image"""
if isinstance(image, str):
image = Image.open(image)
elif isinstance(image, np.ndarray):
image = Image.fromarray(image)
# Calculate aspect ratio preserving resize
aspect_ratio = image.size[0] / image.size[1]
if aspect_ratio > 1:
new_width = int(target_size[0] * aspect_ratio)
new_height = target_size[1]
else:
new_width = target_size[0]
new_height = int(target_size[1] / aspect_ratio)
preprocess = transforms.Compose([
transforms.Resize((new_height, new_width)),
transforms.CenterCrop(target_size),
])
return preprocess(image)
def estimate_depth(image, pipe):
"""Estimate depth using the Depth-Anything model"""
depth_output = pipe(image)
depth_map = depth_output["depth"]
depth_map = np.array(depth_map) / 16.67
return depth_map
def apply_depth_aware_blur(image, depth_map, max_sigma, min_sigma):
"""Apply variable Gaussian blur based on depth values"""
image_array = np.array(image)
blurred = np.zeros_like(image_array, dtype=np.float32)
# Calculate sigma for each depth value
sigmas = np.interp(depth_map, [depth_map.min(), depth_map.max()], [min_sigma, max_sigma])
unique_sigmas = np.unique(sigmas)
blur_stack = {}
# Create blurred versions for each unique sigma
for sigma in unique_sigmas:
if sigma > 0:
blurred_image = np.zeros_like(image_array, dtype=np.float32)
for channel in range(3):
blurred_image[:, :, channel] = gaussian_filter(
image_array[:, :, channel].astype(np.float32),
sigma=sigma
)
blur_stack[sigma] = blurred_image
# Combine blurred versions
for sigma in 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 apply_gaussian_blur(image, sigma):
"""Apply uniform Gaussian blur"""
image_array = np.array(image)
blurred = np.zeros_like(image_array)
for channel in range(3):
blurred[:, :, channel] = gaussian_filter(
image_array[:, :, channel],
sigma=sigma
)
return Image.fromarray(blurred.astype(np.uint8))
# Initialize depth estimation pipeline (moved inside the processing function to avoid CUDA issues)
def get_depth_pipeline():
return pipeline(
task="depth-estimation",
model="depth-anything/Depth-Anything-V2-Small-hf",
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
device=0 if torch.cuda.is_available() else -1
)
def process_image(image, blur_type, gaussian_sigma, lens_min_sigma, lens_max_sigma):
"""Main processing function for Gradio interface"""
if image is None:
return None
processed_image = preprocess_image(image)
if blur_type == "Gaussian Blur":
result = apply_gaussian_blur(processed_image, gaussian_sigma)
else: # Lens Blur
pipe = get_depth_pipeline()
depth_map = estimate_depth(processed_image, pipe)
result = apply_depth_aware_blur(processed_image, depth_map, lens_max_sigma, lens_min_sigma)
return result
# Create Gradio interface
with gr.Blocks() as demo:
gr.Markdown("# Image Blur Effects Demo")
gr.Markdown("Apply Gaussian or Lens (Depth-aware) blur to your images")
with gr.Row():
with gr.Column():
input_image = gr.Image(label="Input Image", type="numpy")
blur_type = gr.Radio(
choices=["Gaussian Blur", "Lens Blur"],
label="Blur Effect",
value="Gaussian Blur"
)
with gr.Column(visible=True) as gaussian_controls:
gaussian_sigma = gr.Slider(
minimum=0, maximum=20, value=5,
label="Gaussian Blur Sigma",
step=0.5
)
with gr.Column() as lens_controls:
lens_min_sigma = gr.Slider(
minimum=0, maximum=20, value=15,
label="Maximum Blur (Far)",
step=0.5
)
lens_max_sigma = gr.Slider(
minimum=0, maximum=10, value=0,
label="Minimum Blur (Near)",
step=0.5
)
process_btn = gr.Button("Apply Blur")
with gr.Column():
output_image = gr.Image(label="Output Image")
# Handle visibility of controls based on blur type selection
def update_controls(blur_type):
return {
gaussian_controls: blur_type == "Gaussian Blur",
lens_controls: blur_type == "Lens Blur"
}
blur_type.change(
fn=update_controls,
inputs=[blur_type],
outputs=[gaussian_controls, lens_controls]
)
# Process image when button is clicked
process_btn.click(
fn=process_image,
inputs=[
input_image,
blur_type,
gaussian_sigma,
lens_min_sigma,
lens_max_sigma
],
outputs=output_image
)
# Launch the demo
demo.launch()