import spaces import os import json import time import torch #a from PIL import Image from tqdm import tqdm import gradio as gr import uuid from datetime import datetime from typing import List, Dict, Optional from safetensors.torch import save_file from src.pipeline import FluxPipeline from src.transformer_flux import FluxTransformer2DModel from src.lora_helper import set_single_lora, set_multi_lora, unset_lora # Initialize the image processor base_path = "black-forest-labs/FLUX.1-dev" lora_base_path = "./models" pipe = FluxPipeline.from_pretrained(base_path, torch_dtype=torch.bfloat16) transformer = FluxTransformer2DModel.from_pretrained(base_path, subfolder="transformer", torch_dtype=torch.bfloat16) pipe.transformer = transformer # Gallery storage GALLERY_DIR = "gallery" os.makedirs(GALLERY_DIR, exist_ok=True) GALLERY_DB = os.path.join(GALLERY_DIR, "gallery_db.json") # Initialize gallery database if not os.path.exists(GALLERY_DB): with open(GALLERY_DB, "w") as f: json.dump({"images": []}, f) def clear_cache(transformer): for name, attn_processor in transformer.attn_processors.items(): attn_processor.bank_kv.clear() def add_to_gallery(image: Image.Image, prompt: str, control_type: str) -> str: """Save image to gallery and return its path""" image_id = str(uuid.uuid4()) filename = f"{image_id}.png" filepath = os.path.join(GALLERY_DIR, filename) image.save(filepath) # Update gallery database with open(GALLERY_DB, "r") as f: db = json.load(f) db["images"].append({ "id": image_id, "filename": filename, "prompt": prompt, "control_type": control_type, "created_at": datetime.now().isoformat() }) with open(GALLERY_DB, "w") as f: json.dump(db, f, indent=2) return filepath def get_gallery_images() -> List[Dict]: """Get all gallery images from database""" try: with open(GALLERY_DB, "r") as f: db = json.load(f) return db["images"] except: return [] def single_condition_generate_image(prompt, spatial_img, height, width, seed, control_type, progress=gr.Progress()): # Set the control type if control_type == "Ghibli": lora_path = os.path.join(lora_base_path, "Ghibli.safetensors") set_single_lora(pipe.transformer, lora_path, lora_weights=[1], cond_size=512, device="cpu") # Process the image spatial_imgs = [spatial_img] if spatial_img else [] progress(0, desc="Starting generation...") image = pipe( prompt, height=int(height), width=int(width), guidance_scale=3.5, num_inference_steps=15, max_sequence_length=512, generator=torch.Generator("cpu").manual_seed(seed), subject_images=[], spatial_images=spatial_imgs, cond_size=512, ).images[0] # Save to gallery image_path = add_to_gallery(image, prompt, control_type) clear_cache(pipe.transformer) return image # Define the Gradio interface components control_types = ["Ghibli"] # Example data single_examples = [ ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/00.png"), 512, 512, 5, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/02.png"), 512, 512, 42, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/03.png"), 512, 512, 1, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/04.png"), 512, 512, 1, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/06.png"), 512, 512, 1, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/07.png"), 512, 512, 1, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/08.png"), 512, 512, 1, "Ghibli"], ["Ghibli Studio style, Charming hand-drawn anime-style illustration", Image.open("./test_imgs/09.png"), 512, 512, 1, "Ghibli"], ] # Create the Gradio Blocks interface with gr.Blocks() as demo: gr.Markdown("# Ghibli Studio Control Image Generation with EasyControl") gr.Markdown("The model is trained on **only 100 real Asian faces** paired with **GPT-4o-generated Ghibli-style counterparts**, and it preserves facial features while applying the iconic anime aesthetic.") gr.Markdown("Generate images using EasyControl with Ghibli control LoRAs.(Running on CPU due to free tier limitations; expect slower performance and lower resolution.)") gr.Markdown("**[Attention!!]**:The recommended prompts for using Ghibli Control LoRA should include the trigger words: `Ghibli Studio style, Charming hand-drawn anime-style illustration`") gr.Markdown("😊😊If you like this demo, please give us a star (github: [EasyControl](https://github.com/Xiaojiu-z/EasyControl))") with gr.Tab("Ghibli Condition Generation"): with gr.Row(): with gr.Column(): prompt = gr.Textbox(label="Prompt", value="Ghibli Studio style, Charming hand-drawn anime-style illustration") spatial_img = gr.Image(label="Ghibli Image", type="pil") height = gr.Slider(minimum=256, maximum=512, step=64, label="Height", value=512) width = gr.Slider(minimum=256, maximum=512, step=64, label="Width", value=512) seed = gr.Number(label="Seed", value=42) control_type = gr.Dropdown(choices=control_types, label="Control Type") single_generate_btn = gr.Button("Generate Image") with gr.Column(): single_output_image = gr.Image(label="Generated Image") gr.Examples( examples=single_examples, inputs=[prompt, spatial_img, height, width, seed, control_type], outputs=single_output_image, fn=single_condition_generate_image, cache_examples=False, label="Single Condition Examples" ) with gr.Tab("Gallery"): gallery = gr.Gallery( label="Generated Images", show_label=True, elem_id="gallery" ) refresh_btn = gr.Button("Refresh Gallery") def load_gallery(): images = get_gallery_images() return [os.path.join(GALLERY_DIR, img["filename"]) for img in images] refresh_btn.click( fn=load_gallery, outputs=gallery ) # Load gallery on page load demo.load( fn=load_gallery, outputs=gallery ) single_generate_btn.click( single_condition_generate_image, inputs=[prompt, spatial_img, height, width, seed, control_type], outputs=single_output_image, concurrency_limit=1 # Process one at a time ) # Launch the Gradio app demo.queue().launch()