|
import os |
|
import base64 |
|
import numpy as np |
|
from PIL import Image, ImageChops, ImageDraw |
|
|
|
import io |
|
import requests |
|
import replicate |
|
import gradio as gr |
|
|
|
from dotenv import load_dotenv, find_dotenv |
|
|
|
|
|
dotenv_path = find_dotenv() |
|
load_dotenv(dotenv_path) |
|
REPLICATE_API_TOKEN = os.getenv('REPLICATE_API_TOKEN') |
|
|
|
def generate_sd3_image(prompt): |
|
prompt = "texture sample zoomed in of " + prompt + ", perfect, seamless pattern" |
|
|
|
output = replicate.run( |
|
"stability-ai/stable-diffusion-3", |
|
input={ |
|
"cfg": 3.5, |
|
"steps": 28, |
|
"prompt": prompt, |
|
"aspect_ratio": "1:1", |
|
"output_format": "jpg", |
|
"output_quality": 80, |
|
"negative_prompt": "", |
|
"prompt_strength": 0.85 |
|
} |
|
) |
|
|
|
response = requests.get(output[0]) |
|
|
|
return Image.open(io.BytesIO(response.content)) |
|
|
|
def generate_pattern(image, prompt): |
|
raise gr.Error(header) |
|
if image is not None: |
|
|
|
starter_image_pil = Image.fromarray(image.astype('uint8')) |
|
|
|
|
|
if starter_image_pil.size[0] > 768 or starter_image_pil.size[1] > 768: |
|
|
|
if starter_image_pil.size[0] > starter_image_pil.size[1]: |
|
|
|
new_width = 768 |
|
new_height = int((768 / starter_image_pil.size[0]) * starter_image_pil.size[1]) |
|
else: |
|
|
|
new_height = 768 |
|
new_width = int((768 / starter_image_pil.size[1]) * starter_image_pil.size[0]) |
|
|
|
|
|
starter_image_pil = starter_image_pil.resize((new_width, new_height), Image.LANCZOS) |
|
else: |
|
starter_image_pil = generate_sd3_image(prompt) |
|
|
|
|
|
|
|
width, height = starter_image_pil.size |
|
horizontal_shift = width // 2 |
|
vertical_shift = height // 2 |
|
|
|
transformed_image_pil = ImageChops.offset(starter_image_pil, horizontal_shift, vertical_shift) |
|
|
|
|
|
cross_image_pil = Image.new('RGB', (width, height), 'black') |
|
draw = ImageDraw.Draw(cross_image_pil) |
|
line_width = 75 |
|
|
|
draw.rectangle([(width // 2 - line_width // 2, 0), (width // 2 + line_width // 2, height)], fill='white') |
|
|
|
draw.rectangle([(0, height // 2 - line_width // 2), (width, height // 2 + line_width // 2)], fill='white') |
|
|
|
buffered = io.BytesIO() |
|
transformed_image_pil.save(buffered, format="JPEG") |
|
image_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8') |
|
|
|
buffered = io.BytesIO() |
|
cross_image_pil.save(buffered, format="JPEG") |
|
cross_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8') |
|
|
|
input = { |
|
"prompt": prompt + ", seamless pattern", |
|
"negative_prompt": "worst quality, low quality, cartoons, sketch, ugly, lowres", |
|
"image": "data:image/jpeg;base64," + image_base64, |
|
"mask": "data:image/jpeg;base64," + cross_base64, |
|
"num_inference_steps": 25, |
|
"num_outputs": 3, |
|
} |
|
|
|
output = replicate.run( |
|
"lucataco/sdxl-inpainting:a5b13068cc81a89a4fbeefeccc774869fcb34df4dbc92c1555e0f2771d49dde7", |
|
input=input |
|
) |
|
|
|
images = [] |
|
for i in range(min(len(output), 3)): |
|
image_url = output[i] |
|
response = requests.get(image_url) |
|
images.append(Image.open(io.BytesIO(response.content))) |
|
|
|
|
|
while len(images) < 3: |
|
images.append(Image.new('RGB', (width, height), 'gray')) |
|
|
|
return images |
|
|
|
header = "Set up APIs on HuggingFace or use free at https://app.idai.tools/ (https://app.idai.tools/interface/seamless_patterns)" |
|
demo = gr.Interface(fn=generate_pattern, inputs=["image", "text"], outputs=["image", "image", "image"], title=header) |
|
demo.launch(share=False) |