Anime / app.py
Astridkraft's picture
Update app.py
56d62f2 verified
Raw
History Blame Contribute Delete
5.74 kB
import torch
import gradio as gr
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
from peft import PeftModel
from PIL import Image, ImageEnhance
# --- Globale Variable ---
pipe_txt2img = None
loaded_adapters = []
def enhance_face_simple(image):
try:
if not isinstance(image, Image.Image):
image = Image.fromarray(image)
enhancer = ImageEnhance.Sharpness(image)
image = enhancer.enhance(1.3)
enhancer = ImageEnhance.Contrast(image)
image = enhancer.enhance(1.1)
return image
except Exception as e:
print(f"⚠️ Bildverbesserung fehlgeschlagen: {e}")
return image
def load_pipeline():
global pipe_txt2img, loaded_adapters
if pipe_txt2img is None:
print("Loading Text-to-Image model...")
device = "cuda" if torch.cuda.is_available() else "cpu"
pipe_txt2img = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float32, # CPU benötigt float32
use_safetensors=True,
safety_checker=None,
requires_safety_checker=False,
).to(device)
# Scheduler auf schnelleren Modus umstellen (CPU-optimiert)
pipe_txt2img.scheduler = DPMSolverMultistepScheduler.from_config(
pipe_txt2img.scheduler.config,
algorithm_type="dpmsolver++",
use_karras_sigmas=True,
timestep_spacing="linspace"
)
# Attention-Slicing deaktivieren (kann auf CPU langsamer sein)
# pipe_txt2img.enable_attention_slicing()
# Character-LoRA via PEFT laden
try:
pipe_txt2img.unet = PeftModel.from_pretrained(
pipe_txt2img.unet,
"Shion1124/anime-character-lora_v1.5",
adapter_name="character"
)
loaded_adapters.append("character")
print("✅ Character-LoRA (PEFT) geladen")
except Exception as e:
print(f"❌ Character-LoRA Fehler: {e}")
print(f"✅ Pipeline bereit. Geladene Adapter: {loaded_adapters}")
return pipe_txt2img
def generate_image(
prompt,
negative_prompt,
steps,
guidance,
width,
height,
char_weight,
enhance_enabled
):
pipe = load_pipeline()
try:
if hasattr(pipe_txt2img.unet, "set_adapter"):
pipe_txt2img.unet.set_adapter("character", char_weight)
else:
pipe_txt2img.set_adapters(["character"], [char_weight])
except Exception as e:
print(f"⚠️ Adapter-Gewicht nicht setzbar: {e}")
result = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=int(steps),
guidance_scale=guidance,
width=int(width),
height=int(height)
)
image = result.images[0]
if enhance_enabled:
image = enhance_face_simple(image)
return image
# --- UI ---
def main_ui():
with gr.Blocks(title="Anime Generator (CPU-optimiert)") as demo:
gr.Markdown("## ✨ Anime-Figuren mit Character-LoRA (CPU-Modus)")
gr.Markdown("**CPU-optimiert:** Weniger Schritte + schnellerer Scheduler")
with gr.Row():
with gr.Column(scale=1):
prompt = gr.Textbox(
label="Prompt",
value="masterpiece, best quality, anime art style, 1girl, solo, close-up, portrait, beautiful detailed face, perfect eyes, sharp focus, high contrast, intricate details, long silver hair, blue eyes, white sundress, straw hat, standing on meadow, cherry blossoms, mountains, sunset, golden clouds, dramatic lighting, highly detailed, 8k",
lines=4
)
negative_prompt = gr.Textbox(
label="Negative Prompt",
value="lowres, bad anatomy, bad hands, text, error, missing fingers, cropped, worst quality, low quality, blurry, deformed, ugly, bad face, distorted face, blurry face, bad eyes, asymmetric eyes, long neck, extra limbs, mutated hands, disfigured, out of frame, bad proportions",
lines=3
)
with gr.Row():
steps = gr.Slider(10, 30, value=15, step=1, label="Schritte (CPU: 15 empfohlen)")
guidance = gr.Slider(5, 12, value=7.5, step=0.5, label="Guidance Scale")
with gr.Row():
width = gr.Dropdown([512, 640], value=512, label="Breite (kleiner = schneller)")
height = gr.Dropdown([512, 640], value=512, label="Höhe (kleiner = schneller)")
gr.Markdown("### LoRA-Gewicht & Bildverbesserung")
with gr.Row():
char_weight = gr.Slider(0, 1.2, value=0.85, step=0.05, label="Character-LoRA")
enhance = gr.Checkbox(value=True, label="Bild verbessern (Schärfe + Kontrast)")
generate_btn = gr.Button("🚀 Bild generieren", variant="primary")
with gr.Column(scale=1):
output_image = gr.Image(label="Generiertes Bild", type="pil")
generate_btn.click(
fn=generate_image,
inputs=[prompt, negative_prompt, steps, guidance, width, height, char_weight, enhance],
outputs=output_image
)
return demo
# --- Launch ---
demo = main_ui()
demo.queue()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
max_file_size="15MB",
show_error=True,
share=False,
debug=False
)