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(
|