Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import torch | |
| import random | |
| import os | |
| import time | |
| from PIL import Image | |
| from deep_translator import GoogleTranslator | |
| from diffusers import DiffusionPipeline | |
| from huggingface_hub import hf_hub_download | |
| # Project by Nymbo with LoRA integration | |
| # Model and LoRA configuration | |
| BASE_MODEL = "black-forest-labs/FLUX.1-dev" | |
| LORA_REPO = "burhansyam/uncen" | |
| LORA_WEIGHTS_NAME = "uncen.safetensors" # Adjust if different | |
| torch_dtype = torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16 | |
| # Initialize the pipeline with LoRA | |
| def init_pipeline(): | |
| pipe = DiffusionPipeline.from_pretrained( | |
| BASE_MODEL, | |
| torch_dtype=torch_dtype | |
| ) | |
| # Load LoRA weights | |
| pipe.load_lora_weights( | |
| hf_hub_download(repo_id=LORA_REPO, filename=LORA_WEIGHTS_NAME), | |
| adapter_name="uncen" | |
| ) | |
| # Enable model offloading if needed | |
| if torch.cuda.is_available(): | |
| pipe.to("cuda") | |
| pipe.enable_xformers_memory_efficient_attention() | |
| return pipe | |
| pipe = init_pipeline() | |
| def convert_to_png(image): | |
| """Convert any image format to true PNG format""" | |
| png_buffer = io.BytesIO() | |
| if image.mode == 'RGBA': | |
| image.save(png_buffer, format='PNG', optimize=True) | |
| else: | |
| if image.mode != 'RGB': | |
| image = image.convert('RGB') | |
| image.save(png_buffer, format='PNG', optimize=True) | |
| png_buffer.seek(0) | |
| return Image.open(png_buffer) | |
| def query(prompt, is_negative=False, steps=35, cfg_scale=7, sampler="DPM++ 2M Karras", | |
| seed=-1, strength=0.7, width=1024, height=1024): | |
| if not prompt: | |
| return None | |
| key = random.randint(0, 999) | |
| # Translate prompt | |
| try: | |
| prompt = GoogleTranslator(source='id', target='en').translate(prompt) | |
| print(f'\033[1mGeneration {key} translation:\033[0m {prompt}') | |
| prompt = f"{prompt} | ultra detail, ultra elaboration, ultra quality, perfect." | |
| except Exception as e: | |
| print(f"Translation error: {e}") | |
| print(f'\033[1mGeneration {key}:\033[0m {prompt}') | |
| # Set random seed if not specified | |
| generator = None | |
| if seed != -1: | |
| generator = torch.Generator(device="cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed) | |
| else: | |
| seed = random.randint(1, 1000000000) | |
| generator = torch.Generator(device="cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed) | |
| # Map sampler names to Diffusers scheduler names | |
| sampler_map = { | |
| "DPM++ 2M Karras": "dpmsolver++", | |
| "DPM++ SDE Karras": "dpmsolver++", | |
| "Euler": "euler", | |
| "Euler a": "euler_a", | |
| "Heun": "heun", | |
| "DDIM": "ddim" | |
| } | |
| try: | |
| # Generate image with LoRA | |
| image = pipe( | |
| prompt=prompt, | |
| negative_prompt=is_negative if is_negative else None, | |
| num_inference_steps=steps, | |
| guidance_scale=cfg_scale, | |
| generator=generator, | |
| strength=strength, | |
| width=width, | |
| height=height, | |
| cross_attention_kwargs={"scale": 0.8}, # LoRA strength adjustment | |
| ).images[0] | |
| png_img = convert_to_png(image) | |
| print(f'\033[1mGeneration {key} completed as PNG!\033[0m') | |
| return png_img | |
| except Exception as e: | |
| print(f"Generation error: {e}") | |
| raise gr.Error(f"Image generation failed: {str(e)}") | |
| # Light theme CSS (same as before) | |
| css = """ | |
| #app-container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| background: #ffffff; | |
| } | |
| #prompt-text-input, #negative-prompt-text-input { | |
| font-size: 14px; | |
| background: #f9f9f9; | |
| } | |
| #gallery { | |
| min-height: 512px; | |
| background: #ffffff; | |
| border: 1px solid #e0e0e0; | |
| } | |
| #gen-button { | |
| margin: 10px 0; | |
| background: #4CAF50; | |
| color: white; | |
| } | |
| .accordion { | |
| background: #f5f5f5; | |
| border: 1px solid #e0e0e0; | |
| } | |
| h1 { | |
| color: #333333; | |
| } | |
| """ | |
| with gr.Blocks(theme=gr.themes.Default(primary_hue="green"), css=css) as app: | |
| gr.HTML("<center><h1>FLUX.1-Dev with LoRA (PNG Output)</h1></center>") | |
| with gr.Column(elem_id="app-container"): | |
| with gr.Row(): | |
| with gr.Column(elem_id="prompt-container"): | |
| with gr.Row(): | |
| text_prompt = gr.Textbox( | |
| label="Prompt", | |
| placeholder="Masukkan prompt dalam Bahasa Indonesia", | |
| lines=2, | |
| elem_id="prompt-text-input" | |
| ) | |
| with gr.Accordion("Advanced Settings", open=False): | |
| negative_prompt = gr.Textbox( | |
| label="Negative Prompt", | |
| value="(deformed, distorted, disfigured), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation", | |
| lines=3 | |
| ) | |
| with gr.Row(): | |
| width = gr.Slider(1024, label="Width", minimum=512, maximum=1536, step=64) | |
| height = gr.Slider(1024, label="Height", minimum=512, maximum=1536, step=64) | |
| with gr.Row(): | |
| steps = gr.Slider(35, label="Steps", minimum=10, maximum=100, step=1) | |
| cfg = gr.Slider(7.0, label="CFG Scale", minimum=1.0, maximum=20.0, step=0.5) | |
| with gr.Row(): | |
| strength = gr.Slider(0.7, label="Strength", minimum=0.1, maximum=1.0, step=0.01) | |
| seed = gr.Number(-1, label="Seed (-1 for random)") | |
| method = gr.Radio( | |
| ["DPM++ 2M Karras", "DPM++ SDE Karras", "Euler", "Euler a", "Heun", "DDIM"], | |
| value="DPM++ 2M Karras", | |
| label="Sampling Method" | |
| ) | |
| generate_btn = gr.Button("Generate Image", variant="primary") | |
| with gr.Row(): | |
| output_image = gr.Image( | |
| type="pil", | |
| label="Generated PNG Image", | |
| format="png", | |
| elem_id="gallery" | |
| ) | |
| generate_btn.click( | |
| fn=query, | |
| inputs=[text_prompt, negative_prompt, steps, cfg, method, seed, strength, width, height], | |
| outputs=output_image | |
| ) | |
| app.launch(server_name="0.0.0.0", server_port=7860, share=True) |