test-100 / app.py
Kims12's picture
Update app.py
16a6799 verified
raw
history blame
30.5 kB
import os
import sys
from torchvision.transforms import functional
sys.modules["torchvision.transforms.functional_tensor"] = functional
from basicsr.archs.srvgg_arch import SRVGGNetCompact
from gfpgan.utils import GFPGANer
from realesrgan.utils import RealESRGANer
import torch
import cv2
import gradio as gr
# ํ•„์š”ํ•œ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ
def download_upscaler_models():
if not os.path.exists('realesr-general-x4v3.pth'):
os.system("wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth -P .")
if not os.path.exists('GFPGANv1.4.pth'):
os.system("wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth -P .")
# ์—…์Šค์ผ€์ผ๋Ÿฌ ๋ชจ๋ธ ์ดˆ๊ธฐํ™”
def init_upscaler_model():
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
model_path = 'realesr-general-x4v3.pth'
half = True if torch.cuda.is_available() else False
upsampler = RealESRGANer(scale=4, model_path=model_path, model=model, tile=0, tile_pad=10, pre_pad=0, half=half)
return upsampler
# ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋ง ํ•จ์ˆ˜
def upscale_image(img):
try:
upsampler = init_upscaler_model()
# ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ฝ๊ธฐ
img = cv2.imread(img, cv2.IMREAD_UNCHANGED)
if len(img.shape) == 3 and img.shape[2] == 4:
img_mode = 'RGBA'
elif len(img.shape) == 2:
img_mode = None
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
else:
img_mode = None
# ์ž‘์€ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์กฐ์ •
h, w = img.shape[0:2]
if h < 300:
img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4)
# ๊ณ ์ •๋œ GFPGANv1.4 ๋ชจ๋ธ ์‚ฌ์šฉ
face_enhancer = GFPGANer(
model_path='GFPGANv1.4.pth',
upscale=2,
arch='clean',
channel_multiplier=2,
bg_upsampler=upsampler
)
# ์ด๋ฏธ์ง€ ํ–ฅ์ƒ
try:
_, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True)
except RuntimeError as error:
print('์˜ค๋ฅ˜', error)
return None
# RGB๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜
output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
return output
except Exception as error:
print('๊ธ€๋กœ๋ฒŒ ์˜ˆ์™ธ', error)
return None
# ์—…์Šค์ผ€์ผ๋Ÿฌ ํƒญ UI ์ƒ์„ฑ ํ•จ์ˆ˜
def create_upscaler_tab():
# ํ•„์š”ํ•œ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ
download_upscaler_models()
with gr.Tab("์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ"):
gr.Markdown(
"""
# ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ
์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ ๊ณ ํ•ด์ƒ๋„๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์ธ๋ฌผ ์‚ฌ์ง„์˜ ์–ผ๊ตด ๋””ํ…Œ์ผ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
"""
)
with gr.Row():
with gr.Column():
input_image = gr.Image(type="filepath", label="์ž…๋ ฅ ์ด๋ฏธ์ง€")
upscale_btn = gr.Button("์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ", variant="primary")
with gr.Column():
output_image = gr.Image(type="numpy", label="๊ฒฐ๊ณผ ์ด๋ฏธ์ง€")
upscale_btn.click(
fn=upscale_image,
inputs=[input_image],
outputs=[output_image]
)
import os
import tempfile
from PIL import Image
import gradio as gr
import logging
import re
from io import BytesIO
import time
# ์—…์Šค์ผ€์ผ๋Ÿฌ ๋ชจ๋“ˆ ์ž„ํฌํŠธ
import sys
from torchvision.transforms import functional
sys.modules["torchvision.transforms.functional_tensor"] = functional
from basicsr.archs.srvgg_arch import SRVGGNetCompact
from gfpgan.utils import GFPGANer
from realesrgan.utils import RealESRGANer
import torch
import cv2
from google import genai
from google.genai import types
# ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋กœ๋“œ
from dotenv import load_dotenv
load_dotenv()
# ๋กœ๊น… ์„ค์ •
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def save_binary_file(file_name, data):
with open(file_name, "wb") as f:
f.write(data)
def translate_prompt_to_english(prompt):
"""
์ž…๋ ฅ๋œ ํ”„๋กฌํ”„ํŠธ์— ํ•œ๊ธ€์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด Geminiโ€‘2.0โ€‘flash ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜์–ด๋กœ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค.
ํ•œ๊ธ€์ด ์—†์œผ๋ฉด ์›๋ณธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
์ค‘์š”: #1, #2, #3 ํƒœ๊ทธ๋Š” ๋ฒˆ์—ญ ์ „ํ›„์— ๋ฐ˜๋“œ์‹œ ๋ณด์กด๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
"""
if not re.search("[๊ฐ€-ํžฃ]", prompt):
return prompt
# #1, #2, #3 ํƒœ๊ทธ๋ฅผ ์ž„์‹œ ํ† ํฐ์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ๋ณด์กด
prompt = prompt.replace("#1", "IMAGE_TAG_ONE")
prompt = prompt.replace("#2", "IMAGE_TAG_TWO")
prompt = prompt.replace("#3", "IMAGE_TAG_THREE")
try:
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
logger.error("Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
# ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
return prompt
client = genai.Client(api_key=api_key)
translation_prompt = f"""
Translate the following Korean text to English:
{prompt}
IMPORTANT: The tokens IMAGE_TAG_ONE, IMAGE_TAG_TWO, and IMAGE_TAG_THREE are special tags
and must be preserved exactly as is in your translation. Do not translate these tokens.
"""
logger.info(f"Translation prompt: {translation_prompt}")
response = client.models.generate_content(
model="gemini-2.0-flash",
contents=[translation_prompt],
config=types.GenerateContentConfig(
response_modalities=['Text'],
temperature=0.2,
top_p=0.95,
top_k=40,
max_output_tokens=512
)
)
translated_text = ""
for part in response.candidates[0].content.parts:
if hasattr(part, 'text') and part.text:
translated_text += part.text
if translated_text.strip():
# ๋ฒˆ์—ญ๋œ ํ…์ŠคํŠธ์—์„œ ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
translated_text = translated_text.replace("IMAGE_TAG_ONE", "#1")
translated_text = translated_text.replace("IMAGE_TAG_TWO", "#2")
translated_text = translated_text.replace("IMAGE_TAG_THREE", "#3")
logger.info(f"Translated text: {translated_text.strip()}")
return translated_text.strip()
else:
logger.warning("๋ฒˆ์—ญ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์›๋ณธ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ")
# ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
return prompt
except Exception as e:
logger.exception("๋ฒˆ์—ญ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
# ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
return prompt
def preprocess_prompt(prompt, image1, image2, image3):
"""
ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ธฐ๋Šฅ ๋ช…๋ น์„ ํ•ด์„
"""
has_img1 = image1 is not None
has_img2 = image2 is not None
has_img3 = image3 is not None
if "#1" in prompt and not has_img1:
prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
else:
prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
if "#2" in prompt and not has_img2:
prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
else:
prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
if "#3" in prompt and not has_img3:
prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
else:
prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
desc_match = re.search(r'#1์„ "(.*?)"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ', prompt)
if desc_match:
description = desc_match.group(1)
prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ {description}์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์›๋ณธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ๋‚ด์šฉ์€ ์œ ์ง€ํ•˜๋˜ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๊ณผ ๋ถ„์œ„๊ธฐ๋กœ ์žฌํ•ด์„ํ•ด์ฃผ์„ธ์š”."
else:
prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
text_match = re.search(r'#1์—์„œ "(.*?)"๋ฅผ ์ง€์›Œ๋ผ', prompt)
if text_match:
text_to_remove = text_match.group(1)
prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ '{text_to_remove}' ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋˜ ๋ถ€๋ถ„์„ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ์ฑ„์›Œ์ฃผ์„ธ์š”."
else:
prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ๊น”๋”ํ•œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
elif "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ" in prompt:
prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€)๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ๋‹๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ์ด๋ฏธ์ง€์— ํ…์ŠคํŠธ๋‚˜ ๊ธ€์ž๋ฅผ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”."
return prompt
def generate_with_images(prompt, images, variation_index=0):
"""
API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
variation_index๋กœ ๋‹ค์–‘ํ•œ ๋ณ€ํ™”๋ฅผ ์ค๋‹ˆ๋‹ค.
"""
try:
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
client = genai.Client(api_key=api_key)
logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
# ๋ณ€ํ˜• ์ธ๋ฑ์Šค์— ๋”ฐ๋ผ ํ”„๋กฌํ”„ํŠธ์— ์•ฝ๊ฐ„์˜ ๋ณ€ํ™” ์ถ”๊ฐ€
variation_suffixes = [
" Create this as the first variation. Do not add any text, watermarks, or labels to the image.",
" Create this as the second variation with more vivid colors. Do not add any text, watermarks, or labels to the image.",
" Create this as the third variation with a more creative style. Do not add any text, watermarks, or labels to the image.",
" Create this as the fourth variation with enhanced details. Do not add any text, watermarks, or labels to the image."
]
if variation_index < len(variation_suffixes):
prompt = prompt + variation_suffixes[variation_index]
else:
prompt = prompt + " Do not add any text, watermarks, or labels to the image."
contents = [prompt]
for idx, img in enumerate(images, 1):
if img is not None:
contents.append(img)
logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
response = client.models.generate_content(
model="gemini-2.0-flash-exp-image-generation",
contents=contents,
config=types.GenerateContentConfig(
response_modalities=['Text', 'Image'],
temperature=1,
top_p=0.95,
top_k=40,
max_output_tokens=8192
)
)
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
temp_path = tmp.name
result_text = ""
image_found = False
for part in response.candidates[0].content.parts:
if hasattr(part, 'text') and part.text:
result_text += part.text
logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
elif hasattr(part, 'inline_data') and part.inline_data:
save_binary_file(temp_path, part.inline_data.data)
image_found = True
logger.info("์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
if not image_found:
return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
result_img = Image.open(temp_path)
if result_img.mode == "RGBA":
result_img = result_img.convert("RGB")
return result_img, f"์ด๋ฏธ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. {result_text}"
except Exception as e:
logger.exception("์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
def process_images_with_prompt(image1, image2, image3, prompt, variation_index=0, max_retries=3):
"""
3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ตœ์ข… ์˜์–ด ํ”„๋กฌํ”„ํŠธ(final_prompt)๋ฅผ ์ƒ์„ฑํ•œ ํ›„,
API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์ตœ๋Œ€ max_retries ํšŸ์ˆ˜๋งŒํผ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
"""
retry_count = 0
last_error = None
while retry_count < max_retries:
try:
images = [image1, image2, image3]
valid_images = [img for img in images if img is not None]
if not valid_images:
return None, "์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
if prompt and prompt.strip():
processed_prompt = preprocess_prompt(prompt, image1, image2, image3)
if re.search("[๊ฐ€-ํžฃ]", processed_prompt):
final_prompt = translate_prompt_to_english(processed_prompt)
else:
final_prompt = processed_prompt
else:
if len(valid_images) == 1:
final_prompt = "Please creatively transform this image into a more vivid and artistic version. Do not include any text or watermarks in the generated image."
logger.info("Default prompt generated for single image")
elif len(valid_images) == 2:
final_prompt = "Please seamlessly composite these two images, integrating their key elements harmoniously into a single image. Do not include any text or watermarks in the generated image."
logger.info("Default prompt generated for two images")
else:
final_prompt = "Please creatively composite these three images, combining their main elements into a cohesive and natural scene. Do not include any text or watermarks in the generated image."
logger.info("Default prompt generated for three images")
result_img, status = generate_with_images(final_prompt, valid_images, variation_index)
if result_img is not None:
return result_img, status, final_prompt
else:
last_error = status
retry_count += 1
logger.warning(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹คํŒจ, ์žฌ์‹œ๋„ {retry_count}/{max_retries}: {status}")
time.sleep(1)
except Exception as e:
last_error = str(e)
retry_count += 1
logger.exception(f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ, ์žฌ์‹œ๋„ {retry_count}/{max_retries}:")
time.sleep(1)
return None, f"์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜({max_retries}ํšŒ) ์ดˆ๊ณผ ํ›„ ์‹คํŒจ: {last_error}", prompt
def generate_multiple_images(image1, image2, image3, prompt, progress=gr.Progress()):
"""
์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์ฐจ๋ก€๋Œ€๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
"""
results = []
statuses = []
prompts = []
num_images = 4 # ์ƒ์„ฑํ•  ์ด๋ฏธ์ง€ ์ˆ˜
max_retries = 3 # ๊ฐ ์ด๋ฏธ์ง€ ๋‹น ์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜
progress(0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค€๋น„ ์ค‘...")
for i in range(num_images):
progress((i / num_images), desc=f"{i+1}/{num_images} ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘...")
result_img, status, final_prompt = process_images_with_prompt(image1, image2, image3, prompt, i, max_retries)
if result_img is not None:
results.append(result_img)
statuses.append(f"์ด๋ฏธ์ง€ #{i+1}: {status}")
prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
else:
results.append(None)
statuses.append(f"์ด๋ฏธ์ง€ #{i+1} ์ƒ์„ฑ ์‹คํŒจ: {status}")
prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
time.sleep(1)
progress(1.0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์™„๋ฃŒ!")
while len(results) < 4:
results.append(None)
combined_status = "\n".join(statuses)
combined_prompts = "\n".join(prompts)
return results[0], results[1], results[2], results[3], combined_status, combined_prompts
# ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ ๊ธฐ๋Šฅ
def download_upscaler_models():
if not os.path.exists('realesr-general-x4v3.pth'):
os.system("wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth -P .")
if not os.path.exists('GFPGANv1.4.pth'):
os.system("wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth -P .")
def upscale_image(img):
try:
# ๋ชจ๋ธ ์ดˆ๊ธฐํ™”
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
model_path = 'realesr-general-x4v3.pth'
half = True if torch.cuda.is_available() else False
upsampler = RealESRGANer(scale=4, model_path=model_path, model=model, tile=0, tile_pad=10, pre_pad=0, half=half)
# ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ฝ๊ธฐ
img = cv2.imread(img, cv2.IMREAD_UNCHANGED)
if len(img.shape) == 3 and img.shape[2] == 4:
img_mode = 'RGBA'
elif len(img.shape) == 2:
img_mode = None
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
else:
img_mode = None
# ์ž‘์€ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์กฐ์ •
h, w = img.shape[0:2]
if h < 300:
img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4)
# GFPGANv1.4 ๋ชจ๋ธ ์‚ฌ์šฉ
face_enhancer = GFPGANer(
model_path='GFPGANv1.4.pth',
upscale=2,
arch='clean',
channel_multiplier=2,
bg_upsampler=upsampler
)
# ์ด๋ฏธ์ง€ ํ–ฅ์ƒ
try:
_, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True)
except RuntimeError as error:
print('์˜ค๋ฅ˜', error)
return None
# RGB๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜
output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
return output
except Exception as error:
print('๊ธ€๋กœ๋ฒŒ ์˜ˆ์™ธ', error)
return None
# Gradio ์ธํ„ฐํŽ˜์ด์Šค
with gr.Blocks() as demo:
gr.HTML(
"""
<div style="text-align: center; margin-bottom: 1rem;">
<h1>์ด์ปค๋จธ์Šค์šฉ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘ ๋„๊ตฌ</h1>
<p>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ์˜ˆ์ œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜์„ธ์š”.</p>
</div>
"""
)
with gr.Tabs():
# ์ฒซ ๋ฒˆ์งธ ํƒญ: ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ
with gr.Tab("์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ"):
with gr.Row():
# ์™ผ์ชฝ ์ž…๋ ฅ ์˜์—ญ (์˜ˆ์ œ ์ด๋ฏธ์ง€๋ฅผ ํฌํ•จํ•˜์—ฌ ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์•„๋ž˜์— ๋ฐฐ์น˜)
with gr.Column(scale=1):
with gr.Row():
image1_input = gr.Image(type="pil", label="#1", image_mode="RGB", height=300, width=200)
image2_input = gr.Image(type="pil", label="#2", image_mode="RGB", height=300, width=200)
image3_input = gr.Image(type="pil", label="#3", image_mode="RGB", height=300, width=200)
prompt_input = gr.Textbox(
lines=3,
placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋น„์›Œ๋‘๋ฉด ์ž๋™ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.",
label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
)
with gr.Row():
image_change_btn1 = gr.Button("์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ-1")
image_change_btn2 = gr.Button("์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ-2")
text_remove_btn = gr.Button("๊ธ€์ž ์ง€์šฐ๊ธฐ")
text_change_btn = gr.Button("๊ธ€์ž ๋ณ€๊ฒฝํ•˜๊ธฐ")
clothes_change_btn1 = gr.Button("๊ฐ€์ƒ ์ƒํ’ˆ์ฐฉ์šฉ-1")
clothes_change_btn2 = gr.Button("๊ฐ€์ƒ ์ƒํ’ˆ์ฐฉ์šฉ-2")
holding_product_btn = gr.Button("์ƒํ’ˆ๋“ค๊ณ  ์žˆ๊ธฐ")
background_change_btn = gr.Button("๋ฐฐ๊ฒฝ ๋ฐ”๊พธ๊ธฐ")
composite_product_btn = gr.Button("๋ถ€๋ถ„ ์ง€์šฐ๊ธฐ")
submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ (4์žฅ)", variant="primary")
gr.Markdown(
"""
### ์‚ฌ์šฉ ๋ฐฉ๋ฒ•:
1. **์ž๋™ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.
2. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
3. **์„ ํƒ ์˜ต์…˜**: ์œ„์˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ๋ž€์— ํ•œ๊ตญ์–ด ๋ฌธ๊ตฌ๋กœ ์ž…๋ ฅํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
4. **๋‹ค์–‘ํ•œ ์ด๋ฏธ์ง€**: "์ด๋ฏธ์ง€ ์ƒ์„ฑ" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ฐจ๋ก€๋กœ 4์žฅ์˜ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
5. **์˜ˆ์ œ์„ ํƒ**: ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๋ฏธ๋ฆฌ ํ…Œ์ŠคํŠธํ•ด๋ณด์„ธ์š”.
> **ํŒ**: ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
"""
)
# ์˜ˆ์ œ ์ด๋ฏธ์ง€: ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์•„๋ž˜ ์™ผ์ชฝ ์˜์—ญ์— ๋ฐฐ์น˜
gr.Markdown("## ์˜ˆ์ œ ์ด๋ฏธ์ง€")
examples = [
["down/๋ชจ๋ธ.jpg", None, None, "(#1์˜ ์—ฌ์„ฑ)์ด ์‚ด์ง ๋’ค๋กœ ๋Œ์•„๋ณด๋Š” ๋ชจ์Šต์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ด์ „ seed๋ฅผ ์œ ์ง€ํ•œํ…Œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ผ."],
["down/์ƒ์–ด๋ ˆ๊ณ ๋ชจํ˜•.png", None, None, "(#1 ๋ ˆ๋ชจ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋งŒ ๊ฒ€์€์ƒ‰ ๊ณ ๋ž˜๋ ˆ๊ณ ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ seed๋ฅผ ๋ณ€๊ฒฝ์„ ํ•˜์ง€๋งˆ๋ผ."],
["down/์ค‘๊ตญ์–ด.png", None, None, "(#1 ์ด๋ฏธ์ง€)์— ์žˆ๋Š” ์ค‘๊ตญ์–ด๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋ผ."],
["down/ํ…์ŠคํŠธ.webp", None, None, '(#1์˜ ํ…์ŠคํŠธ)๋ฅผ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•œ์ฒด ํ…์ŠคํŠธ๋งŒ "Hello"๋กœ ๋ฐ”๊ฟ”๋ผ'],
["down/๋ชจ๋ธ.jpg", "down/์„ ๊ธ€๋ผ์Šค.png", "down/์ฒญ๋ฐ”์ง€.png", "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์™€ (#3์˜ ์ฒญ๋ฐ”์ง€)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ๊ฒƒ ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ."],
["down/๋ชจ๋ธ.jpg", "down/์„ ๊ธ€๋ผ์Šค.png", "down/์นดํŽ˜์ „๊ฒฝ.png", "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ ๊ฒƒ์ฒ˜๋Ÿผ (#3์˜ ์žฅ์†Œ)์—์„œ ์˜์ž์— ์•‰์•„ ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ."],
["down/๋ชจ๋ธ.jpg", "down/์™€์ธ์ž”.png", None, "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์™€์ธ์ž”)์„ ์—ฌ์„ฑ๋ชจ๋ธ์ด ํ™๋ณดํ•  ์™€์ธ์ž”์„ ๋‹๋ณด์ด๊ฒŒ ๋“ค๊ณ  ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ชจ์Šต์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ."],
["down/๋ชจ๋ธ.jpg", "down/์นดํŽ˜์ „๊ฒฝ.png", None, "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2 ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ)์„ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜์—ฌ ์ด๋ฏธ์ง€์˜ ๋ถ„์œ„๊ธฐ๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ƒ์„ฑํ•˜๋ผ."],
["down/์ƒ์–ด๋ ˆ๊ณ ๋ชจํ˜•.png", None, None, "(#1์˜ ๋ ˆ๊ณ ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„, ๊ทธ ์ž๋ฆฌ๋ฅผ ์ฃผ๋ณ€ ๋ฐฐ๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ฑ„์›Œ์ฃผ์„ธ์š”. ๋‹จ, ์ด๋ฏธ์ง€์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์ฃผ์š” ์š”์†Œ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•ด ํ•ด์•ผํ•œ๋‹ค."]
]
gr.Examples(
examples=examples,
inputs=[image1_input, image2_input, image3_input, prompt_input],
elem_id="examples-grid"
)
# ์˜ค๋ฅธ์ชฝ ์ถœ๋ ฅ ์˜์—ญ
with gr.Column(scale=1):
with gr.Row():
with gr.Column():
output_image1 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #1", height=600, width=450)
output_image3 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #3", height=600, width=450)
with gr.Column():
output_image2 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #2", height=600, width=450)
output_image4 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #4", height=600, width=450)
output_text = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€", lines=4)
prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", visible=True, lines=4)
# ์„ ํƒ ์˜ต์…˜ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ๋ž€ ์—…๋ฐ์ดํŠธ (ํ•œ๊ตญ์–ด ๋ฌธ๊ตฌ)
image_change_btn1.click(
fn=lambda: "(#1์˜ ์—ฌ์„ฑ)์ด ์‚ด์ง ๋’ค๋กœ ๋Œ์•„๋ณด๋Š” ๋ชจ์Šต์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ด์ „ seed๋ฅผ ์œ ์ง€ํ•œํ…Œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ผ.",
inputs=[],
outputs=prompt_input
)
image_change_btn2.click(
fn=lambda: "(#1 ๋ ˆ๋ชจ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋งŒ ๊ฒ€์€์ƒ‰ ๊ณ ๋ž˜๋ ˆ๊ณ ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ seed๋ฅผ ๋ณ€๊ฒฝ์„ ํ•˜์ง€๋งˆ๋ผ.",
inputs=[],
outputs=prompt_input
)
text_remove_btn.click(
fn=lambda: "(#1 ์ด๋ฏธ์ง€)์— ์žˆ๋Š” ์ค‘๊ตญ์–ด๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋ผ.",
inputs=[],
outputs=prompt_input
)
text_change_btn.click(
fn=lambda: "(#1์˜ ํ…์ŠคํŠธ)๋ฅผ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•œ์ฒด ํ…์ŠคํŠธ๋งŒ \"Hello\"๋กœ ๋ฐ”๊ฟ”๋ผ",
inputs=[],
outputs=prompt_input
)
clothes_change_btn1.click(
fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๊ฒ”)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์™€ (#3์˜ ์ฒญ๋ฐ”์ง€)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ๊ฒƒ ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ.",
inputs=[],
outputs=prompt_input
)
clothes_change_btn2.click(
fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ ๊ฒƒ์ฒ˜๋Ÿผ (#3์˜ ์žฅ์†Œ)์—์„œ ์˜์ž์— ์•‰์•„ ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ.",
inputs=[],
outputs=prompt_input
)
holding_product_btn.click(
fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์™€์ธ์ž”)์„ ์—ฌ์„ฑ๋ชจ๋ธ์ด ํ™๋ณดํ•  ์™€์ธ์ž”์„ ๋‹๋ณด์ด๊ฒŒ ๋“ค๊ณ  ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ชจ์Šต์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ.",
inputs=[],
outputs=prompt_input
)
background_change_btn.click(
fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2 ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ)์„ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜์—ฌ ๋‘ ์ด๋ฏธ์ง€์˜ ๋ถ„์œ„๊ธฐ๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ƒ์„ฑํ•˜๋ผ.",
inputs=[],
outputs=prompt_input
)
composite_product_btn.click(
fn=lambda: "(#1์˜ ๋ ˆ๊ณ ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„, ๊ทธ ์ž๋ฆฌ๋ฅผ ์ฃผ๋ณ€ ๋ฐฐ๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ฑ„์›Œ์ฃผ์„ธ์š”. ๋‹จ, ์ด๋ฏธ์ง€์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์ฃผ์š” ์š”์†Œ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•ด ํ•ด์•ผํ•œ๋‹ค.",
inputs=[],
outputs=prompt_input
)
submit_btn.click(
fn=generate_multiple_images,
inputs=[image1_input, image2_input, image3_input, prompt_input],
outputs=[output_image1, output_image2, output_image3, output_image4, output_text, prompt_display],
)
# ๋‘ ๋ฒˆ์งธ ํƒญ: ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ
with gr.Tab("์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ"):
# ํ•„์š”ํ•œ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ ํ˜ธ์ถœ
download_upscaler_models()
gr.Markdown(
"""
# ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ
์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ ๊ณ ํ•ด์ƒ๋„๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์ธ๋ฌผ ์‚ฌ์ง„์˜ ์–ผ๊ตด ๋””ํ…Œ์ผ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
"""
)
with gr.Row():
with gr.Column():
input_upscale_image = gr.Image(type="filepath", label="์ž…๋ ฅ ์ด๋ฏธ์ง€")
upscale_btn = gr.Button("์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ", variant="primary")
with gr.Column():
output_upscale_image = gr.Image(type="numpy", label="๊ฒฐ๊ณผ ์ด๋ฏธ์ง€")
upscale_btn.click(
fn=upscale_image,
inputs=[input_upscale_image],
outputs=[output_upscale_image]
)
if __name__ == "__main__":
demo.launch(share=True)