Spaces:
Sleeping
Sleeping
| 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 | |
| ) | |