Spaces:
Running
on
Zero
Running
on
Zero
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 | |
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) |