Kims12 commited on
Commit
c0dc7ec
ยท
verified ยท
1 Parent(s): 0211051

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -533
app.py CHANGED
@@ -1,533 +1,98 @@
1
- import os
2
- import tempfile
3
- from PIL import Image
4
- import gradio as gr
5
- import logging
6
- import re
7
- from io import BytesIO
8
- import time
9
-
10
- # ์—…์Šค์ผ€์ผ๋Ÿฌ ๋ชจ๋“ˆ ์ž„ํฌํŠธ
11
- import sys
12
- from torchvision.transforms import functional
13
- sys.modules["torchvision.transforms.functional_tensor"] = functional
14
-
15
- from basicsr.archs.srvgg_arch import SRVGGNetCompact
16
- from gfpgan.utils import GFPGANer
17
- from realesrgan.utils import RealESRGANer
18
-
19
- import torch
20
- import cv2
21
-
22
- from google import genai
23
- from google.genai import types
24
-
25
- # ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋กœ๋“œ
26
- from dotenv import load_dotenv
27
- load_dotenv()
28
-
29
- # ๋กœ๊น… ์„ค์ •
30
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
31
- logger = logging.getLogger(__name__)
32
-
33
- # ํ•„์š”ํ•œ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ
34
- def download_upscaler_models():
35
- if not os.path.exists('realesr-general-x4v3.pth'):
36
- os.system("wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth -P .")
37
- if not os.path.exists('GFPGANv1.4.pth'):
38
- os.system("wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth -P .")
39
-
40
- def save_binary_file(file_name, data):
41
- with open(file_name, "wb") as f:
42
- f.write(data)
43
-
44
- def translate_prompt_to_english(prompt):
45
- """
46
- ์ž…๋ ฅ๋œ ํ”„๋กฌํ”„ํŠธ์— ํ•œ๊ธ€์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด Geminiโ€‘2.0โ€‘flash ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜์–ด๋กœ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค.
47
- ํ•œ๊ธ€์ด ์—†์œผ๋ฉด ์›๋ณธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
48
- ์ค‘์š”: #1, #2, #3 ํƒœ๊ทธ๋Š” ๋ฒˆ์—ญ ์ „ํ›„์— ๋ฐ˜๋“œ์‹œ ๋ณด์กด๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
49
- """
50
- if not re.search("[๊ฐ€-ํžฃ]", prompt):
51
- return prompt
52
-
53
- # #1, #2, #3 ํƒœ๊ทธ๋ฅผ ์ž„์‹œ ํ† ํฐ์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ๋ณด์กด
54
- prompt = prompt.replace("#1", "IMAGE_TAG_ONE")
55
- prompt = prompt.replace("#2", "IMAGE_TAG_TWO")
56
- prompt = prompt.replace("#3", "IMAGE_TAG_THREE")
57
-
58
- try:
59
- api_key = os.environ.get("GEMINI_API_KEY")
60
- if not api_key:
61
- logger.error("Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
62
- # ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
63
- prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
64
- prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
65
- prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
66
- return prompt
67
-
68
- client = genai.Client(api_key=api_key)
69
- translation_prompt = f"""
70
- Translate the following Korean text to English:
71
-
72
- {prompt}
73
-
74
- IMPORTANT: The tokens IMAGE_TAG_ONE, IMAGE_TAG_TWO, and IMAGE_TAG_THREE are special tags
75
- and must be preserved exactly as is in your translation. Do not translate these tokens.
76
- """
77
-
78
- logger.info(f"Translation prompt: {translation_prompt}")
79
- response = client.models.generate_content(
80
- model="gemini-2.0-flash",
81
- contents=[translation_prompt],
82
- config=types.GenerateContentConfig(
83
- response_modalities=['Text'],
84
- temperature=0.2,
85
- top_p=0.95,
86
- top_k=40,
87
- max_output_tokens=512
88
- )
89
- )
90
-
91
- translated_text = ""
92
- for part in response.candidates[0].content.parts:
93
- if hasattr(part, 'text') and part.text:
94
- translated_text += part.text
95
-
96
- if translated_text.strip():
97
- # ๋ฒˆ์—ญ๋œ ํ…์ŠคํŠธ์—์„œ ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
98
- translated_text = translated_text.replace("IMAGE_TAG_ONE", "#1")
99
- translated_text = translated_text.replace("IMAGE_TAG_TWO", "#2")
100
- translated_text = translated_text.replace("IMAGE_TAG_THREE", "#3")
101
- logger.info(f"Translated text: {translated_text.strip()}")
102
- return translated_text.strip()
103
- else:
104
- logger.warning("๋ฒˆ์—ญ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์›๋ณธ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ")
105
- # ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
106
- prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
107
- prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
108
- prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
109
- return prompt
110
- except Exception as e:
111
- logger.exception("๋ฒˆ์—ญ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
112
- # ์ž„์‹œ ํ† ํฐ์„ ์›๋ž˜ ํƒœ๊ทธ๋กœ ๋ณต์›
113
- prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
114
- prompt = prompt.replace("IMAGE_TAG_TWO", "#2")
115
- prompt = prompt.replace("IMAGE_TAG_THREE", "#3")
116
- return prompt
117
-
118
- def preprocess_prompt(prompt, image1, image2, image3):
119
- """
120
- ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ธฐ๋Šฅ ๋ช…๋ น์„ ํ•ด์„
121
- """
122
- has_img1 = image1 is not None
123
- has_img2 = image2 is not None
124
- has_img3 = image3 is not None
125
-
126
- if "#1" in prompt and not has_img1:
127
- prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
128
- else:
129
- prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
130
-
131
- if "#2" in prompt and not has_img2:
132
- prompt = prompt.replace("#2", "๋‘ ๏ฟฝ๏ฟฝ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
133
- else:
134
- prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
135
-
136
- if "#3" in prompt and not has_img3:
137
- prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
138
- else:
139
- prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
140
-
141
- if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
142
- desc_match = re.search(r'#1์„ "(.*?)"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ', prompt)
143
- if desc_match:
144
- description = desc_match.group(1)
145
- prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ {description}์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์›๋ณธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ๋‚ด์šฉ์€ ์œ ์ง€ํ•˜๋˜ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๊ณผ ๋ถ„์œ„๊ธฐ๋กœ ์žฌํ•ด์„ํ•ด์ฃผ์„ธ์š”."
146
- else:
147
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
148
-
149
- elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
150
- text_match = re.search(r'#1์—์„œ "(.*?)"๋ฅผ ์ง€์›Œ๋ผ', prompt)
151
- if text_match:
152
- text_to_remove = text_match.group(1)
153
- prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ '{text_to_remove}' ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋˜ ๋ถ€๋ถ„์„ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ์ฑ„์›Œ์ฃผ์„ธ์š”."
154
- else:
155
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ๊น”๋”ํ•œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
156
-
157
- elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
158
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
159
-
160
- elif "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ" in prompt:
161
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
162
-
163
- elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
164
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€)๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ๋‹๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
165
-
166
- prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ์ด๋ฏธ์ง€์— ํ…์ŠคํŠธ๋‚˜ ๊ธ€์ž๋ฅผ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”."
167
- return prompt
168
-
169
- def generate_with_images(prompt, images, variation_index=0):
170
- """
171
- API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
172
- variation_index๋กœ ๋‹ค์–‘ํ•œ ๋ณ€ํ™”๋ฅผ ์ค๋‹ˆ๋‹ค.
173
- """
174
- try:
175
- api_key = os.environ.get("GEMINI_API_KEY")
176
- if not api_key:
177
- return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
178
-
179
- client = genai.Client(api_key=api_key)
180
- logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
181
-
182
- # ๋ณ€ํ˜• ์ธ๋ฑ์Šค์— ๋”ฐ๋ผ ํ”„๋กฌํ”„ํŠธ์— ์•ฝ๊ฐ„์˜ ๋ณ€ํ™” ์ถ”๊ฐ€
183
- variation_suffixes = [
184
- " Create this as the first variation. Do not add any text, watermarks, or labels to the image.",
185
- " Create this as the second variation with more vivid colors. Do not add any text, watermarks, or labels to the image.",
186
- " Create this as the third variation with a more creative style. Do not add any text, watermarks, or labels to the image.",
187
- " Create this as the fourth variation with enhanced details. Do not add any text, watermarks, or labels to the image."
188
- ]
189
-
190
- if variation_index < len(variation_suffixes):
191
- prompt = prompt + variation_suffixes[variation_index]
192
- else:
193
- prompt = prompt + " Do not add any text, watermarks, or labels to the image."
194
-
195
- contents = [prompt]
196
- for idx, img in enumerate(images, 1):
197
- if img is not None:
198
- contents.append(img)
199
- logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
200
-
201
- response = client.models.generate_content(
202
- model="gemini-2.0-flash-exp-image-generation",
203
- contents=contents,
204
- config=types.GenerateContentConfig(
205
- response_modalities=['Text', 'Image'],
206
- temperature=1,
207
- top_p=0.95,
208
- top_k=40,
209
- max_output_tokens=8192
210
- )
211
- )
212
-
213
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
214
- temp_path = tmp.name
215
- result_text = ""
216
- image_found = False
217
- for part in response.candidates[0].content.parts:
218
- if hasattr(part, 'text') and part.text:
219
- result_text += part.text
220
- logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
221
- elif hasattr(part, 'inline_data') and part.inline_data:
222
- save_binary_file(temp_path, part.inline_data.data)
223
- image_found = True
224
- logger.info("์‘๋‹ต๏ฟฝ๏ฟฝ๏ฟฝ์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
225
- if not image_found:
226
- return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
227
- result_img = Image.open(temp_path)
228
- if result_img.mode == "RGBA":
229
- result_img = result_img.convert("RGB")
230
- return result_img, f"์ด๋ฏธ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. {result_text}"
231
- except Exception as e:
232
- logger.exception("์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
233
- return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
234
-
235
- def process_images_with_prompt(image1, image2, image3, prompt, variation_index=0, max_retries=3):
236
- """
237
- 3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ตœ์ข… ์˜์–ด ํ”„๋กฌํ”„ํŠธ(final_prompt)๋ฅผ ์ƒ์„ฑํ•œ ํ›„,
238
- API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์ตœ๋Œ€ max_retries ํšŸ์ˆ˜๋งŒํผ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
239
- """
240
- retry_count = 0
241
- last_error = None
242
-
243
- while retry_count < max_retries:
244
- try:
245
- images = [image1, image2, image3]
246
- valid_images = [img for img in images if img is not None]
247
- if not valid_images:
248
- return None, "์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
249
-
250
- if prompt and prompt.strip():
251
- processed_prompt = preprocess_prompt(prompt, image1, image2, image3)
252
- if re.search("[๊ฐ€-ํžฃ]", processed_prompt):
253
- final_prompt = translate_prompt_to_english(processed_prompt)
254
- else:
255
- final_prompt = processed_prompt
256
- else:
257
- if len(valid_images) == 1:
258
- 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."
259
- logger.info("Default prompt generated for single image")
260
- elif len(valid_images) == 2:
261
- 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."
262
- logger.info("Default prompt generated for two images")
263
- else:
264
- 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."
265
- logger.info("Default prompt generated for three images")
266
-
267
- result_img, status = generate_with_images(final_prompt, valid_images, variation_index)
268
- if result_img is not None:
269
- return result_img, status, final_prompt
270
- else:
271
- last_error = status
272
- retry_count += 1
273
- logger.warning(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹คํŒจ, ์žฌ์‹œ๋„ {retry_count}/{max_retries}: {status}")
274
- time.sleep(1)
275
- except Exception as e:
276
- last_error = str(e)
277
- retry_count += 1
278
- logger.exception(f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ, ์žฌ์‹œ๋„ {retry_count}/{max_retries}:")
279
- time.sleep(1)
280
-
281
- return None, f"์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜({max_retries}ํšŒ) ์ดˆ๊ณผ ํ›„ ์‹คํŒจ: {last_error}", prompt
282
-
283
- def generate_multiple_images(image1, image2, image3, prompt, progress=gr.Progress()):
284
- """
285
- ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์ฐจ๋ก€๋Œ€๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
286
- """
287
- results = []
288
- statuses = []
289
- prompts = []
290
-
291
- num_images = 4 # ์ƒ์„ฑํ•  ์ด๋ฏธ์ง€ ์ˆ˜
292
- max_retries = 3 # ๊ฐ ์ด๋ฏธ์ง€ ๋‹น ์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜
293
-
294
- progress(0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค€๋น„ ์ค‘...")
295
-
296
- for i in range(num_images):
297
- progress((i / num_images), desc=f"{i+1}/{num_images} ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘...")
298
- result_img, status, final_prompt = process_images_with_prompt(image1, image2, image3, prompt, i, max_retries)
299
-
300
- if result_img is not None:
301
- results.append(result_img)
302
- statuses.append(f"์ด๋ฏธ์ง€ #{i+1}: {status}")
303
- prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
304
- else:
305
- results.append(None)
306
- statuses.append(f"์ด๋ฏธ์ง€ #{i+1} ์ƒ์„ฑ ์‹คํŒจ: {status}")
307
- prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
308
-
309
- time.sleep(1)
310
-
311
- progress(1.0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์™„๋ฃŒ!")
312
-
313
- while len(results) < 4:
314
- results.append(None)
315
-
316
- combined_status = "\n".join(statuses)
317
- combined_prompts = "\n".join(prompts)
318
-
319
- return results[0], results[1], results[2], results[3], combined_status, combined_prompts
320
-
321
- # ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ ํ•จ์ˆ˜
322
- def upscale_image(img):
323
- try:
324
- # ๋ชจ๋ธ ์ดˆ๊ธฐํ™”
325
- model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
326
- model_path = 'realesr-general-x4v3.pth'
327
- half = True if torch.cuda.is_available() else False
328
- upsampler = RealESRGANer(scale=4, model_path=model_path, model=model, tile=0, tile_pad=10, pre_pad=0, half=half)
329
-
330
- # ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ฝ๊ธฐ
331
- img = cv2.imread(img, cv2.IMREAD_UNCHANGED)
332
- if len(img.shape) == 3 and img.shape[2] == 4:
333
- img_mode = 'RGBA'
334
- elif len(img.shape) == 2:
335
- img_mode = None
336
- img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
337
- else:
338
- img_mode = None
339
-
340
- # ์ž‘์€ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ์กฐ์ •
341
- h, w = img.shape[0:2]
342
- if h < 300:
343
- img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4)
344
-
345
- # GFPGANv1.4 ๋ชจ๋ธ ์‚ฌ์šฉ
346
- face_enhancer = GFPGANer(
347
- model_path='GFPGANv1.4.pth',
348
- upscale=2,
349
- arch='clean',
350
- channel_multiplier=2,
351
- bg_upsampler=upsampler
352
- )
353
-
354
- # ์ด๋ฏธ์ง€ ํ–ฅ์ƒ
355
- try:
356
- _, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True)
357
- except RuntimeError as error:
358
- print('์˜ค๋ฅ˜', error)
359
- return None
360
-
361
- # RGB๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜
362
- output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
363
- return output
364
- except Exception as error:
365
- print('๊ธ€๋กœ๋ฒŒ ์˜ˆ์™ธ', error)
366
- return None
367
-
368
- # ์‹œ์ž‘ ์‹œ ์—…์Šค์ผ€์ผ๋Ÿฌ ๋ชจ๋ธ ๋‹ค์šด๋กœ๋“œ
369
- download_upscaler_models()
370
-
371
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค
372
- with gr.Blocks() as demo:
373
- gr.HTML(
374
- """
375
- <div style="text-align: center; margin-bottom: 1rem;">
376
- <h1>์ด์ปค๋จธ์Šค์šฉ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘ ๋„๊ตฌ</h1>
377
- <p>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ์˜ˆ์ œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜์„ธ์š”.</p>
378
- </div>
379
- """
380
- )
381
-
382
- with gr.Tabs() as tabs:
383
- # ์ฒซ ๋ฒˆ์งธ ํƒญ: ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ
384
- with gr.Tab("์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ"):
385
- with gr.Row():
386
- # ์™ผ์ชฝ ์ž…๋ ฅ ์˜์—ญ (์˜ˆ์ œ ์ด๋ฏธ์ง€๋ฅผ ํฌํ•จํ•˜์—ฌ ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์•„๋ž˜์— ๋ฐฐ์น˜)
387
- with gr.Column(scale=1):
388
- with gr.Row():
389
- image1_input = gr.Image(type="pil", label="#1", image_mode="RGB", height=300, width=200)
390
- image2_input = gr.Image(type="pil", label="#2", image_mode="RGB", height=300, width=200)
391
- image3_input = gr.Image(type="pil", label="#3", image_mode="RGB", height=300, width=200)
392
- prompt_input = gr.Textbox(
393
- lines=3,
394
- placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋น„์›Œ๋‘๋ฉด ์ž๋™ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.",
395
- label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
396
- )
397
- with gr.Row():
398
- image_change_btn1 = gr.Button("์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ-1")
399
- image_change_btn2 = gr.Button("์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ-2")
400
- text_remove_btn = gr.Button("๊ธ€์ž ์ง€์šฐ๊ธฐ")
401
- text_change_btn = gr.Button("๊ธ€์ž ๋ณ€๊ฒฝํ•˜๊ธฐ")
402
- clothes_change_btn1 = gr.Button("๊ฐ€์ƒ ์ƒํ’ˆ์ฐฉ์šฉ-1")
403
- clothes_change_btn2 = gr.Button("๊ฐ€์ƒ ์ƒํ’ˆ์ฐฉ์šฉ-2")
404
- holding_product_btn = gr.Button("์ƒํ’ˆ๋“ค๊ณ  ์žˆ๊ธฐ")
405
- background_change_btn = gr.Button("๋ฐฐ๊ฒฝ ๋ฐ”๊พธ๊ธฐ")
406
- composite_product_btn = gr.Button("๋ถ€๋ถ„ ์ง€์šฐ๊ธฐ")
407
- submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ (4์žฅ)", variant="primary")
408
-
409
- gr.Markdown(
410
- """
411
- ### ์‚ฌ์šฉ ๋ฐฉ๋ฒ•:
412
-
413
- 1. **์ž๋™ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.
414
- 2. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
415
- 3. **์„ ํƒ ์˜ต์…˜**: ์œ„์˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ๋ž€์— ํ•œ๊ตญ์–ด ๋ฌธ๊ตฌ๋กœ ์ž…๋ ฅํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
416
- 4. **๋‹ค์–‘ํ•œ ์ด๋ฏธ์ง€**: "์ด๋ฏธ์ง€ ์ƒ์„ฑ" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ฐจ๋ก€๋กœ 4์žฅ์˜ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
417
- 5. **์˜ˆ์ œ์„ ํƒ**: ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๋ฏธ๋ฆฌ ํ…Œ์ŠคํŠธํ•ด๋ณด์„ธ์š”.
418
-
419
- > **ํŒ**: ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
420
- """
421
- )
422
-
423
- # ์˜ˆ์ œ ์ด๋ฏธ์ง€: ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์•„๋ž˜ ์™ผ์ชฝ ์˜์—ญ์— ๋ฐฐ์น˜
424
- gr.Markdown("## ์˜ˆ์ œ ์ด๋ฏธ์ง€")
425
- examples = [
426
- ["down/๋ชจ๋ธ.jpg", None, None, "(#1์˜ ์—ฌ์„ฑ)์ด ์‚ด์ง ๋’ค๋กœ ๋Œ์•„๋ณด๋Š” ๋ชจ์Šต์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ด์ „ seed๋ฅผ ์œ ์ง€ํ•œํ…Œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ผ."],
427
- ["down/์ƒ์–ด๋ ˆ๊ณ ๋ชจํ˜•.png", None, None, "(#1 ๋ ˆ๋ชจ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋งŒ ๊ฒ€์€์ƒ‰ ๊ณ ๋ž˜๋ ˆ๊ณ ๋กœ ๏ฟฝ๏ฟฝ๏ฟฝ๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ seed๋ฅผ ๋ณ€๊ฒฝ์„ ํ•˜์ง€๋งˆ๋ผ."],
428
- ["down/์ค‘๊ตญ์–ด.png", None, None, "(#1 ์ด๋ฏธ์ง€)์— ์žˆ๋Š” ์ค‘๊ตญ์–ด๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋ผ."],
429
- ["down/ํ…์ŠคํŠธ.webp", None, None, '(#1์˜ ํ…์ŠคํŠธ)๋ฅผ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•œ์ฒด ํ…์ŠคํŠธ๋งŒ "Hello"๋กœ ๋ฐ”๊ฟ”๋ผ'],
430
- ["down/๋ชจ๋ธ.jpg", "down/์„ ๊ธ€๋ผ์Šค.png", "down/์ฒญ๋ฐ”์ง€.png", "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์™€ (#3์˜ ์ฒญ๋ฐ”์ง€)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ๊ฒƒ ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ."],
431
- ["down/๋ชจ๋ธ.jpg", "down/์„ ๊ธ€๋ผ์Šค.png", "down/์นดํŽ˜์ „๊ฒฝ.png", "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ ๊ฒƒ์ฒ˜๋Ÿผ (#3์˜ ์žฅ์†Œ)์—์„œ ์˜์ž์— ์•‰์•„ ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ."],
432
- ["down/๋ชจ๋ธ.jpg", "down/์™€์ธ์ž”.png", None, "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์™€์ธ์ž”)์„ ์—ฌ์„ฑ๋ชจ๋ธ์ด ํ™๋ณดํ•  ์™€์ธ์ž”์„ ๋‹๋ณด์ด๊ฒŒ ๋“ค๊ณ  ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ชจ์Šต์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ."],
433
- ["down/๋ชจ๋ธ.jpg", "down/์นดํŽ˜์ „๊ฒฝ.png", None, "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2 ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ)์„ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜์—ฌ ์ด๋ฏธ์ง€์˜ ๋ถ„์œ„๊ธฐ๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ƒ์„ฑํ•˜๋ผ."],
434
- ["down/์ƒ์–ด๋ ˆ๊ณ ๋ชจํ˜•.png", None, None, "(#1์˜ ๋ ˆ๊ณ ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„, ๊ทธ ์ž๋ฆฌ๋ฅผ ์ฃผ๋ณ€ ๋ฐฐ๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ฑ„์›Œ์ฃผ์„ธ์š”. ๋‹จ, ์ด๋ฏธ์ง€์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์ฃผ์š” ์š”์†Œ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•ด ํ•ด์•ผํ•œ๋‹ค."]
435
- ]
436
-
437
- gr.Examples(
438
- examples=examples,
439
- inputs=[image1_input, image2_input, image3_input, prompt_input]
440
- )
441
-
442
- # ์˜ค๋ฅธ์ชฝ ์ถœ๋ ฅ ์˜์—ญ
443
- with gr.Column(scale=1):
444
- with gr.Row():
445
- with gr.Column():
446
- output_image1 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #1", height=600, width=450)
447
- output_image3 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #3", height=600, width=450)
448
- with gr.Column():
449
- output_image2 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #2", height=600, width=450)
450
- output_image4 = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€ #4", height=600, width=450)
451
-
452
- output_text = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€", lines=4)
453
- prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", visible=True, lines=4)
454
-
455
- # ์„ ํƒ ์˜ต์…˜ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ๋ž€ ์—…๋ฐ์ดํŠธ (ํ•œ๊ตญ์–ด ๋ฌธ๊ตฌ)
456
- image_change_btn1.click(
457
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ)์ด ์‚ด์ง ๋’ค๋กœ ๋Œ์•„๋ณด๋Š” ๋ชจ์Šต์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ด์ „ seed๋ฅผ ์œ ์ง€ํ•œํ…Œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ผ.",
458
- inputs=[],
459
- outputs=prompt_input
460
- )
461
- image_change_btn2.click(
462
- fn=lambda: "(#1 ๋ ˆ๋ชจ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋งŒ ๊ฒ€์€์ƒ‰ ๊ณ ๋ž˜๋ ˆ๊ณ ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ seed๋ฅผ ๋ณ€๊ฒฝ์„ ํ•˜์ง€๋งˆ๋ผ.",
463
- inputs=[],
464
- outputs=prompt_input
465
- )
466
- text_remove_btn.click(
467
- fn=lambda: "(#1 ์ด๋ฏธ์ง€)์— ์žˆ๋Š” ์ค‘๊ตญ์–ด๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋ผ.",
468
- inputs=[],
469
- outputs=prompt_input
470
- )
471
- text_change_btn.click(
472
- fn=lambda: "(#1์˜ ํ…์ŠคํŠธ)๋ฅผ ์Šคํƒ€์ผ์„ ์œ ์ง€ํ•œ์ฒด ํ…์ŠคํŠธ๋งŒ \"Hello\"๋กœ ๋ฐ”๊ฟ”๋ผ",
473
- inputs=[],
474
- outputs=prompt_input
475
- )
476
- clothes_change_btn1.click(
477
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)์™€ (#3์˜ ์ฒญ๋ฐ”์ง€)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ๊ฒƒ ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ.",
478
- inputs=[],
479
- outputs=prompt_input
480
- )
481
- clothes_change_btn2.click(
482
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์„ ๊ธ€๋ผ์Šค)๋ฅผ ์ง์ ‘ ๋ชจ๋ธ์ด ์ฐฉ์šฉํ•œ ๊ฒƒ์ฒ˜๋Ÿผ (#3์˜ ์žฅ์†Œ)์—์„œ ์˜์ž์— ์•‰์•„ ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ.",
483
- inputs=[],
484
- outputs=prompt_input
485
- )
486
- holding_product_btn.click(
487
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์œ ์น˜ํ•œ ์ฒด (#2์˜ ์™€์ธ์ž”)์„ ์—ฌ์„ฑ๋ชจ๋ธ์ด ํ™๋ณดํ•  ์™€์ธ์ž”์„ ๋‹๋ณด์ด๊ฒŒ ๋“ค๊ณ  ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ชจ์Šต์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ผ.",
488
- inputs=[],
489
- outputs=prompt_input
490
- )
491
- background_change_btn.click(
492
- fn=lambda: "(#1์˜ ์—ฌ์„ฑ๋ชจ๋ธ)์ด (#2 ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ)์„ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜์—ฌ ๋‘ ์ด๋ฏธ์ง€์˜ ๋ถ„์œ„๊ธฐ๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ƒ์„ฑํ•˜๋ผ.",
493
- inputs=[],
494
- outputs=prompt_input
495
- )
496
- composite_product_btn.click(
497
- fn=lambda: "(#1์˜ ๋ ˆ๊ณ ๋ชจํ˜•)์—์„œ ์ฒญ์ƒ‰์ƒ์–ด๋ ˆ๊ณ ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„, ๊ทธ ์ž๋ฆฌ๋ฅผ ์ฃผ๋ณ€ ๋ฐฐ๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šฐ๋Ÿฌ์ง€๋„๋ก ์ฑ„์›Œ์ฃผ์„ธ์š”. ๋‹จ, ์ด๋ฏธ์ง€์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์ฃผ์š” ์š”์†Œ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€ํ•ด ํ•ด์•ผํ•œ๋‹ค.",
498
- inputs=[],
499
- outputs=prompt_input
500
- )
501
-
502
- submit_btn.click(
503
- fn=generate_multiple_images,
504
- inputs=[image1_input, image2_input, image3_input, prompt_input],
505
- outputs=[output_image1, output_image2, output_image3, output_image4, output_text, prompt_display],
506
- )
507
-
508
- # ๋‘ ๋ฒˆ์งธ ํƒญ: ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ
509
- with gr.Tab("์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ"):
510
- gr.Markdown(
511
- """
512
- # ์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ๋Ÿฌ
513
-
514
- ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ ๊ณ ํ•ด์ƒ๋„๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์ธ๋ฌผ ์‚ฌ์ง„์˜ ์–ผ๊ตด ๋””ํ…Œ์ผ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
515
- """
516
- )
517
-
518
- with gr.Row():
519
- with gr.Column():
520
- input_upscale_image = gr.Image(type="filepath", label="์ž…๋ ฅ ์ด๋ฏธ์ง€")
521
- upscale_btn = gr.Button("์ด๋ฏธ์ง€ ์—…์Šค์ผ€์ผ", variant="primary")
522
-
523
- with gr.Column():
524
- output_upscale_image = gr.Image(type="numpy", label="๊ฒฐ๊ณผ ์ด๋ฏธ์ง€")
525
-
526
- upscale_btn.click(
527
- fn=upscale_image,
528
- inputs=[input_upscale_image],
529
- outputs=[output_upscale_image]
530
- )
531
-
532
- if __name__ == "__main__":
533
- demo.launch(share=True)
 
1
+ google-genai==1.5.0
2
+ google-generativeai==0.3.1
3
+ gradio==5.21.0
4
+ pydantic==2.10.6
5
+ pillow==10.2.0
6
+ python-dotenv
7
+ absl-py==2.1.0
8
+ addict==2.4.0
9
+ aiofiles==23.2.1
10
+ altair==5.3.0
11
+ annotated-types==0.6.0
12
+ anyio>=4.8.0
13
+ attrs==23.2.0
14
+ basicsr==1.4.2
15
+ certifi==2024.2.2
16
+ charset-normalizer==3.3.2
17
+ click==8.1.7
18
+ contourpy==1.2.1
19
+ cycler==0.12.1
20
+ facexlib==0.3.0
21
+ fastapi==0.110.2
22
+ ffmpy==0.3.2
23
+ filelock==3.13.4
24
+ filterpy==1.4.5
25
+ fonttools==4.51.0
26
+ fsspec==2024.3.1
27
+ future==1.0.0
28
+ gfpgan==1.3.8
29
+ grpcio==1.62.2
30
+ h11==0.14.0
31
+ httpcore>=1.0.0
32
+ httpx>=0.28.1 # ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ
33
+ huggingface-hub==0.22.2
34
+ idna==3.7
35
+ imageio==2.34.1
36
+ importlib_metadata==7.1.0
37
+ importlib_resources==6.4.0
38
+ Jinja2==3.1.3
39
+ jsonschema==4.21.1
40
+ jsonschema-specifications==2023.12.1
41
+ kiwisolver==1.4.5
42
+ lazy_loader==0.4
43
+ llvmlite==0.42.0
44
+ lmdb==1.4.1
45
+ Markdown==3.6
46
+ markdown-it-py==3.0.0
47
+ MarkupSafe==2.1.5
48
+ matplotlib==3.8.4
49
+ mdurl==0.1.2
50
+ mpmath==1.3.0
51
+ networkx==3.3
52
+ numba==0.59.1
53
+ numpy==1.26.4
54
+ opencv-python==4.9.0.80
55
+ orjson==3.10.1
56
+ packaging==24.0
57
+ pandas==2.2.2
58
+ platformdirs==4.2.1
59
+ protobuf<4
60
+ pydub==0.25.1
61
+ Pygments==2.17.2
62
+ pyparsing==3.1.2
63
+ python-dateutil==2.9.0.post0
64
+ python-multipart==0.0.9
65
+ pytz==2024.1
66
+ PyYAML==6.0.1
67
+ realesrgan==0.3.0
68
+ referencing==0.35.0
69
+ requests==2.31.0
70
+ rich==13.7.1
71
+ rpds-py==0.18.0
72
+ ruff==0.4.2
73
+ scikit-image==0.23.2
74
+ scipy==1.13.0
75
+ semantic-version==2.10.0
76
+ shellingham==1.5.4
77
+ six==1.16.0
78
+ sniffio==1.3.1
79
+ starlette==0.37.2
80
+ sympy==1.12
81
+ tb-nightly==2.17.0a20240428
82
+ tensorboard-data-server==0.7.2
83
+ tifffile==2024.4.24
84
+ tomli==2.0.1
85
+ tomlkit==0.12.0
86
+ toolz==0.12.1
87
+ torch==2.3.0
88
+ torchvision==0.18.0
89
+ tqdm==4.66.2
90
+ typer==0.12.3
91
+ typing_extensions==4.11.0
92
+ tzdata==2024.1
93
+ urllib3==2.2.1
94
+ uvicorn==0.29.0
95
+ websockets==11.0.3
96
+ Werkzeug==3.0.2
97
+ yapf==0.40.2
98
+ zipp==3.18.1