InspiraLens / app.py
Ahmad Basyouni
Add application file
b73a750
import gradio as gr
from diffusers import StableDiffusionPipeline, EulerAncestralDiscreteScheduler, DDIMScheduler, PNDMScheduler
import torch
from PIL import ImageEnhance, Image
import numpy as np
import spaces # For using ZeroGPU decorator
# Load Stable Diffusion pipeline with efficient defaults
model_id = "CompVis/stable-diffusion-v1-4"
default_scheduler = DDIMScheduler.from_pretrained(model_id, subfolder="scheduler")
device = "cuda" if torch.cuda.is_available() else "cpu"
torch_dtype = torch.float16 if device == "cuda" else torch.float32
pipe = StableDiffusionPipeline.from_pretrained(model_id, scheduler=default_scheduler, torch_dtype=torch_dtype).to(device)
# Scheduler options (setting DDIM as the default for speed)
schedulers = {
"High-Definition & Fast (DDIM) - Good quality with fastest speed": DDIMScheduler,
"Photo-Realistic (PNDM) - Best for realistic details, moderate speed": PNDMScheduler,
"Artistic & Imaginative (Euler Ancestral) - Good for creative scenes, moderate speed": EulerAncestralDiscreteScheduler,
}
# Main image generation function with 60-second GPU duration limit
@spaces.GPU(duration=60)
def generate_image(prompt, use_categories, genre, style, theme, lighting, scheduler_choice, quality, size):
# Check if additional categories should be added to the prompt
if use_categories:
prompt_text = (
f"{prompt.strip()} in a {genre.lower()} wallpaper style, "
f"with {style.lower()} visuals, focusing on a {theme.lower()} theme "
f"and {lighting.lower()} lighting."
)
else:
prompt_text = prompt.strip()
# Set the scheduler based on user choice
scheduler = schedulers[scheduler_choice].from_pretrained(model_id, subfolder="scheduler")
pipe.scheduler = scheduler
# Set output size based on selection
image_size = (512, 512) if size == "Profile Picture" else (512, 512) # Using smaller size for faster generation
# Generate image with specified quality and size
with torch.no_grad():
image = pipe(prompt_text, num_inference_steps=quality, guidance_scale=7.5).images[0]
image = image.resize(image_size) # Resize image to fit selected dimensions
return np.array(image) # Return as NumPy array for Gradio
# Post-processing function for brightness and contrast
def adjust_brightness_contrast(image, brightness, contrast):
image = Image.fromarray(image.astype('uint8'), 'RGB')
image = ImageEnhance.Brightness(image).enhance(brightness)
image = ImageEnhance.Contrast(image).enhance(contrast)
return np.array(image)
# Warning function for high-quality settings
def show_warning(quality):
if quality > 40: # Lower threshold for warning
return "⚠️ High Quality: This may slow down generation. Consider using values below 40 for faster results."
return ""
# Build Gradio Interface with adjusted defaults
with gr.Blocks() as demo:
gr.Markdown("# ✨ AI-Powered Wallpaper/Profile Picture Generator\n🖼️ A tool to generate and fine-tune AI-created wallpapers and profile pictures with adjustable styles and effects.")
# Image Generation Section
with gr.Tab("Image Generator"):
gr.Markdown("## Generate an Image")
with gr.Row():
with gr.Column():
custom_prompt = gr.Textbox(label="Custom Prompt", placeholder="Describe your image (e.g., 'A forest at sunset')")
# Toggle for using additional categories
use_categories = gr.Checkbox(label="Enable Advanced Settings (Genre, Style, Theme, Lighting)", value=False)
# Additional categories, hidden by default and shown only if use_categories is checked
with gr.Accordion("Advanced Settings", open=False):
genre = gr.Dropdown(["Futuristic", "Nature", "Abstract", "Fantasy", "Sci-Fi", "Cyberpunk"], label="Genre")
style = gr.Dropdown(["Realistic", "Surreal", "Digital Art", "Cartoon", "Photorealistic"], label="Style")
theme = gr.Dropdown(["Landscape", "Portrait", "Abstract Patterns", "Architecture"], label="Theme")
lighting = gr.Dropdown(["Warm", "Cool", "Cinematic", "Soft", "Neon"], label="Lighting")
# Reduced quality for faster generation
quality = gr.Slider(20, 80, value=30, step=10, label="Image Quality", info="Lower values for faster generation.")
warning_message = gr.Markdown("")
# Scheduler selection with default option as DDIM for speed
scheduler_choice = gr.Dropdown(
[
"High-Definition & Fast (DDIM) - Good quality with fastest speed",
"Photo-Realistic (PNDM) - Best for realistic details, moderate speed",
"Artistic & Imaginative (Euler Ancestral) - Good for creative scenes, moderate speed"
],
label="Artistic Style & Speed",
value="High-Definition & Fast (DDIM) - Good quality with fastest speed"
)
size = gr.Dropdown(["Profile Picture", "Wallpaper"], label="Image Size", value="Profile Picture")
generate_button = gr.Button("Generate Image")
with gr.Column():
generated_image = gr.Image(label="Generated Image", interactive=False)
# Display warning message for high-quality settings
quality.change(show_warning, inputs=[quality], outputs=warning_message)
# Bind the generate function to the generate button
generate_button.click(
fn=generate_image,
inputs=[custom_prompt, use_categories, genre, style, theme, lighting, scheduler_choice, quality, size],
outputs=generated_image
)
# Post-Processing Section
with gr.Tab("Edit Generated Image"):
gr.Markdown("## Adjust Brightness & Contrast")
with gr.Row():
with gr.Column():
brightness_slider = gr.Slider(0.5, 2.0, value=1.0, label="Brightness")
contrast_slider = gr.Slider(0.5, 2.0, value=1.0, label="Contrast")
apply_adjustments = gr.Button("Apply Adjustments")
with gr.Column():
output_image = gr.Image(label="Adjusted Image", interactive=False)
# Bind the brightness and contrast adjustment function to the Apply Adjustments button
apply_adjustments.click(
fn=adjust_brightness_contrast,
inputs=[generated_image, brightness_slider, contrast_slider],
outputs=output_image
)
# Launch with a public shareable link
demo.launch(share=True)