Ghibli-Maker / app.py
ar08's picture
Update app.py
30023e3 verified
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()