Spaces:
Runtime error
Runtime error
import gradio as gr | |
import numpy as np | |
import spaces | |
import torch | |
import random | |
from PIL import Image | |
from huggingface_hub import hf_hub_download | |
from diffusers import FluxKontextPipeline, FluxTransformer2DModel, GGUFQuantizationConfig | |
from diffusers.utils import load_image | |
MAX_SEED = np.iinfo(np.int32).max | |
# Download GGUF model file first | |
gguf_file = hf_hub_download( | |
repo_id="bullerwins/FLUX.1-Kontext-dev-GGUF", | |
filename="flux1-kontext-dev-Q8_0.gguf", | |
local_dir="./models" | |
) | |
# Load GGUF transformer model | |
transformer = FluxTransformer2DModel.from_single_file( | |
gguf_file, | |
quantization_config=GGUFQuantizationConfig(compute_dtype=torch.bfloat16), | |
torch_dtype=torch.bfloat16, | |
) | |
# Use FluxKontextPipeline and reference the correct model repository | |
pipe = FluxKontextPipeline.from_pretrained( | |
"black-forest-labs/FLUX.1-Kontext-dev", | |
transformer=transformer, | |
torch_dtype=torch.bfloat16, | |
).to("cuda") | |
# 변경점: 숫자를 가장 가까운 16의 배수로 만들어주는 함수로 수정 | |
def to_multiple_of_16(n): | |
""" | |
Rounds a number to the nearest multiple of 16. | |
""" | |
return int(np.round(n / 16.0) * 16.0) | |
def infer(input_image, prompt, seed=42, randomize_seed=False, guidance_scale=2.5, steps=28, progress=gr.Progress(track_tqdm=True)): | |
""" | |
Perform image editing using the FLUX.1 Kontext pipeline. | |
This function takes an input image and a text prompt to generate a modified version | |
of the image based on the provided instructions. It uses the FLUX.1 Kontext model | |
for contextual image editing tasks. | |
Args: | |
input_image (PIL.Image.Image): The input image to be edited. Will be converted | |
to RGB format if not already in that format. | |
prompt (str): Text description of the desired edit to apply to the image. | |
Examples: "Remove glasses", "Add a hat", "Change background to beach". | |
seed (int, optional): Random seed for reproducible generation. Defaults to 42. | |
Must be between 0 and MAX_SEED (2^31 - 1). | |
randomize_seed (bool, optional): If True, generates a random seed instead of | |
using the provided seed value. Defaults to False. | |
guidance_scale (float, optional): Controls how closely the model follows the | |
prompt. Higher values mean stronger adherence to the prompt but may reduce | |
image quality. Range: 1.0-10.0. Defaults to 2.5. | |
steps (int, optional): Controls how many steps to run the diffusion model for. | |
Range: 1-30. Defaults to 28. | |
progress (gr.Progress, optional): Gradio progress tracker for monitoring | |
generation progress. Defaults to gr.Progress(track_tqdm=True). | |
Returns: | |
tuple: A 3-tuple containing: | |
- PIL.Image.Image: The generated/edited image | |
- int: The seed value used for generation (useful when randomize_seed=True) | |
- gr.update: Gradio update object to make the reuse button visible | |
Example: | |
>>> edited_image, used_seed, button_update = infer( | |
... input_image=my_image, | |
... prompt="Add sunglasses", | |
... seed=123, | |
... randomize_seed=False, | |
... guidance_scale=2.5 | |
... ) | |
""" | |
if randomize_seed: | |
seed = random.randint(0, MAX_SEED) | |
if input_image: | |
input_image = input_image.convert("RGB") | |
# 변경점: 모델의 요구사항에 맞게 이미지 크기를 16의 배수로 조정합니다. | |
original_width, original_height = input_image.size | |
new_width = to_multiple_of_16(original_width) | |
new_height = to_multiple_of_16(original_height) | |
# 조정된 크기로 이미지를 리사이즈합니다. | |
resized_image = input_image.resize((new_width, new_height)) | |
image = pipe( | |
image=resized_image, | |
prompt=prompt, | |
guidance_scale=guidance_scale, | |
num_inference_steps=steps, | |
generator=torch.Generator().manual_seed(seed), | |
).images[0] | |
else: | |
# 텍스트-이미지 생성 시에는 크기를 명시해주는 것이 좋습니다. | |
image = pipe( | |
prompt=prompt, | |
width=1024, | |
height=1024, | |
guidance_scale=guidance_scale, | |
num_inference_steps=steps, | |
generator=torch.Generator().manual_seed(seed), | |
).images[0] | |
return image, seed, gr.Button(visible=True) | |
def infer_example(input_image, prompt): | |
image, seed, _ = infer(input_image, prompt) | |
return image, seed | |
css=""" | |
#col-container { | |
margin: 0 auto; | |
max-width: 960px; | |
} | |
""" | |
with gr.Blocks(css=css) as demo: | |
with gr.Column(elem_id="col-container"): | |
gr.Markdown(f"""# FLUX.1 Kontext [dev] | |
Image editing and manipulation model guidance-distilled from FLUX.1 Kontext [pro], [[blog]](https://bfl.ai/announcements/flux-1-kontext-dev) [[model]](https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev) | |
""") | |
with gr.Row(): | |
with gr.Column(): | |
input_image = gr.Image(label="Upload the image for editing", type="pil") | |
with gr.Row(): | |
prompt = gr.Text( | |
label="Prompt", | |
show_label=False, | |
max_lines=1, | |
placeholder="Enter your prompt for editing (e.g., 'Remove glasses', 'Add a hat')", | |
container=False, | |
) | |
run_button = gr.Button("Run", scale=0) | |
with gr.Accordion("Advanced Settings", open=False): | |
seed = gr.Slider( | |
label="Seed", | |
minimum=0, | |
maximum=MAX_SEED, | |
step=1, | |
value=0, | |
) | |
randomize_seed = gr.Checkbox(label="Randomize seed", value=True) | |
guidance_scale = gr.Slider( | |
label="Guidance Scale", | |
minimum=1, | |
maximum=10, | |
step=0.1, | |
value=2.5, | |
) | |
steps = gr.Slider( | |
label="Steps", | |
minimum=1, | |
maximum=30, | |
value=28, | |
step=1 | |
) | |
with gr.Column(): | |
result = gr.Image(label="Result", show_label=False, interactive=False) | |
reuse_button = gr.Button("Reuse this image", visible=False) | |
examples = gr.Examples( | |
examples=[ | |
["flowers.png", "turn the flowers into sunflowers"], | |
["monster.png", "make this monster ride a skateboard on the beach"], | |
["cat.png", "make this cat happy"] | |
], | |
inputs=[input_image, prompt], | |
outputs=[result, seed], | |
fn=infer_example, | |
cache_examples="lazy" | |
) | |
gr.on( | |
triggers=[run_button.click, prompt.submit], | |
fn = infer, | |
inputs = [input_image, prompt, seed, randomize_seed, guidance_scale, steps], | |
outputs = [result, seed, reuse_button] | |
) | |
reuse_button.click( | |
fn = lambda image: image, | |
inputs = [result], | |
outputs = [input_image] | |
) | |
demo.launch(mcp_server=True) |