Instant-Image / app.py
scooter7's picture
Update app.py
e21bd42 verified
from __future__ import annotations
import os
import random
import uuid
import gradio as gr
import spaces
import numpy as np
from diffusers import PixArtAlphaPipeline, LCMScheduler
import torch
from typing import Tuple
from datetime import datetime
# Description for the app
DESCRIPTION = """
# Instant Image
"""
if not torch.cuda.is_available():
DESCRIPTION += "\n<p>Running on CPU 🥶 This demo does not work on CPU.</p>"
# Configuration and constants
MAX_SEED = np.iinfo(np.int32).max
CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES", "1") == "1"
MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "4192"))
USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE", "0") == "1"
ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD", "0") == "1"
PORT = int(os.getenv("DEMO_PORT", "15432"))
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# Define color-based attributes
color_attributes = {
"Purple": {"verbs": ["assist", "befriend", "care", "collaborate", "connect", "embrace", "empower", "encourage", "foster", "give", "help", "nourish", "nurture", "promote", "protect", "provide", "serve", "share", "shepherd", "steward", "tend", "uplift", "value", "welcome"], "adjectives": ["caring", "encouraging", "attentive", "compassionate", "empathetic", "generous", "hospitable", "nurturing", "protective", "selfless", "supportive", "welcoming"]},
"Green": {"verbs": ["analyze", "discover", "examine", "expand", "explore", "extend", "inquire", "journey", "launch", "move", "pioneer", "pursue", "question", "reach", "search", "uncover", "venture", "wonder"], "adjectives": ["adventurous", "curious", "discerning", "examining", "experiential", "exploratory", "inquisitive", "investigative", "intrepid", "philosophical"]},
"Maroon": {"verbs": ["accomplish", "achieve", "build", "challenge", "commit", "compete", "contend", "dedicate", "defend", "devote", "drive", "endeavor", "entrust", "endure", "fight", "grapple", "grow", "improve", "increase", "overcome", "persevere", "persist", "press on", "pursue", "resolve"], "adjectives": ["competitive", "determined", "gritty", "industrious", "persevering", "relentless", "resilient", "tenacious", "tough", "unwavering"]},
"Orange": {"verbs": ["compose", "conceptualize", "conceive", "craft", "create", "design", "dream", "envision", "express", "fashion", "form", "imagine", "interpret", "make", "originate", "paint", "perform", "portray", "realize", "shape"], "adjectives": ["artistic", "conceptual", "creative", "eclectic", "expressive", "imaginative", "interpretive", "novel", "original", "whimsical"]},
"Yellow": {"verbs": ["accelerate", "advance", "change", "conceive", "create", "engineer", "envision", "experiment", "dream", "ignite", "illuminate", "imagine", "innovate", "inspire", "invent", "pioneer", "progress", "shape", "spark", "solve", "transform", "unleash", "unlock"], "adjectives": ["advanced", "analytical", "brilliant", "experimental", "forward-thinking", "innovative", "intelligent", "inventive", "leading-edge", "visionary"]},
"Red": {"verbs": ["animate", "amuse", "captivate", "cheer", "delight", "encourage", "energize", "engage", "enjoy", "enliven", "entertain", "excite", "express", "inspire", "joke", "motivate", "play", "stir", "uplift"], "adjectives": ["dynamic", "energetic", "engaging", "entertaining", "enthusiastic", "exciting", "fun", "lively", "magnetic", "playful", "humorous"]},
"Blue": {"verbs": ["accomplish", "achieve", "affect", "assert", "cause", "command", "determine", "direct", "dominate", "drive", "empower", "establish", "guide", "impact", "impress", "influence", "inspire", "lead", "outpace", "outshine", "realize", "shape", "succeed", "transform", "win"], "adjectives": ["accomplished", "assertive", "confident", "decisive", "elite", "influential", "powerful", "prominent", "proven", "strong"]},
"Pink": {"verbs": ["arise", "aspire", "detail", "dream", "elevate", "enchant", "enrich", "envision", "exceed", "excel", "experience", "improve", "idealize", "imagine", "inspire", "perfect", "poise", "polish", "prepare", "refine", "uplift"], "adjectives": ["aesthetic", "charming", "classic", "dignified", "idealistic", "meticulous", "poised", "polished", "refined", "sophisticated", "elegant"]},
"Silver": {"verbs": ["activate", "campaign", "challenge", "commit", "confront", "dare", "defy", "disrupt", "drive", "excite", "face", "ignite", "incite", "influence", "inspire", "inspirit", "motivate", "move", "push", "rebel", "reimagine", "revolutionize", "rise", "spark", "stir", "fight", "free"], "adjectives": ["bold", "daring", "fearless", "independent", "non-conformist", "radical", "rebellious", "resolute", "unconventional", "valiant"]},
"Beige": {"verbs": ["dedicate", "humble", "collaborate", "empower", "inspire", "empassion", "transform"], "adjectives": ["dedicated", "collaborative", "consistent", "empowering", "enterprising", "humble", "inspiring", "passionate", "proud", "traditional", "transformative"]},
}
# Image styles for Gradio interface
style_list = [
{"name": "(No style)", "prompt": "{prompt}", "negative_prompt": ""},
{"name": "Cinematic", "prompt": "cinematic still {prompt} . emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy", "negative_prompt": "anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured"},
{"name": "Realistic", "prompt": "Photorealistic {prompt} . Ulta-realistic, professional, 4k, highly detailed", "negative_prompt": "drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, disfigured"},
{"name": "Anime", "prompt": "anime artwork {prompt} . anime style, key visual, vibrant, studio anime, highly detailed", "negative_prompt": "photo, deformed, black and white, realism, disfigured, low contrast"},
{"name": "Digital Art", "prompt": "concept art {prompt} . digital artwork, illustrative, painterly, matte painting, highly detailed", "negative_prompt": "photo, photorealistic, realism, ugly"},
{"name": "Pixel art", "prompt": "pixel-art {prompt} . low-res, blocky, pixel art style, 8-bit graphics", "negative_prompt": "sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic"},
{"name": "Fantasy art", "prompt": "ethereal fantasy concept art of {prompt} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy", "negative_prompt": "photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white"},
{"name": "3D Model", "prompt": "professional 3d model {prompt} . octane render, highly detailed, volumetric, dramatic lighting", "negative_prompt": "ugly, deformed, noisy, low poly, blurry, painting"},
]
# Create dictionary of styles
styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
STYLE_NAMES = list(styles.keys())
DEFAULT_STYLE_NAME = "(No style)"
NUM_IMAGES_PER_PROMPT = 1
# Function to apply style and modify prompt based on selected colors
def apply_style(style_name: str, positive: str, color_selections: dict) -> Tuple[str, str]:
p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
color_prompt = ""
# Aggregate verbs and adjectives from selected colors based on their ratios
for color, attributes in color_selections.items():
if attributes["selected"]:
verbs = random.sample(color_attributes[color]["verbs"], min(3, len(color_attributes[color]["verbs"])))
adjectives = random.sample(color_attributes[color]["adjectives"], min(3, len(color_attributes[color]["adjectives"])))
color_prompt += " ".join(verbs) + " " + " ".join(adjectives) + " "
# Form the final prompt
final_prompt = p.replace("{prompt}", positive + " " + color_prompt.strip())
return final_prompt, n
# Check if CUDA is available and set up the pipeline
if torch.cuda.is_available():
pipe = PixArtAlphaPipeline.from_pretrained(
"PixArt-alpha/PixArt-LCM-XL-2-1024-MS",
torch_dtype=torch.float16,
use_safetensors=True,
)
if os.getenv('CONSISTENCY_DECODER', False):
print("Using DALL-E 3 Consistency Decoder")
pipe.vae = ConsistencyDecoderVAE.from_pretrained("openai/consistency-decoder", torch_dtype=torch.float16)
if ENABLE_CPU_OFFLOAD:
pipe.enable_model_cpu_offload()
else:
pipe.to(device)
print("Loaded on Device!")
if USE_TORCH_COMPILE:
pipe.transformer = torch.compile(pipe.transformer, mode="reduce-overhead", fullgraph=True)
print("Model Compiled!")
# Function to save image
def save_image(img):
unique_name = str(uuid.uuid4()) + ".png"
img.save(unique_name)
return unique_name
# Function to randomize seed if needed
def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
if randomize_seed:
seed = random.randint(0, MAX_SEED)
return seed
# Main function to generate images based on user inputs
@spaces.GPU(duration=30)
def generate(
prompt: str,
negative_prompt: str = "",
style: str = DEFAULT_STYLE_NAME,
use_negative_prompt: bool = False,
seed: int = 0,
width: int = 1024,
height: int = 1024,
inference_steps: int = 4,
randomize_seed: bool = False,
use_resolution_binning: bool = True,
purple_selected: bool = False,
purple_ratio: float = 0.0,
green_selected: bool = False,
green_ratio: float = 0.0,
maroon_selected: bool = False,
maroon_ratio: float = 0.0,
orange_selected: bool = False,
orange_ratio: float = 0.0,
yellow_selected: bool = False,
yellow_ratio: float = 0.0,
red_selected: bool = False,
red_ratio: float = 0.0,
blue_selected: bool = False,
blue_ratio: float = 0.0,
pink_selected: bool = False,
pink_ratio: float = 0.0,
silver_selected: bool = False,
silver_ratio: float = 0.0,
beige_selected: bool = False,
beige_ratio: float = 0.0,
):
seed = int(randomize_seed_fn(seed, randomize_seed))
generator = torch.Generator().manual_seed(seed)
if not use_negative_prompt:
negative_prompt = None # type: ignore
# Process color selections and their ratios
color_selections = {
"Purple": {"selected": purple_selected, "ratio": purple_ratio},
"Green": {"selected": green_selected, "ratio": green_ratio},
"Maroon": {"selected": maroon_selected, "ratio": maroon_ratio},
"Orange": {"selected": orange_selected, "ratio": orange_ratio},
"Yellow": {"selected": yellow_selected, "ratio": yellow_ratio},
"Red": {"selected": red_selected, "ratio": red_ratio},
"Blue": {"selected": blue_selected, "ratio": blue_ratio},
"Pink": {"selected": pink_selected, "ratio": pink_ratio},
"Silver": {"selected": silver_selected, "ratio": silver_ratio},
"Beige": {"selected": beige_selected, "ratio": beige_ratio},
}
# Apply style and modify prompt based on color selections
prompt, negative_prompt = apply_style(style, prompt, color_selections)
# Generate images
try:
images = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
width=width,
height=height,
guidance_scale=0,
num_inference_steps=inference_steps,
generator=generator,
num_images_per_prompt=NUM_IMAGES_PER_PROMPT,
use_resolution_binning=use_resolution_binning,
output_type="pil",
).images
except Exception as e:
print(f"Error during image generation: {e}")
return [], seed
image_paths = [save_image(img) for img in images]
print(image_paths)
return image_paths, seed
# Example prompts
examples = [
"A Monkey with a happy face in the Sahara desert.",
"Eiffel Tower was Made up of ICE.",
"Color photo of a corgi made of transparent glass, standing on the riverside in Yosemite National Park.",
"A close-up photo of a woman. She wore a blue coat with a gray dress underneath and has blue eyes.",
"A litter of golden retriever puppies playing in the snow. Their heads pop out of the snow, covered in.",
"an astronaut sitting in a diner, eating fries, cinematic, analog film",
]
# Set up the Gradio interface
with gr.Blocks() as demo:
gr.Markdown(DESCRIPTION)
with gr.Row(equal_height=False):
with gr.Group():
with gr.Row():
prompt = gr.Text(
label="Prompt",
show_label=False,
max_lines=1,
placeholder="Enter your prompt",
container=False,
)
run_button = gr.Button("Run", scale=0)
result = gr.Gallery(label="Result", columns=NUM_IMAGES_PER_PROMPT, show_label=False)
# Color selection and ratio configuration in the UI
with gr.Accordion("Color Influences", open=False):
with gr.Group():
color_checkboxes = {}
color_sliders = {}
for color in color_attributes:
with gr.Row():
color_checkboxes[color] = gr.Checkbox(label=f"{color} Selected", value=False)
color_sliders[color] = gr.Slider(label=f"{color} Influence Ratio", minimum=0, maximum=1, step=0.01, value=0.0)
with gr.Accordion("Advanced options", open=False):
with gr.Group():
with gr.Row():
use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=False, visible=True)
negative_prompt = gr.Text(
label="Negative prompt",
max_lines=1,
placeholder="Enter a negative prompt",
visible=True,
)
style_selection = gr.Radio(
choices=STYLE_NAMES,
value=DEFAULT_STYLE_NAME,
label="Image Style",
show_label=True,
container=True,
interactive=True,
)
seed = gr.Slider(
label="Seed",
minimum=0,
maximum=MAX_SEED,
step=1,
value=0,
)
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
with gr.Row(visible=True):
width = gr.Slider(
label="Width",
minimum=256,
maximum=MAX_IMAGE_SIZE,
step=32,
value=1024,
)
height = gr.Slider(
label="Height",
minimum=256,
maximum=MAX_IMAGE_SIZE,
step=32,
value=1024,
)
with gr.Row():
inference_steps = gr.Slider(
label="Steps",
minimum=4,
maximum=20,
step=1,
value=4,
)
gr.Examples(
examples=examples,
inputs=prompt,
outputs=[result, seed],
fn=generate,
cache_examples=CACHE_EXAMPLES,
)
# Dynamic updates based on user interactions
use_negative_prompt.change(
fn=lambda x: gr.update(visible=x),
inputs=use_negative_prompt,
outputs=negative_prompt,
api_name=False,
)
gr.on(
triggers=[
prompt.submit,
negative_prompt.submit,
run_button.click,
],
fn=generate,
inputs=[
prompt,
negative_prompt,
style_selection,
use_negative_prompt,
seed,
width,
height,
inference_steps,
randomize_seed,
# Color configurations
color_checkboxes["Purple"],
color_sliders["Purple"],
color_checkboxes["Green"],
color_sliders["Green"],
color_checkboxes["Maroon"],
color_sliders["Maroon"],
color_checkboxes["Orange"],
color_sliders["Orange"],
color_checkboxes["Yellow"],
color_sliders["Yellow"],
color_checkboxes["Red"],
color_sliders["Red"],
color_checkboxes["Blue"],
color_sliders["Blue"],
color_checkboxes["Pink"],
color_sliders["Pink"],
color_checkboxes["Silver"],
color_sliders["Silver"],
color_checkboxes["Beige"],
color_sliders["Beige"],
],
outputs=[result, seed],
api_name="run",
)
# Launch the Gradio app
if __name__ == "__main__":
demo.queue(max_size=20).launch()
# Uncomment the next line to launch the server with specific options
# demo.queue(max_size=20).launch(server_name="0.0.0.0", server_port=11900, debug=True)