|
import gradio as gr |
|
import torch |
|
from diffusers import FluxFillPipeline |
|
from diffusers.utils import load_image |
|
from PIL import Image, ImageDraw |
|
import numpy as np |
|
import spaces |
|
import requests |
|
|
|
|
|
pipe = FluxFillPipeline.from_pretrained( |
|
"black-forest-labs/FLUX.1-Fill-dev", |
|
torch_dtype=torch.bfloat16 |
|
).to("cuda") |
|
|
|
|
|
@spaces.GPU |
|
def translate_albanian_to_english(text): |
|
if not text.strip(): |
|
return "" |
|
for attempt in range(2): |
|
try: |
|
response = requests.post( |
|
"https://hal1993-mdftranslation1234567890abcdef1234567890-fc073a6.hf.space/v1/translate", |
|
json={"from_language": "sq", "to_language": "en", "input_text": text}, |
|
headers={"accept": "application/json", "Content-Type": "application/json"}, |
|
timeout=5 |
|
) |
|
response.raise_for_status() |
|
translated = response.json().get("translate", "") |
|
return translated |
|
except Exception as e: |
|
if attempt == 1: |
|
raise gr.Error(f"Përkthimi dështoi: {str(e)}") |
|
raise gr.Error("Përkthimi dështoi. Ju lutem provoni përsëri.") |
|
|
|
|
|
def update_aspect_ratio(ratio): |
|
if ratio == "1:1": |
|
return 640, 640 |
|
elif ratio == "9:16": |
|
width = 512 |
|
height = int(round(512 * 16 / 9 / 8)) * 8 |
|
return width, height |
|
elif ratio == "16:9": |
|
width = int(round(512 * 16 / 9 / 8)) * 8 |
|
height = 512 |
|
return width, height |
|
return 640, 640 |
|
|
|
|
|
def can_expand(source_width, source_height, target_width, target_height, alignment): |
|
if alignment in ("Left", "Right") and source_width >= target_width: |
|
return False |
|
if alignment in ("Top", "Bottom") and source_height >= target_height: |
|
return False |
|
return True |
|
|
|
def prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, alignment): |
|
if image is None: |
|
raise gr.Error("Ju lutem ngarkoni një imazh.") |
|
|
|
target_size = (width, height) |
|
|
|
|
|
scale_factor = min(target_size[0] / image.width, target_size[1] / image.height) |
|
new_width = int(image.width * scale_factor) |
|
new_height = int(image.height * scale_factor) |
|
source = image.resize((new_width, new_height), Image.LANCZOS) |
|
|
|
|
|
resize_map = { |
|
"E Plotë": 100, |
|
"75%": 75, |
|
"50%": 50, |
|
"33%": 33, |
|
"25%": 25 |
|
} |
|
resize_percentage = resize_map.get(resize_option, 75) |
|
|
|
|
|
resize_factor = resize_percentage / 100 |
|
new_width = int(source.width * resize_factor) |
|
new_height = int(source.height * resize_factor) |
|
new_width = max(new_width, 64) |
|
new_height = max(new_height, 64) |
|
source = source.resize((new_width, new_height), Image.LANCZOS) |
|
|
|
|
|
overlap_x = int(new_width * (overlap_percentage / 100)) |
|
overlap_y = int(new_height * (overlap_percentage / 100)) |
|
overlap_x = max(overlap_x, 1) |
|
overlap_y = max(overlap_y, 1) |
|
|
|
|
|
if alignment == "Middle": |
|
margin_x = (target_size[0] - new_width) // 2 |
|
margin_y = (target_size[1] - new_height) // 2 |
|
elif alignment == "Left": |
|
margin_x = 0 |
|
margin_y = (target_size[1] - new_height) // 2 |
|
elif alignment == "Right": |
|
margin_x = target_size[0] - new_width |
|
margin_y = (target_size[1] - new_height) // 2 |
|
elif alignment == "Top": |
|
margin_x = (target_size[0] - new_width) // 2 |
|
margin_y = 0 |
|
elif alignment == "Bottom": |
|
margin_x = (target_size[0] - new_width) // 2 |
|
margin_y = target_size[1] - new_height |
|
|
|
margin_x = max(0, min(margin_x, target_size[0] - new_width)) |
|
margin_y = max(0, min(margin_y, target_size[1] - new_height)) |
|
|
|
|
|
background = Image.new('RGB', target_size, (255, 255, 255)) |
|
background.paste(source, (margin_x, margin_y)) |
|
|
|
|
|
mask = Image.new('L', target_size, 255) |
|
mask_draw = ImageDraw.Draw(mask) |
|
white_gaps_patch = 2 |
|
left_overlap = margin_x + overlap_x |
|
right_overlap = margin_x + new_width - overlap_x |
|
top_overlap = margin_y + overlap_y |
|
bottom_overlap = margin_y + new_height - overlap_y |
|
|
|
if alignment == "Left": |
|
left_overlap = margin_x |
|
elif alignment == "Right": |
|
right_overlap = margin_x + new_width |
|
elif alignment == "Top": |
|
top_overlap = margin_y |
|
elif alignment == "Bottom": |
|
bottom_overlap = margin_y + new_height |
|
|
|
mask_draw.rectangle([ |
|
(left_overlap, top_overlap), |
|
(right_overlap, bottom_overlap) |
|
], fill=0) |
|
|
|
return background, mask |
|
|
|
@spaces.GPU |
|
def inpaint(image, width, height, overlap_percentage, num_inference_steps, resize_option, prompt, progress=gr.Progress(track_tqdm=True)): |
|
|
|
final_prompt = translate_albanian_to_english(prompt.strip()) if prompt.strip() else "" |
|
|
|
|
|
background, mask = prepare_image_and_mask( |
|
image, width, height, overlap_percentage, resize_option, alignment="Middle" |
|
) |
|
|
|
|
|
if not can_expand(background.width, background.height, width, height, "Middle"): |
|
alignment = "Middle" |
|
|
|
|
|
cnet_image = background.copy() |
|
cnet_image.paste(0, (0, 0), mask) |
|
|
|
|
|
try: |
|
result = pipe( |
|
prompt=final_prompt, |
|
height=height, |
|
width=width, |
|
image=cnet_image, |
|
mask_image=mask, |
|
num_inference_steps=num_inference_steps, |
|
guidance_scale=50, |
|
).images[0] |
|
except Exception as e: |
|
raise gr.Error(f"Gabim gjatë gjenerimit të imazhit: {str(e)}") |
|
|
|
|
|
result = result.convert("RGBA") |
|
cnet_image.paste(result, (0, 0), mask) |
|
|
|
return np.array(cnet_image) |
|
|
|
|
|
def create_demo(): |
|
with gr.Blocks() as demo: |
|
|
|
gr.HTML(""" |
|
<style> |
|
body::before { |
|
content: ""; |
|
display: block; |
|
height: 320px; |
|
background-color: var(--body-background-fill); |
|
} |
|
button[aria-label="Fullscreen"], button[aria-label="Fullscreen"]:hover { |
|
display: none !important; |
|
visibility: hidden !important; |
|
opacity: 0 !important; |
|
pointer-events: none !important; |
|
} |
|
button[aria-label="Share"], button[aria-label="Share"]:hover { |
|
display: none !important; |
|
} |
|
button[aria-label="Download"] { |
|
transform: scale(3); |
|
transform-origin: top right; |
|
margin: 0 !important; |
|
padding: 6px !important; |
|
} |
|
.constrained-container { |
|
max-width: 600px; /* Limits container width */ |
|
margin: 0 auto; /* Centers the container */ |
|
} |
|
</style> |
|
""") |
|
|
|
gr.Markdown("# Zgjeroni Imazhin") |
|
gr.Markdown("Zgjeroni imazhin duke plotësuar sfondin bazuar në përshkrimin e dhënë") |
|
|
|
with gr.Row(): |
|
with gr.Column(elem_classes="constrained-container"): |
|
input_image = gr.Image(sources='upload', type="pil", label="Imazhi i Ngarkuar", height=480, width=480) |
|
prompt = gr.Textbox(label="Përshkrimi", placeholder="Shkruani përshkrimin këtu (opsionale)") |
|
aspect_ratio = gr.Radio(choices=["9:16", "1:1", "16:9"], value="1:1", label="Raporti i Aspektit") |
|
resize_option = gr.Radio( |
|
choices=["E Plotë", "75%", "50%", "33%", "25%"], |
|
value="75%", |
|
label="Madhësia e Imazhit të Hyrjes", |
|
info="Zgjidhni sa i madh të jetë imazhi i hyrjes në kanavacën përfundimtare" |
|
) |
|
generate_button = gr.Button(value="Gjenero") |
|
result_image = gr.Image(label="Rezultati", type="numpy", height=480, width=480, elem_classes="constrained-container") |
|
|
|
width_slider = gr.Slider(label="Gjerësia e Synuar", minimum=256, maximum=1536, value=640, step=8, visible=False) |
|
height_slider = gr.Slider(label="Lartësia e Synuar", minimum=256, maximum=1536, value=640, step=8, visible=False) |
|
overlap_percentage = gr.Slider(label="Përqindja e Mbivendosjes", minimum=1, maximum=50, value=10, step=1, visible=False) |
|
num_inference_steps = gr.Slider(label="Hapat", minimum=2, maximum=50, value=28, step=1, visible=False) |
|
|
|
|
|
aspect_ratio.change( |
|
fn=update_aspect_ratio, |
|
inputs=[aspect_ratio], |
|
outputs=[width_slider, height_slider] |
|
) |
|
|
|
|
|
inputs = [ |
|
input_image, width_slider, height_slider, overlap_percentage, num_inference_steps, |
|
resize_option, prompt |
|
] |
|
generate_button.click( |
|
fn=inpaint, |
|
inputs=inputs, |
|
outputs=[result_image] |
|
) |
|
|
|
return demo |
|
|
|
if __name__ == "__main__": |
|
print(f"Gradio version: {gr.__version__}") |
|
app = create_demo() |
|
app.queue(max_size=12).launch(server_name='0.0.0.0') |