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) |