Update app.py
Browse files
app.py
CHANGED
|
@@ -13,6 +13,7 @@ from transformers import pipeline # ์๋ก ์ถ๊ฐ๋ import
|
|
| 13 |
|
| 14 |
load_dotenv()
|
| 15 |
|
|
|
|
| 16 |
# ๊ธฐ์กด ์ฝ๋ ์ ์ง (๋ก๊น
, ํจ์ ๋ฑ ๋ชจ๋ ๊ธฐ๋ฅ ์ฝ๋)
|
| 17 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 18 |
logger = logging.getLogger(__name__)
|
|
@@ -42,6 +43,116 @@ def save_binary_file(file_name, data):
|
|
| 42 |
with open(file_name, "wb") as f:
|
| 43 |
f.write(data)
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
def translate_prompt_to_english(prompt):
|
| 46 |
# ๊ธฐ์กด ํจ์ ์ ์ง
|
| 47 |
if not re.search("[๊ฐ-ํฃ]", prompt):
|
|
@@ -196,7 +307,8 @@ def generate_with_images(prompt, images, variation_index=0):
|
|
| 196 |
)
|
| 197 |
)
|
| 198 |
|
| 199 |
-
|
|
|
|
| 200 |
temp_path = tmp.name
|
| 201 |
result_text = ""
|
| 202 |
image_found = False
|
|
@@ -210,16 +322,22 @@ def generate_with_images(prompt, images, variation_index=0):
|
|
| 210 |
logger.info("์๋ต์์ ์ด๋ฏธ์ง ์ถ์ถ ์ฑ๊ณต")
|
| 211 |
if not image_found:
|
| 212 |
return None, f"API์์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ์ง ๋ชปํ์ต๋๋ค. ์๋ต ํ
์คํธ: {result_text}"
|
|
|
|
| 213 |
result_img = Image.open(temp_path)
|
| 214 |
if result_img.mode == "RGBA":
|
| 215 |
-
result_img = result_img.convert("RGB")
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
except Exception as e:
|
| 218 |
logger.exception("์ด๋ฏธ์ง ์์ฑ ์ค ์ค๋ฅ ๋ฐ์:")
|
| 219 |
return None, f"์ค๋ฅ ๋ฐ์: {str(e)}"
|
| 220 |
|
| 221 |
def process_images_with_prompt(image1, image2, image3, prompt, variation_index=0, max_retries=3):
|
| 222 |
-
# ๊ธฐ์กด ํจ์ ์ ์ง
|
| 223 |
retry_count = 0
|
| 224 |
last_error = None
|
| 225 |
|
|
@@ -249,6 +367,7 @@ def process_images_with_prompt(image1, image2, image3, prompt, variation_index=0
|
|
| 249 |
|
| 250 |
result_img, status = generate_with_images(final_prompt, valid_images, variation_index)
|
| 251 |
if result_img is not None:
|
|
|
|
| 252 |
return result_img, status, final_prompt
|
| 253 |
else:
|
| 254 |
last_error = status
|
|
@@ -264,7 +383,7 @@ def process_images_with_prompt(image1, image2, image3, prompt, variation_index=0
|
|
| 264 |
return None, f"์ต๋ ์ฌ์๋ ํ์({max_retries}ํ) ์ด๊ณผ ํ ์คํจ: {last_error}", prompt
|
| 265 |
|
| 266 |
def generate_multiple_images(image1, image2, image3, prompt, progress=gr.Progress()):
|
| 267 |
-
#
|
| 268 |
results = []
|
| 269 |
statuses = []
|
| 270 |
prompts = []
|
|
@@ -279,6 +398,7 @@ def generate_multiple_images(image1, image2, image3, prompt, progress=gr.Progres
|
|
| 279 |
result_img, status, final_prompt = process_images_with_prompt(image1, image2, image3, prompt, i, max_retries)
|
| 280 |
|
| 281 |
if result_img is not None:
|
|
|
|
| 282 |
results.append(result_img)
|
| 283 |
statuses.append(f"์ด๋ฏธ์ง #{i+1}: {status}")
|
| 284 |
prompts.append(f"์ด๋ฏธ์ง #{i+1}: {final_prompt}")
|
|
@@ -299,6 +419,7 @@ def generate_multiple_images(image1, image2, image3, prompt, progress=gr.Progres
|
|
| 299 |
|
| 300 |
return results[0], results[1], results[2], results[3], combined_status, combined_prompts
|
| 301 |
|
|
|
|
| 302 |
# GFPGAN ๊ด๋ จ ์ฝ๋ ์ ์ง
|
| 303 |
import sys
|
| 304 |
from torchvision.transforms import functional
|
|
@@ -842,6 +963,7 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 842 |
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-expand-alt"></i> ์ด๋ฏธ์ง ํ์ฅ</p>
|
| 843 |
์๋ณธ ์ด๋ฏธ์ง ์ฃผ๋ณ์ ์์ฐ์ค๋ฝ๊ฒ ์ถ๊ฐ ์์ญ์ ์์ฑํ์ฌ ์ด๋ฏธ์ง๋ฅผ ํ์ฅํฉ๋๋ค.
|
| 844 |
</div>
|
|
|
|
| 845 |
</div>
|
| 846 |
</div>
|
| 847 |
</div>
|
|
@@ -882,22 +1004,55 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 882 |
</p>
|
| 883 |
</div>
|
| 884 |
|
|
|
|
| 885 |
<div class="manual-section">
|
| 886 |
-
<div class="manual-section-title"><i class="fas fa-
|
| 887 |
-
<
|
| 888 |
-
<
|
| 889 |
-
|
| 890 |
-
|
| 891 |
-
|
| 892 |
-
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
|
| 896 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 897 |
</div>
|
| 898 |
-
</div>
|
| 899 |
""")
|
| 900 |
-
|
| 901 |
with gr.TabItem("โจ ์ด์ปค๋จธ์ค ์ด๋ฏธ์ง ์์ฑ๊ธฐ", elem_classes="tab-content"):
|
| 902 |
with gr.Row(equal_height=True):
|
| 903 |
with gr.Column(scale=1):
|
|
@@ -928,6 +1083,8 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 928 |
background_change_btn = gr.Button('๐ผ๏ธ ๋ฐฐ๊ฒฝ ๋ฐ๊พธ๊ธฐ', elem_classes="custom-button")
|
| 929 |
composite_product_btn = gr.Button('โ๏ธ ๋ถ๋ถ ์ง์ฐ๊ธฐ', elem_classes="custom-button")
|
| 930 |
outpainting_btn = gr.Button('๐ ์ด๋ฏธ์ง ํ์ฅ', elem_classes="custom-button")
|
|
|
|
|
|
|
| 931 |
|
| 932 |
submit_single_btn = gr.Button('โจ ์ด๋ฏธ์ง ์์ฑ (1์ฅ)', elem_classes="custom-button primary")
|
| 933 |
submit_btn = gr.Button('โจ ์ด๋ฏธ์ง ์์ฑ (4์ฅ)', elem_classes="custom-button primary")
|
|
@@ -937,11 +1094,11 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 937 |
gr.HTML('<div class="section-title"><i class="fas fa-images"></i> ์์ฑ๋ ์ด๋ฏธ์ง</div>')
|
| 938 |
with gr.Row():
|
| 939 |
with gr.Column():
|
| 940 |
-
output_image1 = gr.Image(label="์ด๋ฏธ์ง #1", elem_classes="image-container", height=400)
|
| 941 |
-
output_image3 = gr.Image(label="์ด๋ฏธ์ง #3", elem_classes="image-container", height=400)
|
| 942 |
with gr.Column():
|
| 943 |
-
output_image2 = gr.Image(label="์ด๋ฏธ์ง #2", elem_classes="image-container", height=400)
|
| 944 |
-
output_image4 = gr.Image(label="์ด๋ฏธ์ง #4", elem_classes="image-container", height=400)
|
| 945 |
|
| 946 |
gr.HTML('<div class="section-title"><i class="fas fa-info-circle"></i> ๊ฒฐ๊ณผ ์ ๋ณด</div>')
|
| 947 |
output_text = gr.Textbox(label="์ํ ๋ฉ์์ง", lines=2, elem_classes="custom-input")
|
|
@@ -959,14 +1116,15 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 959 |
["down/๋ชจ๋ธ.jpg", "down/์์ธ์.png", None, "(#1์ ์ฌ์ฑ๋ชจ๋ธ)์ด(#2์ ์์ธ์)์ ๋ค๊ณ ์๋ ์์ฐ์ค๋ฌ์ด ๋ชจ์ต"],
|
| 960 |
["down/๋ชจ๋ธ.jpg", "down/์นดํ์ ๊ฒฝ.png", None, "(#1์ ์ฌ์ฑ๋ชจ๋ธ)์ด (#2 ์นดํ)์์ ์์ฐ์ค๋ฝ๊ฒ ์๋ ๋ชจ์ต"],
|
| 961 |
["down/์์ด๋ ๊ณ ๋ชจํ.png", None, None, "(#1์ ๋ ๊ณ ๋ชจํ)์์ ์ฒญ์์์ด๋ ๊ณ ๋ฅผ ์ ๊ฑฐํ ํ, ๊ทธ ์๋ฆฌ๋ฅผ ์ฃผ๋ณ ๋ฐฐ๊ฒฝ๊ณผ ์์ฐ์ค๋ฝ๊ฒ ์ด์ฐ๋ฌ์ง๋๋ก ์ฑ์์ฃผ์ธ์. ๋จ, ์ด๋ฏธ์ง์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ฃผ์ ์์๋ ๋์ผํ๊ฒ ์ ์งํด ํด์ผํ๋ค."],
|
| 962 |
-
["down/์นดํ์ ๊ฒฝ.png", None, None, "(#1 ์ด๋ฏธ์ง)๋ฅผ ์๋ณธ๊ทธ๋๋ก ์ค์์ ๋๊ณ ๋น์จ๋ก ์ ์งํ ์ฒด ์์๋ ๋ฐ ์ข์ฐ๋ก ํฌ๊ฒ ํ์ฅํ๋ผ."]
|
|
|
|
| 963 |
]
|
| 964 |
|
| 965 |
gr.Examples(
|
| 966 |
examples=examples,
|
| 967 |
inputs=[image1_input, image2_input, image3_input, prompt_input]
|
| 968 |
)
|
| 969 |
-
|
| 970 |
with gr.TabItem("๐ ์ด๋ฏธ์ง ์
์ค์ผ์ผ๋ฌ", elem_classes="tab-content"):
|
| 971 |
with gr.Row():
|
| 972 |
with gr.Column(elem_classes="panel"):
|
|
@@ -1017,6 +1175,82 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 1017 |
with gr.Row():
|
| 1018 |
bg_remove_status = gr.Textbox(label="์ํ", lines=2, elem_classes="custom-input")
|
| 1019 |
bg_remove_btn = gr.Button('โ๏ธ ๋ฐฐ๊ฒฝ ์ ๊ฑฐํ๊ธฐ', elem_classes="custom-button primary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1020 |
|
| 1021 |
# ๋ฒํผ ์ด๋ฒคํธ ์ฐ๊ฒฐ
|
| 1022 |
image_change_btn1.click(
|
|
@@ -1070,6 +1304,12 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 1070 |
inputs=[],
|
| 1071 |
outputs=prompt_input
|
| 1072 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1073 |
|
| 1074 |
# ๋จ์ผ ์ด๋ฏธ์ง ์์ฑ ๋ฒํผ ์ด๋ฒคํธ ์ฐ๊ฒฐ
|
| 1075 |
submit_single_btn.click(
|
|
|
|
| 13 |
|
| 14 |
load_dotenv()
|
| 15 |
|
| 16 |
+
|
| 17 |
# ๊ธฐ์กด ์ฝ๋ ์ ์ง (๋ก๊น
, ํจ์ ๋ฑ ๋ชจ๋ ๊ธฐ๋ฅ ์ฝ๋)
|
| 18 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 19 |
logger = logging.getLogger(__name__)
|
|
|
|
| 43 |
with open(file_name, "wb") as f:
|
| 44 |
f.write(data)
|
| 45 |
|
| 46 |
+
|
| 47 |
+
# ์ด๋ฏธ์ง ํํฐ ๊ธฐ๋ฅ์ ์ํ ์ถ๊ฐ ์ฝ๋
|
| 48 |
+
import cv2
|
| 49 |
+
import numpy as np
|
| 50 |
+
from PIL import Image, ImageEnhance, ImageFilter
|
| 51 |
+
import tempfile
|
| 52 |
+
from datetime import datetime, timedelta
|
| 53 |
+
|
| 54 |
+
# ์ด๋ฏธ์ง ํํฐ ์ฒ๋ฆฌ ํจ์
|
| 55 |
+
def adjust_brightness(image, value):
|
| 56 |
+
"""์ด๋ฏธ์ง ๋ฐ๊ธฐ ์กฐ์ """
|
| 57 |
+
value = float(value - 1) * 100 # 0-2 ๋ฒ์๋ฅผ -100์์ +100์ผ๋ก ๋ณํ
|
| 58 |
+
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
|
| 59 |
+
h, s, v = cv2.split(hsv)
|
| 60 |
+
v = cv2.add(v, value)
|
| 61 |
+
v = np.clip(v, 0, 255)
|
| 62 |
+
final_hsv = cv2.merge((h, s, v))
|
| 63 |
+
return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
|
| 64 |
+
|
| 65 |
+
def adjust_contrast(image, value):
|
| 66 |
+
"""์ด๋ฏธ์ง ๋๋น ์กฐ์ """
|
| 67 |
+
value = float(value)
|
| 68 |
+
return np.clip(image * value, 0, 255).astype(np.uint8)
|
| 69 |
+
|
| 70 |
+
def adjust_saturation(image, value):
|
| 71 |
+
"""์ด๋ฏธ์ง ์ฑ๋ ์กฐ์ """
|
| 72 |
+
value = float(value - 1) * 100 # 0-2 ๋ฒ์๋ฅผ -100์์ +100์ผ๋ก ๋ณํ
|
| 73 |
+
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
|
| 74 |
+
h, s, v = cv2.split(hsv)
|
| 75 |
+
s = cv2.add(s, value)
|
| 76 |
+
s = np.clip(s, 0, 255)
|
| 77 |
+
final_hsv = cv2.merge((h, s, v))
|
| 78 |
+
return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
|
| 79 |
+
|
| 80 |
+
def adjust_temperature(image, value):
|
| 81 |
+
"""์ด๋ฏธ์ง ์์จ๋ ์กฐ์ (์์ ๋ฐธ๋ฐ์ค)"""
|
| 82 |
+
value = float(value) * 30 # ํจ๊ณผ ์ค์ผ์ผ ์กฐ์
|
| 83 |
+
b, g, r = cv2.split(image)
|
| 84 |
+
if value > 0: # ๋ฐ๋ปํ๊ฒ
|
| 85 |
+
r = cv2.add(r, value)
|
| 86 |
+
b = cv2.subtract(b, value)
|
| 87 |
+
else: # ์ฐจ๊ฐ๊ฒ
|
| 88 |
+
r = cv2.add(r, value)
|
| 89 |
+
b = cv2.subtract(b, value)
|
| 90 |
+
|
| 91 |
+
r = np.clip(r, 0, 255)
|
| 92 |
+
b = np.clip(b, 0, 255)
|
| 93 |
+
return cv2.merge([b, g, r])
|
| 94 |
+
|
| 95 |
+
def adjust_tint(image, value):
|
| 96 |
+
"""์ด๋ฏธ์ง ์์กฐ ์กฐ์ """
|
| 97 |
+
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
|
| 98 |
+
h, s, v = cv2.split(hsv_image)
|
| 99 |
+
h = cv2.add(h, int(value))
|
| 100 |
+
h = np.clip(h, 0, 179) # Hue ๊ฐ์ 0-179 ๋ฒ์
|
| 101 |
+
final_hsv = cv2.merge((h, s, v))
|
| 102 |
+
return cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
|
| 103 |
+
|
| 104 |
+
def adjust_exposure(image, value):
|
| 105 |
+
"""์ด๋ฏธ์ง ๋
ธ์ถ ์กฐ์ """
|
| 106 |
+
enhancer = ImageEnhance.Brightness(Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)))
|
| 107 |
+
img_enhanced = enhancer.enhance(1 + float(value) / 5.0)
|
| 108 |
+
return cv2.cvtColor(np.array(img_enhanced), cv2.COLOR_RGB2BGR)
|
| 109 |
+
|
| 110 |
+
def adjust_vibrance(image, value):
|
| 111 |
+
"""์ด๋ฏธ์ง ํ๊ธฐ ์กฐ์ """
|
| 112 |
+
img = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
| 113 |
+
converter = ImageEnhance.Color(img)
|
| 114 |
+
factor = 1 + (float(value) / 100.0)
|
| 115 |
+
img = converter.enhance(factor)
|
| 116 |
+
return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
|
| 117 |
+
|
| 118 |
+
def adjust_color_mixer_blues(image, value):
|
| 119 |
+
"""์ด๋ฏธ์ง ์ปฌ๋ฌ ๋ฏน์ (๋ธ๋ฃจ) ์กฐ์ """
|
| 120 |
+
b, g, r = cv2.split(image)
|
| 121 |
+
b = cv2.add(b, float(value))
|
| 122 |
+
b = np.clip(b, 0, 255)
|
| 123 |
+
return cv2.merge([b, g, r])
|
| 124 |
+
|
| 125 |
+
def adjust_shadows(image, value):
|
| 126 |
+
"""์ด๋ฏธ์ง ๊ทธ๋ฆผ์ ์กฐ์ """
|
| 127 |
+
pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
| 128 |
+
enhancer = ImageEnhance.Brightness(pil_image)
|
| 129 |
+
factor = 1 + (float(value) / 100.0)
|
| 130 |
+
pil_image = enhancer.enhance(factor)
|
| 131 |
+
return cv2.cvtColor(np.array(pil_image), cv2.COLOR_BGR2RGB)
|
| 132 |
+
|
| 133 |
+
def process_image(image, brightness, contrast, saturation, temperature, tint, exposure, vibrance, color_mixer_blues, shadows):
|
| 134 |
+
"""๋ชจ๋ ์กฐ์ ์ฌํญ์ ์ด๋ฏธ์ง์ ์ ์ฉ"""
|
| 135 |
+
if image is None:
|
| 136 |
+
return None
|
| 137 |
+
|
| 138 |
+
# PIL ์ด๋ฏธ์ง๋ฅผ OpenCV ํ์์ผ๋ก ๋ณํ
|
| 139 |
+
image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
|
| 140 |
+
|
| 141 |
+
# ์กฐ์ ์ฌํญ ์์ฐจ ์ ์ฉ
|
| 142 |
+
image = adjust_brightness(image, brightness)
|
| 143 |
+
image = adjust_contrast(image, contrast)
|
| 144 |
+
image = adjust_saturation(image, saturation)
|
| 145 |
+
image = adjust_temperature(image, temperature)
|
| 146 |
+
image = adjust_tint(image, tint)
|
| 147 |
+
image = adjust_exposure(image, exposure)
|
| 148 |
+
image = adjust_vibrance(image, vibrance)
|
| 149 |
+
image = adjust_color_mixer_blues(image, color_mixer_blues)
|
| 150 |
+
image = adjust_shadows(image, shadows)
|
| 151 |
+
|
| 152 |
+
# PIL ์ด๋ฏธ์ง๋ก ๋ค์ ๋ณํ
|
| 153 |
+
return Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
| 154 |
+
|
| 155 |
+
|
| 156 |
def translate_prompt_to_english(prompt):
|
| 157 |
# ๊ธฐ์กด ํจ์ ์ ์ง
|
| 158 |
if not re.search("[๊ฐ-ํฃ]", prompt):
|
|
|
|
| 307 |
)
|
| 308 |
)
|
| 309 |
|
| 310 |
+
# ์์ ํ์ผ์ ํญ์ JPG ํ์ฅ์๋ก ์์ฑ
|
| 311 |
+
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
|
| 312 |
temp_path = tmp.name
|
| 313 |
result_text = ""
|
| 314 |
image_found = False
|
|
|
|
| 322 |
logger.info("์๋ต์์ ์ด๋ฏธ์ง ์ถ์ถ ์ฑ๊ณต")
|
| 323 |
if not image_found:
|
| 324 |
return None, f"API์์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ์ง ๋ชปํ์ต๋๋ค. ์๋ต ํ
์คํธ: {result_text}"
|
| 325 |
+
|
| 326 |
result_img = Image.open(temp_path)
|
| 327 |
if result_img.mode == "RGBA":
|
| 328 |
+
result_img = result_img.convert("RGB") # JPG๋ ํฌ๋ช
๋๋ฅผ ์ง์ํ์ง ์์ผ๋ฏ๋ก RGB๋ก ๋ณํ
|
| 329 |
+
|
| 330 |
+
# ๋ณํ๋ ์ด๋ฏธ์ง๋ฅผ JPG๋ก ์ ์ฅ
|
| 331 |
+
result_img.save(temp_path, format="JPEG", quality=95)
|
| 332 |
+
|
| 333 |
+
# ํ์ผ ๊ฒฝ๋ก ๋ฐํ
|
| 334 |
+
return temp_path, f"์ด๋ฏธ์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์์ต๋๋ค. {result_text}"
|
| 335 |
except Exception as e:
|
| 336 |
logger.exception("์ด๋ฏธ์ง ์์ฑ ์ค ์ค๋ฅ ๋ฐ์:")
|
| 337 |
return None, f"์ค๋ฅ ๋ฐ์: {str(e)}"
|
| 338 |
|
| 339 |
def process_images_with_prompt(image1, image2, image3, prompt, variation_index=0, max_retries=3):
|
| 340 |
+
# ๊ธฐ์กด ํจ์ ๋ด์ฉ ์ ์ง
|
| 341 |
retry_count = 0
|
| 342 |
last_error = None
|
| 343 |
|
|
|
|
| 367 |
|
| 368 |
result_img, status = generate_with_images(final_prompt, valid_images, variation_index)
|
| 369 |
if result_img is not None:
|
| 370 |
+
# ์ด๋ฏธ ํ์ผ ๊ฒฝ๋ก๊ฐ ๋ฐํ๋๋ฏ๋ก ์ถ๊ฐ ์ฒ๋ฆฌ ์์ด ๊ทธ๋๋ก ๋ฐํ
|
| 371 |
return result_img, status, final_prompt
|
| 372 |
else:
|
| 373 |
last_error = status
|
|
|
|
| 383 |
return None, f"์ต๋ ์ฌ์๋ ํ์({max_retries}ํ) ์ด๊ณผ ํ ์คํจ: {last_error}", prompt
|
| 384 |
|
| 385 |
def generate_multiple_images(image1, image2, image3, prompt, progress=gr.Progress()):
|
| 386 |
+
# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ค์ด JPG๋ก ๋ณํ๋๋๋ก ์์
|
| 387 |
results = []
|
| 388 |
statuses = []
|
| 389 |
prompts = []
|
|
|
|
| 398 |
result_img, status, final_prompt = process_images_with_prompt(image1, image2, image3, prompt, i, max_retries)
|
| 399 |
|
| 400 |
if result_img is not None:
|
| 401 |
+
# ์ด๋ฏธ ํ์ผ ๊ฒฝ๋ก์ด๋ฏ๋ก ์ถ๊ฐ ์ฒ๋ฆฌ ์์ด ๊ทธ๋๋ก ์ถ๊ฐ
|
| 402 |
results.append(result_img)
|
| 403 |
statuses.append(f"์ด๋ฏธ์ง #{i+1}: {status}")
|
| 404 |
prompts.append(f"์ด๋ฏธ์ง #{i+1}: {final_prompt}")
|
|
|
|
| 419 |
|
| 420 |
return results[0], results[1], results[2], results[3], combined_status, combined_prompts
|
| 421 |
|
| 422 |
+
|
| 423 |
# GFPGAN ๊ด๋ จ ์ฝ๋ ์ ์ง
|
| 424 |
import sys
|
| 425 |
from torchvision.transforms import functional
|
|
|
|
| 963 |
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-expand-alt"></i> ์ด๋ฏธ์ง ํ์ฅ</p>
|
| 964 |
์๋ณธ ์ด๋ฏธ์ง ์ฃผ๋ณ์ ์์ฐ์ค๋ฝ๊ฒ ์ถ๊ฐ ์์ญ์ ์์ฑํ์ฌ ์ด๋ฏธ์ง๋ฅผ ํ์ฅํฉ๋๋ค.
|
| 965 |
</div>
|
| 966 |
+
|
| 967 |
</div>
|
| 968 |
</div>
|
| 969 |
</div>
|
|
|
|
| 1004 |
</p>
|
| 1005 |
</div>
|
| 1006 |
|
| 1007 |
+
|
| 1008 |
<div class="manual-section">
|
| 1009 |
+
<div class="manual-section-title"><i class="fas fa-tools"></i> ์ฃผ์ ๊ธฐ๋ฅ</div>
|
| 1010 |
+
<div class="manual-text">
|
| 1011 |
+
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem;">
|
| 1012 |
+
<div>
|
| 1013 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-exchange-alt"></i> ์ด๋ฏธ์ง ๋ณ๊ฒฝ</p>
|
| 1014 |
+
ํฌ์ฆ๋ ์คํ์ผ์ ๋ณ๊ฒฝํ๋ฉด์ ์๋ณธ์ ์ฃผ์ ์์๋ ์ ์งํฉ๋๋ค.
|
| 1015 |
+
</div>
|
| 1016 |
+
|
| 1017 |
+
<div>
|
| 1018 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-eraser"></i> ๊ธ์ ์ง์ฐ๊ธฐ/๋ณ๊ฒฝ</p>
|
| 1019 |
+
์ด๋ฏธ์ง์ ํ
์คํธ๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ์ ๊ฑฐํ๊ฑฐ๋ ๋ค๋ฅธ ํ
์คํธ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
|
| 1020 |
+
</div>
|
| 1021 |
+
|
| 1022 |
+
<div>
|
| 1023 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-tshirt"></i> ๊ฐ์ ์ํ์ฐฉ์ฉ</p>
|
| 1024 |
+
๋ชจ๋ธ์๊ฒ ๋ค๋ฅธ ์ด๋ฏธ์ง์ ์ํ์ ์์ฐ์ค๋ฝ๊ฒ ์ฐฉ์ฉ์ํต๋๋ค.
|
| 1025 |
+
</div>
|
| 1026 |
+
|
| 1027 |
+
<div>
|
| 1028 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-image"></i> ๋ฐฐ๊ฒฝ ๋ฐ๊พธ๊ธฐ</p>
|
| 1029 |
+
์ฃผ์ ํผ์ฌ์ฒด๋ ์ ์งํ๋ฉฐ ๋ฐฐ๊ฒฝ๋ง ๊ต์ฒดํฉ๋๋ค.
|
| 1030 |
+
</div>
|
| 1031 |
+
|
| 1032 |
+
<div>
|
| 1033 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-cut"></i> ๋ถ๋ถ ์ง์ฐ๊ธฐ</p>
|
| 1034 |
+
์ด๋ฏธ์ง์ ํน์ ๋ถ๋ถ์ ์ง์ฐ๊ณ ๋ฐฐ๊ฒฝ๊ณผ ์์ฐ์ค๋ฝ๊ฒ ์กฐํ๋๋๋ก ์ฑ์๋๋ค.
|
| 1035 |
+
</div>
|
| 1036 |
+
|
| 1037 |
+
<div>
|
| 1038 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-wine-glass"></i> ์ํ๋ค๊ณ ์๊ธฐ</p>
|
| 1039 |
+
๋ชจ๋ธ์ด ์ํ์ ๋ค๊ณ ์๋ ์์ฐ์ค๋ฌ์ด ํฌ์ฆ์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํฉ๋๋ค.
|
| 1040 |
+
</div>
|
| 1041 |
+
|
| 1042 |
+
<div>
|
| 1043 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-expand-alt"></i> ์ด๋ฏธ์ง ํ์ฅ</p>
|
| 1044 |
+
์๋ณธ ์ด๋ฏธ์ง ์ฃผ๋ณ์ ์์ฐ์ค๋ฝ๊ฒ ์ถ๊ฐ ์์ญ์ ์์ฑํ์ฌ ์ด๋ฏธ์ง๋ฅผ ํ์ฅํฉ๋๋ค.
|
| 1045 |
+
</div>
|
| 1046 |
+
|
| 1047 |
+
<div>
|
| 1048 |
+
<p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-utensils"></i> ์์ ํ๋ ์ดํ
</p>
|
| 1049 |
+
์์์ ํน์ ์ฉ๊ธฐ์ ๋ด์ ์์
์ ์ธ ๊ฐ๋๋ก ์๋ฆ๋ต๊ฒ ํ๋ ์ดํ
ํฉ๋๋ค.
|
| 1050 |
+
</div>
|
| 1051 |
+
</div>
|
| 1052 |
+
</div>
|
| 1053 |
</div>
|
|
|
|
| 1054 |
""")
|
| 1055 |
+
|
| 1056 |
with gr.TabItem("โจ ์ด์ปค๋จธ์ค ์ด๋ฏธ์ง ์์ฑ๊ธฐ", elem_classes="tab-content"):
|
| 1057 |
with gr.Row(equal_height=True):
|
| 1058 |
with gr.Column(scale=1):
|
|
|
|
| 1083 |
background_change_btn = gr.Button('๐ผ๏ธ ๋ฐฐ๊ฒฝ ๋ฐ๊พธ๊ธฐ', elem_classes="custom-button")
|
| 1084 |
composite_product_btn = gr.Button('โ๏ธ ๋ถ๋ถ ์ง์ฐ๊ธฐ', elem_classes="custom-button")
|
| 1085 |
outpainting_btn = gr.Button('๐ ์ด๋ฏธ์ง ํ์ฅ', elem_classes="custom-button")
|
| 1086 |
+
food_plating_btn = gr.Button('๐ฝ๏ธ ์์ํ๋ ์ดํ
', elem_classes="custom-button") # ์๋ก ์ถ๊ฐ๋ ๋ฒํผ
|
| 1087 |
+
|
| 1088 |
|
| 1089 |
submit_single_btn = gr.Button('โจ ์ด๋ฏธ์ง ์์ฑ (1์ฅ)', elem_classes="custom-button primary")
|
| 1090 |
submit_btn = gr.Button('โจ ์ด๋ฏธ์ง ์์ฑ (4์ฅ)', elem_classes="custom-button primary")
|
|
|
|
| 1094 |
gr.HTML('<div class="section-title"><i class="fas fa-images"></i> ์์ฑ๋ ์ด๋ฏธ์ง</div>')
|
| 1095 |
with gr.Row():
|
| 1096 |
with gr.Column():
|
| 1097 |
+
output_image1 = gr.Image(label="์ด๋ฏธ์ง #1", elem_classes="image-container", height=400, type="filepath")
|
| 1098 |
+
output_image3 = gr.Image(label="์ด๋ฏธ์ง #3", elem_classes="image-container", height=400, type="filepath")
|
| 1099 |
with gr.Column():
|
| 1100 |
+
output_image2 = gr.Image(label="์ด๋ฏธ์ง #2", elem_classes="image-container", height=400, type="filepath")
|
| 1101 |
+
output_image4 = gr.Image(label="์ด๋ฏธ์ง #4", elem_classes="image-container", height=400, type="filepath")
|
| 1102 |
|
| 1103 |
gr.HTML('<div class="section-title"><i class="fas fa-info-circle"></i> ๊ฒฐ๊ณผ ์ ๋ณด</div>')
|
| 1104 |
output_text = gr.Textbox(label="์ํ ๋ฉ์์ง", lines=2, elem_classes="custom-input")
|
|
|
|
| 1116 |
["down/๋ชจ๋ธ.jpg", "down/์์ธ์.png", None, "(#1์ ์ฌ์ฑ๋ชจ๋ธ)์ด(#2์ ์์ธ์)์ ๋ค๊ณ ์๋ ์์ฐ์ค๋ฌ์ด ๋ชจ์ต"],
|
| 1117 |
["down/๋ชจ๋ธ.jpg", "down/์นดํ์ ๊ฒฝ.png", None, "(#1์ ์ฌ์ฑ๋ชจ๋ธ)์ด (#2 ์นดํ)์์ ์์ฐ์ค๋ฝ๊ฒ ์๋ ๋ชจ์ต"],
|
| 1118 |
["down/์์ด๋ ๊ณ ๋ชจํ.png", None, None, "(#1์ ๋ ๊ณ ๋ชจํ)์์ ์ฒญ์์์ด๋ ๊ณ ๋ฅผ ์ ๊ฑฐํ ํ, ๊ทธ ์๋ฆฌ๋ฅผ ์ฃผ๋ณ ๋ฐฐ๊ฒฝ๊ณผ ์์ฐ์ค๋ฝ๊ฒ ์ด์ฐ๋ฌ์ง๋๋ก ์ฑ์์ฃผ์ธ์. ๋จ, ์ด๋ฏธ์ง์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ฃผ์ ์์๋ ๋์ผํ๊ฒ ์ ์งํด ํด์ผํ๋ค."],
|
| 1119 |
+
["down/์นดํ์ ๊ฒฝ.png", None, None, "(#1 ์ด๋ฏธ์ง)๋ฅผ ์๋ณธ๊ทธ๋๋ก ์ค์์ ๋๊ณ ๋น์จ๋ก ์ ์งํ ์ฒด ์์๋ ๋ฐ ์ข์ฐ๋ก ํฌ๊ฒ ํ์ฅํ๋ผ."],
|
| 1120 |
+
["down/์๋ฌ๋.png", "down/์ฉ๊ธฐ.png", None, "(#1์ ์๋ฌ๋)๊ฐ ์์๋ง์ผ๋ก ๋ฐ๋์(#2์ ๋์ผํ ์ฉ๊ธฐ)์ ๊ฝ ์ฐจ๋๋ก ์์
์ ์ธ ๊ฐ๋๋ก ์ด์ธ๋ฆฌ๋ ์ํ๊ณผ ํจ๊ป ํ๋ ์ดํ
ํ ๋ชจ์ต"]
|
| 1121 |
]
|
| 1122 |
|
| 1123 |
gr.Examples(
|
| 1124 |
examples=examples,
|
| 1125 |
inputs=[image1_input, image2_input, image3_input, prompt_input]
|
| 1126 |
)
|
| 1127 |
+
|
| 1128 |
with gr.TabItem("๐ ์ด๋ฏธ์ง ์
์ค์ผ์ผ๋ฌ", elem_classes="tab-content"):
|
| 1129 |
with gr.Row():
|
| 1130 |
with gr.Column(elem_classes="panel"):
|
|
|
|
| 1175 |
with gr.Row():
|
| 1176 |
bg_remove_status = gr.Textbox(label="์ํ", lines=2, elem_classes="custom-input")
|
| 1177 |
bg_remove_btn = gr.Button('โ๏ธ ๋ฐฐ๊ฒฝ ์ ๊ฑฐํ๊ธฐ', elem_classes="custom-button primary")
|
| 1178 |
+
|
| 1179 |
+
# ์ด๋ฏธ์ง ํํฐ ํญ UI ๊ฐ์
|
| 1180 |
+
with gr.TabItem("๐๏ธ ์ด๋ฏธ์ง ํํฐ", elem_classes="tab-content"):
|
| 1181 |
+
with gr.Column(elem_classes="panel"):
|
| 1182 |
+
gr.HTML('<div class="section-title"><i class="fas fa-sliders-h"></i> ์ด๋ฏธ์ง ํํฐ</div>')
|
| 1183 |
+
gr.HTML("""
|
| 1184 |
+
<p style="margin-bottom: 1rem; font-size: 1.05rem;">
|
| 1185 |
+
์ด๋ฏธ์ง ํํฐ๋ฅผ ์ ์ฉํ์ฌ ์์๊ณผ ํค์ ์กฐ์ ํฉ๋๋ค.
|
| 1186 |
+
</p>
|
| 1187 |
+
<div class="tip-box">
|
| 1188 |
+
<i class="fas fa-lightbulb"></i> <strong>ํ:</strong> ์ฌ๋ผ์ด๋๋ฅผ ์กฐ์ ํ์ฌ ์ด๋ฏธ์ง์ ๋ฐ๊ธฐ, ๋๋น, ์ฑ๋ ๋ฑ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
|
| 1189 |
+
</div>
|
| 1190 |
+
""")
|
| 1191 |
+
|
| 1192 |
+
# ์
๋ ฅ/์ถ๋ ฅ ์ด๋ฏธ์ง ์น์
|
| 1193 |
+
with gr.Row():
|
| 1194 |
+
with gr.Column():
|
| 1195 |
+
gr.HTML('<div class="section-title"><i class="fas fa-upload"></i> ์
๋ ฅ ์ด๋ฏธ์ง</div>')
|
| 1196 |
+
filter_input_image = gr.Image(type="pil", label="์
๋ก๋", elem_classes="image-container")
|
| 1197 |
+
|
| 1198 |
+
with gr.Column():
|
| 1199 |
+
gr.HTML('<div class="section-title"><i class="fas fa-image"></i> ๊ฒฐ๊ณผ ์ด๋ฏธ์ง</div>')
|
| 1200 |
+
filter_output_image = gr.Image(type="pil", label="ํํฐ ์ ์ฉ ๊ฒฐ๊ณผ", elem_classes="image-container")
|
| 1201 |
+
|
| 1202 |
+
# ํํฐ ์กฐ์ ์ฌ๋ผ์ด๋๋ค
|
| 1203 |
+
gr.HTML('<div class="section-title"><i class="fas fa-sliders-h"></i> ํํฐ ์กฐ์ </div>')
|
| 1204 |
+
with gr.Group():
|
| 1205 |
+
brightness_slider = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="๋ฐ๊ธฐ ์กฐ์ ")
|
| 1206 |
+
contrast_slider = gr.Slider(0.5, 1.5, value=1.0, step=0.1, label="๋๋น ์กฐ์ ")
|
| 1207 |
+
saturation_slider = gr.Slider(0.0, 2.0, value=1.0, step=0.1, label="์ฑ๋ ์กฐ์ ")
|
| 1208 |
+
temperature_slider = gr.Slider(-1.0, 1.0, value=0.0, step=0.1, label="์์จ๋ ์กฐ์ ")
|
| 1209 |
+
tint_slider = gr.Slider(-100, 100, value=0, step=1, label="์์กฐ ์กฐ์ ")
|
| 1210 |
+
exposure_slider = gr.Slider(-5.0, 5.0, value=0.0, step=0.1, label="๋
ธ์ถ ์กฐ์ ")
|
| 1211 |
+
vibrance_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="ํ๊ธฐ ์กฐ์ ")
|
| 1212 |
+
color_mixer_blues_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="์ปฌ๋ฌ ๋ฏน์ (๋ธ๋ฃจ)")
|
| 1213 |
+
shadows_slider = gr.Slider(-100.0, 100.0, value=0.0, step=1.0, label="๊ทธ๋ฆผ์ ์กฐ์ ")
|
| 1214 |
+
|
| 1215 |
+
# ์ด๋ฏธ์ง ์ฒ๋ฆฌ ํจ์ ์ฐ๊ฒฐ
|
| 1216 |
+
inputs = [
|
| 1217 |
+
filter_input_image,
|
| 1218 |
+
brightness_slider,
|
| 1219 |
+
contrast_slider,
|
| 1220 |
+
saturation_slider,
|
| 1221 |
+
temperature_slider,
|
| 1222 |
+
tint_slider,
|
| 1223 |
+
exposure_slider,
|
| 1224 |
+
vibrance_slider,
|
| 1225 |
+
color_mixer_blues_slider,
|
| 1226 |
+
shadows_slider
|
| 1227 |
+
]
|
| 1228 |
+
|
| 1229 |
+
input_components = [
|
| 1230 |
+
brightness_slider,
|
| 1231 |
+
contrast_slider,
|
| 1232 |
+
saturation_slider,
|
| 1233 |
+
temperature_slider,
|
| 1234 |
+
tint_slider,
|
| 1235 |
+
exposure_slider,
|
| 1236 |
+
vibrance_slider,
|
| 1237 |
+
color_mixer_blues_slider,
|
| 1238 |
+
shadows_slider
|
| 1239 |
+
]
|
| 1240 |
+
|
| 1241 |
+
for input_component in input_components:
|
| 1242 |
+
input_component.change(
|
| 1243 |
+
fn=process_image,
|
| 1244 |
+
inputs=inputs,
|
| 1245 |
+
outputs=filter_output_image
|
| 1246 |
+
)
|
| 1247 |
+
|
| 1248 |
+
filter_input_image.change(
|
| 1249 |
+
fn=lambda x, *args: process_image(x, *args) if x is not None else None,
|
| 1250 |
+
inputs=inputs,
|
| 1251 |
+
outputs=filter_output_image
|
| 1252 |
+
)
|
| 1253 |
+
|
| 1254 |
|
| 1255 |
# ๋ฒํผ ์ด๋ฒคํธ ์ฐ๊ฒฐ
|
| 1256 |
image_change_btn1.click(
|
|
|
|
| 1304 |
inputs=[],
|
| 1305 |
outputs=prompt_input
|
| 1306 |
)
|
| 1307 |
+
|
| 1308 |
+
food_plating_btn.click(
|
| 1309 |
+
fn=lambda: "(#1์ ์๋ฌ๋)๊ฐ ์์๋ง์ผ๋ก ๋ฐ๋์(#2์ ๋์ผํ ์ฉ๊ธฐ)์ ๊ฝ ์ฐจ๋๋ก ์์
์ ์ธ ๊ฐ๋๋ก ์ด์ธ๋ฆฌ๋ ์ํ๊ณผ ํจ๊ป ํ๋ ์ดํ
ํ ๋ชจ์ต",
|
| 1310 |
+
inputs=[],
|
| 1311 |
+
outputs=prompt_input
|
| 1312 |
+
)
|
| 1313 |
|
| 1314 |
# ๋จ์ผ ์ด๋ฏธ์ง ์์ฑ ๋ฒํผ ์ด๋ฒคํธ ์ฐ๊ฒฐ
|
| 1315 |
submit_single_btn.click(
|