Kims12 commited on
Commit
96e0832
ยท
verified ยท
1 Parent(s): 24551ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1 -1341
app.py CHANGED
@@ -1,1342 +1,2 @@
1
  import os
2
- import tempfile
3
- from PIL import Image
4
- import gradio as gr
5
- import logging
6
- import re
7
- import time
8
-
9
- from google import genai
10
- from google.genai import types
11
- from dotenv import load_dotenv
12
- from transformers import pipeline # ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ import
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__)
20
-
21
- # ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
22
- def remove_background(image):
23
- if image is None:
24
- return None, "์ด๋ฏธ์ง€๊ฐ€ ์—…๋กœ๋“œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
25
-
26
- try:
27
- logger.info("๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ์‹œ์ž‘")
28
-
29
- # ๋ชจ๋ธ์„ ์ฒ˜์Œ ๋กœ๋“œํ•  ๋•Œ๋Š” ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Œ
30
- pipe = pipeline("image-segmentation", model="briaai/RMBG-1.4", trust_remote_code=True)
31
-
32
- # ๋ฐฐ๊ฒฝ์ด ์ œ๊ฑฐ๋œ ์ด๋ฏธ์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ
33
- output_image = pipe(image)
34
-
35
- logger.info("๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ์™„๋ฃŒ")
36
- return output_image, "๋ฐฐ๊ฒฝ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
37
- except Exception as e:
38
- logger.exception("๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
39
- return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
40
-
41
-
42
- def save_binary_file(file_name, data):
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):
159
- return prompt
160
-
161
- prompt = prompt.replace("#1", "IMAGE_TAG_ONE")
162
- prompt = prompt.replace("#2", "IMAGE_TAG_TWO")
163
- prompt = prompt.replace("#3", "IMAGE_TAG_THREE")
164
-
165
- try:
166
- api_key = os.environ.get("GEMINI_API_KEY")
167
- if not api_key:
168
- logger.error("Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
169
- prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
170
- prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
171
- prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
172
- return prompt
173
-
174
- client = genai.Client(api_key=api_key)
175
- translation_prompt = f"""
176
- Translate the following Korean text to English:
177
-
178
- {prompt}
179
-
180
- IMPORTANT: The tokens IMAGE_TAG_ONE, IMAGE_TAG_TWO, and IMAGE_TAG_THREE are special tags
181
- and must be preserved exactly as is in your translation. Do not translate these tokens.
182
- """
183
-
184
- logger.info(f"Translation prompt: {translation_prompt}")
185
- response = client.models.generate_content(
186
- model="gemini-2.0-flash",
187
- contents=[translation_prompt],
188
- config=types.GenerateContentConfig(
189
- response_modalities=['Text'],
190
- temperature=0.2,
191
- top_p=0.95,
192
- top_k=40,
193
- max_output_tokens=512
194
- )
195
- )
196
-
197
- translated_text = ""
198
- for part in response.candidates[0].content.parts:
199
- if hasattr(part, 'text') and part.text:
200
- translated_text += part.text
201
-
202
- if translated_text.strip():
203
- translated_text = translated_text.replace("IMAGE_TAG_ONE", "#1")
204
- translated_text = translated_text.replace("IMAGE_TAG_TWO", "#2")
205
- translated_text = translated_text.replace("IMAGE_TAG_THREE", "#3")
206
- logger.info(f"Translated text: {translated_text.strip()}")
207
- return translated_text.strip()
208
- else:
209
- logger.warning("๋ฒˆ์—ญ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์›๋ณธ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ")
210
- prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
211
- prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
212
- prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
213
- return prompt
214
- except Exception as e:
215
- logger.exception("๋ฒˆ์—ญ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
216
- prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
217
- prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
218
- prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
219
- return prompt
220
-
221
- def preprocess_prompt(prompt, image1, image2, image3):
222
- # ๊ธฐ์กด ํ•จ์ˆ˜ ์œ ์ง€
223
- has_img1 = image1 is not None
224
- has_img2 = image2 is not None
225
- has_img3 = image3 is not None
226
-
227
- if "#1" in prompt and not has_img1:
228
- prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
229
- else:
230
- prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
231
-
232
- if "#2" in prompt and not has_img2:
233
- prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
234
- else:
235
- prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
236
-
237
- if "#3" in prompt and not has_img3:
238
- prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
239
- else:
240
- prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
241
-
242
- if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
243
- desc_match = re.search(r'#1์„ "(.*?)"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ', prompt)
244
- if desc_match:
245
- description = desc_match.group(1)
246
- prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ {description}์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์›๋ณธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ๋‚ด์šฉ์€ ์œ ์ง€ํ•˜๋˜ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๊ณผ ๋ถ„์œ„๊ธฐ๋กœ ์žฌํ•ด์„ํ•ด์ฃผ์„ธ์š”."
247
- else:
248
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
249
-
250
- elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
251
- text_match = re.search(r'#1์—์„œ "(.*?)"๋ฅผ ์ง€์›Œ๋ผ', prompt)
252
- if text_match:
253
- text_to_remove = text_match.group(1)
254
- prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ '{text_to_remove}' ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋˜ ๋ถ€๋ถ„์„ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ์ฑ„์›Œ์ฃผ์„ธ์š”."
255
- else:
256
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ๊น”๋”ํ•œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
257
-
258
- elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
259
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ๏ฟฝ๏ฟฝ์˜ ์˜์ƒ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
260
-
261
- elif "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ" in prompt:
262
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
263
-
264
- elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
265
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€)๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ๋‹๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
266
-
267
- prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ์ด๋ฏธ์ง€์— ํ…์ŠคํŠธ๋‚˜ ๊ธ€์ž๋ฅผ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”."
268
- return prompt
269
-
270
- def generate_with_images(prompt, images, variation_index=0):
271
- # ๊ธฐ์กด ํ•จ์ˆ˜ ์œ ์ง€
272
- try:
273
- api_key = os.environ.get("GEMINI_API_KEY")
274
- if not api_key:
275
- return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
276
-
277
- client = genai.Client(api_key=api_key)
278
- logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
279
-
280
- variation_suffixes = [
281
- " Create this as the first variation. Do not add any text, watermarks, or labels to the image.",
282
- " Create this as the second variation with more vivid colors. Do not add any text, watermarks, or labels to the image.",
283
- " Create this as the third variation with a more creative style. Do not add any text, watermarks, or labels to the image.",
284
- " Create this as the fourth variation with enhanced details. Do not add any text, watermarks, or labels to the image."
285
- ]
286
-
287
- if variation_index < len(variation_suffixes):
288
- prompt = prompt + variation_suffixes[variation_index]
289
- else:
290
- prompt = prompt + " Do not add any text, watermarks, or labels to the image."
291
-
292
- contents = [prompt]
293
- for idx, img in enumerate(images, 1):
294
- if img is not None:
295
- contents.append(img)
296
- logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
297
-
298
- response = client.models.generate_content(
299
- model="gemini-2.0-flash-exp-image-generation",
300
- contents=contents,
301
- config=types.GenerateContentConfig(
302
- response_modalities=['Text', 'Image'],
303
- temperature=1,
304
- top_p=0.95,
305
- top_k=40,
306
- max_output_tokens=8192
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
315
- for part in response.candidates[0].content.parts:
316
- if hasattr(part, 'text') and part.text:
317
- result_text += part.text
318
- logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
319
- elif hasattr(part, 'inline_data') and part.inline_data:
320
- save_binary_file(temp_path, part.inline_data.data)
321
- image_found = True
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
-
344
- while retry_count < max_retries:
345
- try:
346
- images = [image1, image2, image3]
347
- valid_images = [img for img in images if img is not None]
348
- if not valid_images:
349
- return None, "์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
350
-
351
- if prompt and prompt.strip():
352
- processed_prompt = preprocess_prompt(prompt, image1, image2, image3)
353
- if re.search("[๊ฐ€-ํžฃ]", processed_prompt):
354
- final_prompt = translate_prompt_to_english(processed_prompt)
355
- else:
356
- final_prompt = processed_prompt
357
- else:
358
- if len(valid_images) == 1:
359
- 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."
360
- logger.info("Default prompt generated for single image")
361
- elif len(valid_images) == 2:
362
- 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."
363
- logger.info("Default prompt generated for two images")
364
- else:
365
- 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."
366
- logger.info("Default prompt generated for three images")
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
374
- retry_count += 1
375
- logger.warning(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹คํŒจ, ์žฌ์‹œ๋„ {retry_count}/{max_retries}: {status}")
376
- time.sleep(1)
377
- except Exception as e:
378
- last_error = str(e)
379
- retry_count += 1
380
- logger.exception(f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ, ์žฌ์‹œ๋„ {retry_count}/{max_retries}:")
381
- time.sleep(1)
382
-
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 = []
390
-
391
- num_images = 4
392
- max_retries = 3
393
-
394
- progress(0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค€๋น„ ์ค‘...")
395
-
396
- for i in range(num_images):
397
- progress((i / num_images), desc=f"{i+1}/{num_images} ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘...")
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}")
405
- else:
406
- results.append(None)
407
- statuses.append(f"์ด๋ฏธ์ง€ #{i+1} ์ƒ์„ฑ ์‹คํŒจ: {status}")
408
- prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
409
-
410
- time.sleep(1)
411
-
412
- progress(1.0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์™„๋ฃŒ!")
413
-
414
- while len(results) < 4:
415
- results.append(None)
416
-
417
- combined_status = "\n".join(statuses)
418
- combined_prompts = "\n".join(prompts)
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
426
- sys.modules["torchvision.transforms.functional_tensor"] = functional
427
-
428
- from basicsr.archs.srvgg_arch import SRVGGNetCompact
429
- from gfpgan.utils import GFPGANer
430
- from realesrgan.utils import RealESRGANer
431
-
432
- import torch
433
- import cv2
434
-
435
- # ํ•„์š”ํ•œ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ
436
- if not os.path.exists('realesr-general-x4v3.pth'):
437
- os.system("wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth -P .")
438
- if not os.path.exists('GFPGANv1.4.pth'):
439
- os.system("wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth -P .")
440
- if not os.path.exists('RestoreFormer.pth'):
441
- os.system("wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/RestoreFormer.pth -P .")
442
-
443
- model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
444
- model_path = 'realesr-general-x4v3.pth'
445
- half = True if torch.cuda.is_available() else False
446
- upsampler = RealESRGANer(scale=4, model_path=model_path, model=model, tile=0, tile_pad=10, pre_pad=0, half=half)
447
-
448
- def upscaler(img, version, scale):
449
- try:
450
- img = cv2.imread(img, cv2.IMREAD_UNCHANGED)
451
- if len(img.shape) == 3 and img.shape[2] == 4:
452
- img_mode = 'RGBA'
453
- elif len(img.shape) == 2:
454
- img_mode = None
455
- img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
456
- else:
457
- img_mode = None
458
-
459
- h, w = img.shape[0:2]
460
- if h < 300:
461
- img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4)
462
-
463
- face_enhancer = GFPGANer(
464
- model_path=f'{version}.pth',
465
- upscale=2,
466
- arch='RestoreFormer' if version=='RestoreFormer' else 'clean',
467
- channel_multiplier=2,
468
- bg_upsampler=upsampler
469
- )
470
-
471
- try:
472
- _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True)
473
- except RuntimeError as error:
474
- print('์˜ค๋ฅ˜ ๋ฐœ์ƒ:', error)
475
-
476
- try:
477
- if scale != 2:
478
- interpolation = cv2.INTER_AREA if scale < 2 else cv2.INTER_LANCZOS4
479
- h, w = img.shape[0:2]
480
- output = cv2.resize(output, (int(w * scale / 2), int(h * scale / 2)), interpolation=interpolation)
481
- except Exception as error:
482
- print('์ž˜๋ชป๋œ ์Šค์ผ€์ผ ์ž…๋ ฅ:', error)
483
-
484
- output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
485
- return output
486
- except Exception as error:
487
- print('์ „์ฒด ์˜ˆ์™ธ ๋ฐœ์ƒ:', error)
488
- return None
489
-
490
- def upscaler_korean(img):
491
- return upscaler(img, "GFPGANv1.4", 2)
492
-
493
- # ์ปค์Šคํ…€ CSS ์Šคํƒ€์ผ
494
- custom_css = """
495
- :root {
496
- --primary-color: #5561e9;
497
- --secondary-color: #6c8aff;
498
- --accent-color: #ff6b6b;
499
- --background-color: #f0f5ff;
500
- --card-bg: #ffffff;
501
- --text-color: #334155;
502
- --border-radius: 18px;
503
- --shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
504
- }
505
-
506
- body {
507
- font-family: 'Pretendard', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
508
- background-color: var(--background-color);
509
- color: var(--text-color);
510
- line-height: 1.6;
511
- }
512
-
513
- /* Gradio ์ปจํ…Œ์ด๋„ˆ ์˜ค๋ฒ„๋ผ์ด๋“œ */
514
- .gradio-container {
515
- max-width: 100% !important;
516
- margin: 0 auto !important;
517
- padding: 0 !important;
518
- background-color: var(--background-color) !important;
519
- }
520
-
521
- /* ์ƒ๋‹จ ํ—ค๋” */
522
- .app-header {
523
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
524
- color: white;
525
- padding: 2rem;
526
- border-radius: var(--border-radius);
527
- margin-bottom: 1.5rem;
528
- box-shadow: var(--shadow);
529
- text-align: center;
530
- }
531
-
532
- .app-header h1 {
533
- margin: 0;
534
- font-size: 2.5rem;
535
- font-weight: 700;
536
- letter-spacing: -0.5px;
537
- }
538
-
539
- .app-header p {
540
- margin: 0.75rem 0 0;
541
- font-size: 1.1rem;
542
- opacity: 0.9;
543
- }
544
-
545
- /* ํŒจ๋„ ์Šคํƒ€์ผ๋ง */
546
- .panel {
547
- background-color: var(--card-bg);
548
- border-radius: var(--border-radius);
549
- box-shadow: var(--shadow);
550
- padding: 1.5rem;
551
- margin-bottom: 1.5rem;
552
- border: 1px solid rgba(0, 0, 0, 0.04);
553
- transition: transform 0.3s ease;
554
- }
555
-
556
- .panel:hover {
557
- transform: translateY(-5px);
558
- }
559
-
560
- /* ์„น์…˜ ์ œ๋ชฉ */
561
- .section-title {
562
- font-size: 1.5rem;
563
- font-weight: 700;
564
- color: var(--primary-color);
565
- margin-bottom: 1rem;
566
- padding-bottom: 0.5rem;
567
- border-bottom: 2px solid var(--secondary-color);
568
- display: flex;
569
- align-items: center;
570
- }
571
-
572
- .section-title i {
573
- margin-right: 0.5rem;
574
- font-size: 1.4rem;
575
- }
576
-
577
- /* ๋ฒ„ํŠผ ์Šคํƒ€์ผ๋ง */
578
- .custom-button {
579
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
580
- color: white !important;
581
- border: none !important;
582
- border-radius: calc(var(--border-radius) - 5px) !important;
583
- padding: 0.8rem 1.2rem !important;
584
- font-weight: 600 !important;
585
- cursor: pointer !important;
586
- transition: all 0.3s ease !important;
587
- box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
588
- text-transform: none !important;
589
- display: flex !important;
590
- align-items: center !important;
591
- justify-content: center !important;
592
- }
593
-
594
- .custom-button:hover {
595
- transform: translateY(-2px) !important;
596
- box-shadow: 0 7px 14px rgba(50, 50, 93, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08) !important;
597
- }
598
-
599
- .custom-button.primary {
600
- background: linear-gradient(135deg, var(--accent-color), #ff9a8b) !important;
601
- }
602
-
603
- .custom-button i {
604
- margin-right: 0.5rem;
605
- }
606
-
607
- /* ์ด๋ฏธ์ง€ ์ปจํ…Œ์ด๋„ˆ */
608
- .image-container {
609
- border-radius: var(--border-radius);
610
- overflow: hidden;
611
- border: 1px solid rgba(0, 0, 0, 0.08);
612
- transition: all 0.3s ease;
613
- background-color: white;
614
- }
615
-
616
- .image-container:hover {
617
- box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
618
- }
619
-
620
- /* ํƒญ ์ปจํ…Œ์ด๋„ˆ */
621
- .custom-tabs {
622
- background-color: transparent !important;
623
- border: none !important;
624
- margin-bottom: 1rem;
625
- }
626
-
627
- .custom-tabs button {
628
- background-color: rgba(255, 255, 255, 0.7) !important;
629
- border: none !important;
630
- border-radius: var(--border-radius) var(--border-radius) 0 0 !important;
631
- padding: 0.8rem 1.5rem !important;
632
- font-weight: 600 !important;
633
- color: var(--text-color) !important;
634
- transition: all 0.3s ease !important;
635
- }
636
-
637
- .custom-tabs button[aria-selected="true"] {
638
- background-color: var(--primary-color) !important;
639
- color: white !important;
640
- }
641
-
642
- /* ์ž…๋ ฅ ํ•„๋“œ */
643
- .custom-input {
644
- border-radius: calc(var(--border-radius) - 5px) !important;
645
- border: 1px solid rgba(0, 0, 0, 0.1) !important;
646
- padding: 0.8rem 1rem !important;
647
- transition: all 0.3s ease !important;
648
- }
649
-
650
- .custom-input:focus {
651
- border-color: var(--primary-color) !important;
652
- box-shadow: 0 0 0 2px rgba(85, 97, 233, 0.2) !important;
653
- }
654
-
655
- /* ์‚ฌ์šฉ์ž ๋งค๏ฟฝ๏ฟฝ์–ผ */
656
- .user-manual {
657
- background-color: white;
658
- padding: 2rem;
659
- border-radius: var(--border-radius);
660
- box-shadow: var(--shadow);
661
- margin-top: 2rem;
662
- }
663
-
664
- .manual-title {
665
- font-size: 1.8rem;
666
- font-weight: 700;
667
- color: var(--primary-color);
668
- margin-bottom: 1.5rem;
669
- text-align: center;
670
- display: flex;
671
- align-items: center;
672
- justify-content: center;
673
- }
674
-
675
- .manual-title i {
676
- margin-right: 0.5rem;
677
- font-size: 1.8rem;
678
- }
679
-
680
- .manual-section {
681
- margin-bottom: 1.5rem;
682
- padding: 1.2rem;
683
- background-color: #f8faff;
684
- border-radius: calc(var(--border-radius) - 5px);
685
- }
686
-
687
- .manual-section-title {
688
- font-size: 1.3rem;
689
- font-weight: 700;
690
- margin-bottom: 1rem;
691
- color: var(--primary-color);
692
- display: flex;
693
- align-items: center;
694
- }
695
-
696
- .manual-section-title i {
697
- margin-right: 0.5rem;
698
- font-size: 1.2rem;
699
- }
700
-
701
- .manual-text {
702
- font-size: 1rem;
703
- line-height: 1.7;
704
- }
705
-
706
- .manual-text strong {
707
- color: var(--accent-color);
708
- }
709
-
710
- .tip-box {
711
- background-color: rgba(255, 107, 107, 0.1);
712
- border-left: 3px solid var(--accent-color);
713
- padding: 1rem 1.2rem;
714
- margin: 1rem 0;
715
- border-radius: 8px;
716
- }
717
-
718
- /* ๋ฒ„ํŠผ ๊ทธ๋ฃน */
719
- .button-grid {
720
- display: grid;
721
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
722
- gap: 0.8rem;
723
- margin-bottom: 1.2rem;
724
- }
725
-
726
- /* ๋กœ๋”ฉ ์• ๋‹ˆ๋ฉ”์ด์…˜ */
727
- .progress-container {
728
- background-color: rgba(255, 255, 255, 0.9);
729
- border-radius: var(--border-radius);
730
- padding: 2rem;
731
- box-shadow: var(--shadow);
732
- text-align: center;
733
- }
734
-
735
- .progress-bar {
736
- height: 8px;
737
- border-radius: 4px;
738
- background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
739
- margin: 1rem 0;
740
- }
741
-
742
- /* ์˜ˆ์‹œ ๊ทธ๋ฆฌ๋“œ */
743
- .examples-grid {
744
- display: grid;
745
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
746
- gap: 1rem;
747
- margin: 1.5rem 0;
748
- }
749
-
750
- .example-card {
751
- background: white;
752
- border-radius: var(--border-radius);
753
- overflow: hidden;
754
- box-shadow: var(--shadow);
755
- transition: transform 0.3s ease;
756
- }
757
-
758
- .example-card:hover {
759
- transform: translateY(-5px);
760
- }
761
-
762
- /* ๋ฐ˜์‘ํ˜• */
763
- @media (max-width: 768px) {
764
- .button-grid {
765
- grid-template-columns: repeat(2, 1fr);
766
- }
767
- }
768
-
769
- /* ์ „์ฒด ์ธํ„ฐํŽ˜์ด์Šค ๋‘ฅ๊ทผ ๋ชจ์„œ๋ฆฌ */
770
- .block, .prose, .gr-prose, .gr-form, .gr-panel {
771
- border-radius: var(--border-radius) !important;
772
- }
773
-
774
- /* ๋ฉ”์ธ ์ปจํ…์ธ  ์Šคํฌ๋กค๋ฐ” */
775
- ::-webkit-scrollbar {
776
- width: 8px;
777
- height: 8px;
778
- }
779
-
780
- ::-webkit-scrollbar-track {
781
- background: rgba(0, 0, 0, 0.05);
782
- border-radius: 10px;
783
- }
784
-
785
- ::-webkit-scrollbar-thumb {
786
- background: var(--secondary-color);
787
- border-radius: 10px;
788
- }
789
- """
790
-
791
- # FontAwesome ์•„์ด์ฝ˜ ํฌํ•จ
792
- fontawesome_link = """
793
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
794
- """
795
-
796
- # ์•ฑ ํ—ค๋” HTML
797
- header_html = """
798
- <div class="app-header">
799
- <h1>โœจ ์ด์ปค๋จธ์Šค ์ „์šฉ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ(Ver1.1) โœจ</h1>
800
- <p>์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ์ƒํ’ˆ ์ด๋ฏธ์ง€๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ์ƒ์„ฑํ•˜์„ธ์š”! ํ•œ ๋ฒˆ์˜ ํด๋ฆญ์œผ๋กœ ์ „๋ฌธ์ ์ธ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</p>
801
- </div>
802
- """
803
-
804
- # ์‚ฌ์šฉ์ž ๋งค๋‰ด์–ผ HTML
805
- user_manual_html = """
806
- <div class="user-manual">
807
- <div class="manual-title"><i class="fas fa-book"></i> ์‚ฌ์šฉ ์„ค๋ช…์„œ</div>
808
-
809
- <div class="manual-section">
810
- <div class="manual-section-title"><i class="fas fa-magic"></i> ์ด์ปค๋จธ์Šค ์ „์šฉ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</div>
811
- <p class="manual-text">
812
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">1๏ธโƒฃ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ</span><br>
813
- ์ตœ๋Œ€ 3๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.<br><br>
814
-
815
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">2๏ธโƒฃ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ ๋˜๋Š” ๋ฒ„ํŠผ ์„ ํƒ</span><br>
816
- ๋ณ€ํ™˜ํ•˜๊ณ  ์‹ถ์€ ๋‚ด์šฉ์„ ์ง์ ‘ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜, ๋ฏธ๋ฆฌ ์ •์˜๋œ ๋ฒ„ํŠผ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์„ธ์š”.<br><br>
817
-
818
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">3๏ธโƒฃ ์ด๋ฏธ์ง€ ์ƒ์„ฑ</span><br>
819
- '์ด๋ฏธ์ง€ ์ƒ์„ฑ' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด 4๊ฐ€์ง€ ๋ฒ„์ „์˜ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
820
- </p>
821
- </div>
822
-
823
- <div class="manual-section">
824
- <div class="manual-section-title"><i class="fas fa-hashtag"></i> ์ด๋ฏธ์ง€ ์ฐธ์กฐ ๋ฐฉ๋ฒ•</div>
825
- <p class="manual-text">
826
- ํ”„๋กฌํ”„ํŠธ์—์„œ ๋‹ค์Œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
827
- <ul>
828
- <li><strong style="font-size: 1.05rem;">#1</strong> - ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</li>
829
- <li><strong style="font-size: 1.05rem;">#2</strong> - ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</li>
830
- <li><strong style="font-size: 1.05rem;">#3</strong> - ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</li>
831
- </ul>
832
-
833
- <div class="tip-box">
834
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ์˜ˆ๋ฅผ ๋“ค์–ด, "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2์˜ ์„ ๊ธ€๋ผ์Šค)๋ฅผ ์ฐฉ์šฉํ•œ ๋ชจ์Šต"๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
835
- </div>
836
- </p>
837
- </div>
838
-
839
- <div class="manual-section">
840
- <div class="manual-section-title"><i class="fas fa-tools"></i> ์ฃผ์š” ๊ธฐ๋Šฅ</div>
841
- <div class="manual-text">
842
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem;">
843
- <div>
844
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-exchange-alt"></i> ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ</p>
845
- ํฌ์ฆˆ๋‚˜ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•˜๋ฉด์„œ ์›๋ณธ์˜ ์ฃผ์š” ์š”์†Œ๋Š” ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
846
- </div>
847
-
848
- <div>
849
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-eraser"></i> ๊ธ€์ž ์ง€์šฐ๊ธฐ/๋ณ€๊ฒฝ</p>
850
- ์ด๋ฏธ์ง€์˜ ํ…์ŠคํŠธ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํ…์ŠคํŠธ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
851
- </div>
852
-
853
- <div>
854
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-tshirt"></i> ๊ฐ€์ƒ ์ƒํ’ˆ์ฐฉ์šฉ</p>
855
- ๋ชจ๋ธ์—๊ฒŒ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€์˜ ์ƒํ’ˆ์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ฐฉ์šฉ์‹œํ‚ต๋‹ˆ๋‹ค.
856
- </div>
857
-
858
- <div>
859
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-image"></i> ๋ฐฐ๊ฒฝ ๋ฐ”๊พธ๊ธฐ</p>
860
- ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๋ฉฐ ๋ฐฐ๊ฒฝ๋งŒ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.
861
- </div>
862
- </div>
863
- </div>
864
- </div>
865
-
866
- <div class="manual-section">
867
- <div class="manual-section-title"><i class="fas fa-search-plus"></i> ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ</div>
868
- <p class="manual-text">
869
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">์ด๋ฏธ์ง€ ๊ฐœ์„  ๊ธฐ๋Šฅ</span><br>
870
- ์ €ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ ๊ณ ํ•ด์ƒ๋„๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์–ผ๊ตด์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณต์›ํ•ฉ๋‹ˆ๋‹ค.<br>
871
- ํŠนํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค:
872
- <ul>
873
- <li>ํ•ด์ƒ๋„๊ฐ€ ๋‚ฎ์€ ์ด๋ฏธ์ง€ ๊ฐœ์„ </li>
874
- <li>ํ๋ฆฟํ•˜๊ฑฐ๋‚˜ ๋…ธ์ด์ฆˆ๊ฐ€ ์žˆ๋Š” ์–ผ๊ตด ๋ณต์›</li>
875
- <li>์ด๋ฏธ์ง€ ์ „๋ฐ˜์ ์ธ ์„ ๋ช…๋„ ํ–ฅ์ƒ</li>
876
- </ul>
877
-
878
- <div class="tip-box">
879
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๊ฐ€ ์ž‘์„์ˆ˜๋ก ์ฒ˜๋ฆฌ ์†๋„๊ฐ€ ๋น ๋ฆ…๋‹ˆ๋‹ค. ์–ผ๊ตด์ด ํฌํ•จ๋œ ์ด๋ฏธ์ง€์—์„œ ๊ฐ€์žฅ ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
880
- </div>
881
- </p>
882
- </div>
883
- </div>
884
- """
885
-
886
- # UI ๊ตฌ์„ฑ
887
- with gr.Blocks(css=custom_css) as demo:
888
- gr.HTML(fontawesome_link)
889
- gr.HTML(header_html)
890
-
891
- with gr.Tabs(elem_classes="custom-tabs") as tabs:
892
- # ์‚ฌ์šฉ ์„ค๋ช…์„œ ํƒญ์„ ์ฒซ ๋ฒˆ์งธ๋กœ ๋ฐฐ์น˜
893
- with gr.TabItem("๐Ÿ“š ์‚ฌ์šฉ ์„ค๋ช…์„œ", elem_classes="tab-content"):
894
- gr.HTML("""
895
- <div class="user-manual">
896
- <div class="manual-title"><i class="fas fa-book"></i> ์‚ฌ์šฉ ์„ค๋ช…์„œ</div>
897
-
898
- <div class="manual-section">
899
- <div class="manual-section-title"><i class="fas fa-magic"></i> ์ด์ปค๋จธ์Šค์ „์šฉ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</div>
900
- <p class="manual-text">
901
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">1๏ธโƒฃ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ</span><br>
902
- ์ตœ๋Œ€ 3๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.<br><br>
903
-
904
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">2๏ธโƒฃ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ ๋˜๋Š” ๋ฒ„ํŠผ ์„ ํƒ</span><br>
905
- ๋ณ€ํ™˜ํ•˜๊ณ  ์‹ถ์€ ๋‚ด์šฉ์„ ์ง์ ‘ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜, ๋ฏธ๋ฆฌ ์ •์˜๋œ ๋ฒ„ํŠผ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์„ธ์š”.<br><br>
906
-
907
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">3๏ธโƒฃ ์ด๋ฏธ์ง€ ์ƒ์„ฑ</span><br>
908
- '์ด๋ฏธ์ง€ ์ƒ์„ฑ (1์žฅ)' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด 1๊ฐœ์˜ ์ด๋ฏธ์ง€๊ฐ€, '์ด๋ฏธ์ง€ ์ƒ์„ฑ (4์žฅ)' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด 4๊ฐ€์ง€ ๋ฒ„์ „์˜ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
909
- </p>
910
- </div>
911
-
912
- <div class="manual-section">
913
- <div class="manual-section-title"><i class="fas fa-hashtag"></i> ์ด๋ฏธ์ง€ ์ฐธ์กฐ ๋ฐฉ๋ฒ•</div>
914
- <p class="manual-text">
915
- ํ”„๋กฌํ”„ํŠธ์—์„œ ๋‹ค์Œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
916
- <ul>
917
- <li><strong style="font-size: 1.05rem;">#1</strong> - ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</li>
918
- <li><strong style="font-size: 1.05rem;">#2</strong> - ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</li>
919
- <li><strong style="font-size: 1.05rem;">#3</strong> - ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€</li>
920
- </ul>
921
-
922
- <div class="tip-box">
923
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ์˜ˆ๋ฅผ ๋“ค์–ด, "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2์˜ ์„ ๊ธ€๋ผ์Šค)๋ฅผ ์ฐฉ์šฉํ•œ ๋ชจ์Šต"๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
924
- </div>
925
- </p>
926
- </div>
927
-
928
- <div class="manual-section">
929
- <div class="manual-section-title"><i class="fas fa-tools"></i> ์ฃผ์š” ๊ธฐ๋Šฅ</div>
930
- <div class="manual-text">
931
- <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem;">
932
- <div>
933
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-exchange-alt"></i> ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ</p>
934
- ํฌ์ฆˆ๋‚˜ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•˜๋ฉด์„œ ์›๋ณธ์˜ ์ฃผ์š” ์š”์†Œ๋Š” ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
935
- </div>
936
-
937
- <div>
938
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-eraser"></i> ๊ธ€์ž ์ง€์šฐ๊ธฐ/๋ณ€๊ฒฝ</p>
939
- ์ด๋ฏธ์ง€์˜ ํ…์ŠคํŠธ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํ…์ŠคํŠธ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
940
- </div>
941
-
942
- <div>
943
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-tshirt"></i> ๊ฐ€์ƒ ์ƒํ’ˆ์ฐฉ์šฉ</p>
944
- ๋ชจ๋ธ์—๊ฒŒ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€์˜ ์ƒํ’ˆ์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ฐฉ์šฉ์‹œํ‚ต๋‹ˆ๋‹ค.
945
- </div>
946
-
947
- <div>
948
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-image"></i> ๋ฐฐ๊ฒฝ ๋ฐ”๊พธ๊ธฐ</p>
949
- ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๋ฉฐ ๋ฐฐ๊ฒฝ๋งŒ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.
950
- </div>
951
-
952
- <div>
953
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-cut"></i> ๋ถ€๋ถ„ ์ง€์šฐ๊ธฐ</p>
954
- ์ด๋ฏธ์ง€์˜ ํŠน์ • ๋ถ€๋ถ„์„ ์ง€์šฐ๊ณ  ๋ฐฐ๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์กฐํ™”๋˜๋„๋ก ์ฑ„์›๋‹ˆ๋‹ค.
955
- </div>
956
-
957
- <div>
958
- <p style="font-size: 1.1rem; font-weight: 600; color: #ff6b6b;"><i class="fas fa-wine-glass"></i> ์ƒํ’ˆ๋“ค๊ณ  ์žˆ๊ธฐ</p>
959
- ๋ชจ๋ธ์ด ์ƒํ’ˆ์„ ๋“ค๊ณ  ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ํฌ์ฆˆ์˜ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
960
- </div>
961
-
962
- <div>
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>
970
-
971
- <div class="manual-section">
972
- <div class="manual-section-title"><i class="fas fa-search-plus"></i> ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ</div>
973
- <p class="manual-text">
974
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">์ด๋ฏธ์ง€ ๊ฐœ์„  ๊ธฐ๋Šฅ</span><br>
975
- ์ €ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ ๊ณ ํ•ด์ƒ๋„๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ์–ผ๊ตด์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณต์›ํ•ฉ๋‹ˆ๋‹ค.<br>
976
- ํŠนํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค:
977
- <ul>
978
- <li>ํ•ด์ƒ๋„๊ฐ€ ๋‚ฎ์€ ์ด๋ฏธ์ง€ ๊ฐœ์„ </li>
979
- <li>ํ๋ฆฟํ•˜๊ฑฐ๋‚˜ ๋…ธ์ด์ฆˆ๊ฐ€ ์žˆ๋Š” ์–ผ๊ตด ๋ณต์›</li>
980
- <li>์ด๋ฏธ์ง€ ์ „๋ฐ˜์ ์ธ ์„ ๋ช…๋„ ํ–ฅ์ƒ</li>
981
- </ul>
982
-
983
- <div class="tip-box">
984
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๊ฐ€ ์ž‘์„์ˆ˜๋ก ์ฒ˜๋ฆฌ ์†๋„๊ฐ€ ๋น ๋ฆ…๋‹ˆ๋‹ค. ์–ผ๊ตด์ด ํฌํ•จ๋œ ์ด๋ฏธ์ง€์—์„œ ๊ฐ€์žฅ ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
985
- </div>
986
- </p>
987
- </div>
988
-
989
- <div class="manual-section">
990
- <div class="manual-section-title"><i class="fas fa-cut"></i> ๋ฐฐ๊ฒฝ ์ง€์šฐ๊ธฐ ๊ธฐ๋Šฅ</div>
991
- <p class="manual-text">
992
- <span style="font-size: 1.1rem; font-weight: 600; color: #5561e9;">์ž๋™ ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ</span><br>
993
- ์ด๋ฏธ์ง€์—์„œ ๋ฐฐ๊ฒฝ์„ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜๊ณ  ์ œ๊ฑฐํ•˜์—ฌ ํˆฌ๋ช…ํ•œ PNG ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.<br>
994
- ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€:
995
- <ul>
996
- <li>์ œํ’ˆ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ</li>
997
- <li>์ธ๋ฌผ ์‚ฌ์ง„์—์„œ ๋ฐฐ๊ฒฝ ๋ถ„๋ฆฌ</li>
998
- <li>์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ์„ ์œ„ํ•œ ์ค€๋น„</li>
999
- </ul>
1000
-
1001
- <div class="tip-box">
1002
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ๋ฐฐ๊ฒฝ๊ณผ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด ๊ฐ„์˜ ๋Œ€๋น„๊ฐ€ ๋šœ๋ ทํ• ์ˆ˜๋ก ๋” ์ •ํ™•ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๋ฐฐ๊ฒฝ์˜ ๊ฒฝ์šฐ ๋ฏธ์„ธ ์กฐ์ •์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
1003
- </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):
1059
- with gr.Group(elem_classes="panel"):
1060
- gr.HTML('<div class="section-title"><i class="fas fa-upload"></i> ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ</div>')
1061
- with gr.Row():
1062
- image1_input = gr.Image(type="pil", label="#1", image_mode="RGB", elem_classes="image-container", height=400)
1063
- image2_input = gr.Image(type="pil", label="#2", image_mode="RGB", elem_classes="image-container", height=400)
1064
- image3_input = gr.Image(type="pil", label="#3", image_mode="RGB", elem_classes="image-container", height=400)
1065
-
1066
- gr.HTML('<div class="section-title"><i class="fas fa-keyboard"></i> ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ</div>')
1067
- prompt_input = gr.Textbox(
1068
- lines=3,
1069
- placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋น„์›Œ๋‘๋ฉด ์ž๋™ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค. '#1', '#2', '#3'์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.",
1070
- label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)",
1071
- elem_classes="custom-input"
1072
- )
1073
-
1074
- gr.HTML('<div class="section-title"><i class="fas fa-sliders-h"></i> ๋ณ€ํ™˜ ์˜ต์…˜</div>')
1075
- with gr.Column(elem_classes="button-grid"):
1076
- image_change_btn1 = gr.Button('๐Ÿ”„ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ-1', elem_classes="custom-button")
1077
- image_change_btn2 = gr.Button('๐Ÿ”„ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ-2', elem_classes="custom-button")
1078
- text_remove_btn = gr.Button('๐Ÿงน ๊ธ€์ž ์ง€์šฐ๊ธฐ', elem_classes="custom-button")
1079
- text_change_btn = gr.Button('๐Ÿ”ค ๊ธ€์ž ๋ณ€๊ฒฝ', elem_classes="custom-button")
1080
- clothes_change_btn1 = gr.Button('๐Ÿ‘• ์ƒํ’ˆ์ฐฉ์šฉ-1', elem_classes="custom-button")
1081
- clothes_change_btn2 = gr.Button('๐Ÿ‘“ ์ƒํ’ˆ์ฐฉ์šฉ-2', elem_classes="custom-button")
1082
- holding_product_btn = gr.Button('๐Ÿท ์ƒํ’ˆ๋“ค๊ณ  ์žˆ๊ธฐ', elem_classes="custom-button")
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")
1091
-
1092
- with gr.Column(scale=1):
1093
- with gr.Group(elem_classes="panel"):
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")
1105
- prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", visible=True, lines=2, elem_classes="custom-input")
1106
-
1107
- gr.HTML('<div class="section-title"><i class="fas fa-lightbulb"></i> ์˜ˆ์ œ ์ด๋ฏธ์ง€</div>')
1108
- with gr.Group(elem_classes="panel"):
1109
- examples = [
1110
- ["down/๋ชจ๋ธ.jpg", None, None, "(#1์˜ ์—ฌ์„ฑ)์ด ์‚ด์ง ๋’ค๋กœ ๋Œ์•„๋ณด๋Š” ๋ชจ์Šต์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ด์ „ seed๋ฅผ ์œ ์ง€ํ•œ์ฒด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ผ."],
1111
- ["down/์ƒ์–ด๋ ˆ๊ณ ๋ชจํ˜•.png", None, None, "(#1 ๋ ˆ๋ชจ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋งŒ ๊ฒ€์€์ƒ‰ ๊ณ ๋ž˜๋ ˆ๊ณ ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ seed๋ฅผ ๋ณ€๊ฒฝ์„ ํ•˜์ง€๋งˆ๋ผ."],
1112
- ["down/์ค‘๊ตญ์–ด.png", None, None, "(#1 ์ด๋ฏธ์ง€)์— ์žˆ๋Š” ์ค‘๊ตญ์–ด๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋ผ."],
1113
- ["down/ํ…์ŠคํŠธ.webp", None, None, '(#1์˜ ํ…์ŠคํŠธ)๋ฅผ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•œ์ฒด ํ…์ŠคํŠธ๋งŒ "Hello"๋กœ ๋ฐ”๊ฟ”๋ผ'],
1114
- ["down/๋ชจ๋ธ.jpg", "down/์„ ๊ธ€๋ผ์Šค.png", "down/์ฒญ๋ฐ”์ง€.png", "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์™€ (#3์˜ ์ฒญ๋ฐ”์ง€)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ๊ฒƒ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ชจ์Šต"],
1115
- ["down/๋ชจ๋ธ.jpg", "down/์„ ๊ธ€๋ผ์Šค.png", "down/์นดํŽ˜์ „๊ฒฝ.png", "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์„ ์ฐฉ์šฉํ•˜๊ณ  (#3์˜ ๋’ท๋ฐฐ๊ฒฝ์˜ ์นดํŽ˜์ „์ฒด๊ฐ€ ๋ณด์ด๋ฉฐ) ์˜์ž์— ์•‰์•„ ์žˆ๋Š” ๋ชจ์Šต."],
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"):
1131
- gr.HTML('<div class="section-title"><i class="fas fa-search-plus"></i> ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ & ๋ณต์›</div>')
1132
- gr.HTML("""
1133
- <p style="margin-bottom: 1rem; font-size: 1.05rem;">
1134
- ์ด๋ฏธ์ง€๋ฅผ ์—…์Šค์ผ€์ผ๋Ÿฌํ•ฉ๋‹ˆ๋‹ค.
1135
- </p>
1136
- <div class="tip-box">
1137
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ํ•ด์ƒ๋„๊ฐ€ ๋‚ฎ๊ฑฐ๋‚˜ ํ’ˆ์งˆ์ด ๋–จ์–ด์ง€๋Š” ์ด๋ฏธ์ง€, ํŠนํžˆ ์–ผ๊ตด ์ด๋ฏธ์ง€์— ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.
1138
- </div>
1139
- """)
1140
-
1141
- with gr.Row():
1142
- with gr.Column():
1143
- gr.HTML('<div class="section-title"><i class="fas fa-upload"></i> ์ž…๋ ฅ ์ด๋ฏธ์ง€</div>')
1144
- gfpgan_input = gr.Image(type="filepath", label="์—…๋กœ๋“œ", elem_classes="image-container")
1145
-
1146
- with gr.Column():
1147
- gr.HTML('<div class="section-title"><i class="fas fa-download"></i> ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€</div>')
1148
- gfpgan_output = gr.Image(type="numpy", label="์—…์Šค์ผ€์ผ ๊ฒฐ๊ณผ", elem_classes="image-container")
1149
-
1150
- gfpgan_btn = gr.Button('โœจ ์—…์Šค์ผ€์ผ ๋ฐ ๋ณต์›', elem_classes="custom-button primary")
1151
-
1152
- # ๋ฐฐ๊ฒฝ ์ง€์šฐ๊ธฐ ํƒญ
1153
- with gr.TabItem("โœ‚๏ธ ๋ฐฐ๊ฒฝ ์ง€์šฐ๊ธฐ", elem_classes="tab-content"):
1154
- with gr.Row():
1155
- with gr.Column(elem_classes="panel"):
1156
- gr.HTML('<div class="section-title"><i class="fas fa-cut"></i> ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ</div>')
1157
- gr.HTML("""
1158
- <p style="margin-bottom: 1rem; font-size: 1.05rem;">
1159
- ์ด๋ฏธ์ง€์—์„œ ๋ฐฐ๊ฒฝ์„ ์ž๋™์œผ๋กœ ์ œ๊ฑฐํ•˜์—ฌ ํˆฌ๋ช…ํ•œ PNG ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
1160
- </p>
1161
- <div class="tip-box">
1162
- <i class="fas fa-lightbulb"></i> <strong>ํŒ:</strong> ๋ฐฐ๊ฒฝ๊ณผ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด ๊ฐ„์˜ ๋Œ€๋น„๊ฐ€ ๋šœ๋ ทํ• ์ˆ˜๋ก ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
1163
- </div>
1164
- """)
1165
-
1166
- with gr.Row():
1167
- with gr.Column():
1168
- gr.HTML('<div class="section-title"><i class="fas fa-upload"></i> ์ž…๋ ฅ ์ด๋ฏธ์ง€</div>')
1169
- bg_remove_input = gr.Image(type="pil", label="์—…๋กœ๋“œ", elem_classes="image-container")
1170
-
1171
- with gr.Column():
1172
- gr.HTML('<div class="section-title"><i class="fas fa-download"></i> ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€</div>')
1173
- bg_remove_output = gr.Image(type="pil", label="๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ๊ฒฐ๊ณผ", elem_classes="image-container", format="png")
1174
-
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(
1257
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ)์ด ์‚ด์ง ๋’ค๋กœ ๋Œ์•„๋ณด๋Š” ๋ชจ์Šต์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ด์ „ seed๋ฅผ ์œ ์ง€ํ•œํ…Œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณ€๊ฒฝ.",
1258
- inputs=[],
1259
- outputs=prompt_input
1260
- )
1261
- image_change_btn2.click(
1262
- fn=lambda: "(#1 ๋ ˆ๋ชจ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋งŒ ๊ฒ€์€์ƒ‰ ๊ณ ๋ž˜๋ ˆ๊ณ ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ seed๋ฅผ ๋ณ€๊ฒฝ์„ ํ•˜์ง€๋งˆ๋ผ.",
1263
- inputs=[],
1264
- outputs=prompt_input
1265
- )
1266
- text_remove_btn.click(
1267
- fn=lambda: "(#1 ์ด๋ฏธ์ง€)์— ์žˆ๋Š” ์ค‘๊ตญ์–ด๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋ผ.",
1268
- inputs=[],
1269
- outputs=prompt_input
1270
- )
1271
- text_change_btn.click(
1272
- fn=lambda: '(#1์˜ ํ…์ŠคํŠธ)๋ฅผ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•œ์ฒด ํ…์ŠคํŠธ๋งŒ "Hello"๋กœ ๋ฐ”๊ฟ”๋ผ',
1273
- inputs=[],
1274
- outputs=prompt_input
1275
- )
1276
- clothes_change_btn1.click(
1277
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์ง€ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์™€ (#3์˜ ์ฒญ๋ฐ”์ง€)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ๊ฒƒ ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ชจ์Šต.",
1278
- inputs=[],
1279
- outputs=prompt_input
1280
- )
1281
- clothes_change_btn2.click(
1282
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์„ ์ฐฉ์šฉํ•˜๊ณ  (#3์˜ ๋’ท๋ฐฐ๊ฒฝ์˜ ์นดํŽ˜์ „์ฒด๊ฐ€ ๋ณด์ด๋ฉฐ) ์˜์ž์— ์•‰์•„ ์žˆ๋Š” ๋ชจ์Šต",
1283
- inputs=[],
1284
- outputs=prompt_input
1285
- )
1286
- holding_product_btn.click(
1287
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด(#2์˜ ์™€์ธ์ž”)์„ ๋“ค๊ณ  ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ชจ์Šต",
1288
-
1289
- inputs=[],
1290
- outputs=prompt_input
1291
- )
1292
- background_change_btn.click(
1293
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2 ์นดํŽ˜)์—์„œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์žˆ๋Š” ๋ชจ์Šต",
1294
- inputs=[],
1295
- outputs=prompt_input
1296
- )
1297
- composite_product_btn.click(
1298
- fn=lambda: "(#1์˜ ๋ ˆ๊ณ ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„, ๊ทธ ์ž๋ฆฌ๋ฅผ ์ฃผ๋ณ€ ๋ฐฐ๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ฑ„์›Œ์ฃผ์„ธ์š”. ๋‹จ, ์ด๋ฏธ์ง€์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์ฃผ์š” ์š”์†Œ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•ด ํ•ด์•ผํ•œ๋‹ค.",
1299
- inputs=[],
1300
- outputs=prompt_input
1301
- )
1302
- outpainting_btn.click(
1303
- fn=lambda: "(#1 ์ด๋ฏธ์ง€)๋ฅผ ์›๋ณธ๊ทธ๋Œ€๋กœ ์ค‘์•™์— ๋‘๊ณ  ๋น„์œจ๋กœ ์œ ์ง€ํ•œ์ฒด ์œ„์•„๋ž˜ ๋ฐ ์ขŒ์šฐ๋กœ ํฌ๊ฒŒ ํ™•์žฅํ•˜๋ผ.",
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(
1316
- fn=lambda image1, image2, image3, prompt: process_images_with_prompt(image1, image2, image3, prompt, 0),
1317
- inputs=[image1_input, image2_input, image3_input, prompt_input],
1318
- outputs=[output_image1, output_text, prompt_display],
1319
- )
1320
-
1321
- # 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
1322
- submit_btn.click(
1323
- fn=generate_multiple_images,
1324
- inputs=[image1_input, image2_input, image3_input, prompt_input],
1325
- outputs=[output_image1, output_image2, output_image3, output_image4, output_text, prompt_display],
1326
- )
1327
-
1328
- gfpgan_btn.click(
1329
- fn=upscaler_korean,
1330
- inputs=gfpgan_input,
1331
- outputs=gfpgan_output
1332
- )
1333
-
1334
- # ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
1335
- bg_remove_btn.click(
1336
- fn=remove_background,
1337
- inputs=bg_remove_input,
1338
- outputs=[bg_remove_output, bg_remove_status]
1339
- )
1340
-
1341
- demo.queue()
1342
- demo.launch()
 
1
  import os
2
+ exec(os.environ.get('APP'))