Update app.py
Browse files
app.py
CHANGED
@@ -17,6 +17,67 @@ load_dotenv()
|
|
17 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
18 |
logger = logging.getLogger(__name__)
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
# ------------------- κΈ°λ³Έ μ΄λ―Έμ§ μμ± κ΄λ ¨ ν¨μ -------------------
|
21 |
def save_binary_file(file_name, data):
|
22 |
with open(file_name, "wb") as f:
|
@@ -86,32 +147,39 @@ def generate_with_images(prompt, images, variation_index=0):
|
|
86 |
return None, "API ν€κ° μ€μ λμ§ μμμ΅λλ€. νκ²½λ³μλ₯Ό νμΈν΄μ£ΌμΈμ."
|
87 |
client = genai.Client(api_key=api_key)
|
88 |
logger.info(f"Gemini API μμ² μμ - ν둬ννΈ: {prompt}, λ³ν μΈλ±μ€: {variation_index}")
|
|
|
|
|
89 |
variation_suffixes = [
|
90 |
-
" Create this as the
|
91 |
-
" Create this as
|
92 |
-
" Create this as
|
93 |
-
" Create this as
|
94 |
]
|
|
|
95 |
if variation_index < len(variation_suffixes):
|
96 |
prompt = prompt + variation_suffixes[variation_index]
|
97 |
else:
|
98 |
-
prompt = prompt + " Do not add any text, watermarks, or labels to the image."
|
|
|
99 |
contents = [prompt]
|
100 |
for idx, img in enumerate(images, 1):
|
101 |
if img is not None:
|
102 |
contents.append(img)
|
103 |
logger.info(f"μ΄λ―Έμ§ #{idx} μΆκ°λ¨")
|
|
|
|
|
104 |
response = client.models.generate_content(
|
105 |
model="gemini-2.0-flash-exp-image-generation",
|
106 |
contents=contents,
|
107 |
config=types.GenerateContentConfig(
|
108 |
response_modalities=['Text', 'Image'],
|
109 |
-
temperature=1,
|
110 |
-
top_p=0.
|
111 |
-
top_k=
|
112 |
-
max_output_tokens=
|
113 |
)
|
114 |
)
|
|
|
115 |
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
|
116 |
temp_path = tmp.name
|
117 |
result_text = ""
|
@@ -160,117 +228,21 @@ def process_images_with_prompt(image1, prompt, variation_index=0, max_retries=3)
|
|
160 |
time.sleep(1)
|
161 |
return None, f"μ΅λ μ¬μλ νμ({max_retries}ν) μ΄κ³Ό ν μ€ν¨: {last_error}", prompt
|
162 |
|
163 |
-
# -------------------
|
164 |
-
|
165 |
-
|
166 |
-
if
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
try:
|
175 |
-
with open(file_path, 'r', encoding='utf-8') as f:
|
176 |
-
data = json.load(f)
|
177 |
-
logger.info(f"{filename} νμΌμ μ±κ³΅μ μΌλ‘ λ‘λνμ΅λλ€. {len(data)} νλͺ© ν¬ν¨.")
|
178 |
-
return data
|
179 |
-
except Exception as e:
|
180 |
-
logger.warning(f"{filename} νμΌ λ‘λ μ€ μ€λ₯ λ°μ: {str(e)}. κΈ°λ³Έκ°μ μ¬μ©ν©λλ€.")
|
181 |
-
return {}
|
182 |
-
|
183 |
-
SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
|
184 |
-
STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
|
185 |
-
NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
|
186 |
-
INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
|
187 |
-
ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
|
188 |
-
|
189 |
-
if not SIMPLE_BACKGROUNDS:
|
190 |
-
SIMPLE_BACKGROUNDS = {"νμ΄νΈ λ°°κ²½": "white background"}
|
191 |
-
if not STUDIO_BACKGROUNDS:
|
192 |
-
STUDIO_BACKGROUNDS = {"μ ν μ¬μ§ μ€νλμ€": "product photography studio"}
|
193 |
-
if not NATURE_BACKGROUNDS:
|
194 |
-
NATURE_BACKGROUNDS = {"μ΄λ ν΄λ³": "tropical beach"}
|
195 |
-
if not INDOOR_BACKGROUNDS:
|
196 |
-
INDOOR_BACKGROUNDS = {"λͺ¨λ 리λΉλ£Έ": "modern living room"}
|
197 |
-
if not ABSTRACT_BACKGROUNDS:
|
198 |
-
ABSTRACT_BACKGROUNDS = {"λ€μ¨ μ‘°λͺ
": "neon lights"}
|
199 |
-
|
200 |
-
# ------------------- μμ€ν
μΈμ€νΈλμ
μμ (μν ν¬μ»€μ€, κ³ νμ§ λ λλ§ λ° μν ν
λ리 λΉ μ΅μν) -------------------
|
201 |
-
def generate_system_instruction():
|
202 |
-
return """λΉμ μ μν μ΄λ―Έμ§μ λ°°κ²½μ λ³κ²½νκΈ° μν κ³ νμ§ ν둬ννΈλ₯Ό μμ±νλ μ λ¬Έκ°μ
λλ€.
|
203 |
-
μ¬μ©μκ° μ 곡νλ μνλͺ
, λ°°κ²½ μ ν, μΆκ° μμ²μ¬νμ λ°νμΌλ‘ λ―Έλμ λ(Midjourney)μ μ¬μ©ν μ μλ μμΈνκ³ μ λ¬Έμ μΈ ν둬ννΈλ₯Ό μμ΄λ‘ μμ±ν΄μ£ΌμΈμ.
|
204 |
-
λ€μ κ°μ΄λλΌμΈμ λ°λμ μ€μν΄μΌ ν©λλ€:
|
205 |
-
1. μνμ "#1"λ‘ μ§μ νμ¬ μ°Έμ‘°ν©λλ€. (μ: "skincare tube (#1)")
|
206 |
-
2. *** λ§€μ° μ€μ: μνμ μλ νΉμ±(λμμΈ, μμ, νν, λ‘κ³ , ν¨ν€μ§ λ±)μ μ΄λ€ μν©μμλ μ λ λ³κ²½νμ§ μμ΅λλ€. ***
|
207 |
-
3. *** μνμ λ³Έμ§μ νΉμ±μ μ μ§νλ, μνμ ν¬μ»€μ€λ₯Ό λ§μΆ° λͺ¨λ μΈλΆ μ¬νμ΄ μ λͺ
νκ² λλ¬λλλ‘ νλ©°, κ³ νμ§(ultra high resolution)λ‘ λ λλ§λμ΄ νμ§ μ ν μμ΄ ννλμ΄μΌ ν©λλ€. ***
|
208 |
-
4. μ΄λ―Έμ§ λΉμ¨μ μ νν 1:1(μ μ¬κ°ν) νμμΌλ‘ μ§μ ν©λλ€. ν둬ννΈμ "square format", "1:1 ratio" λλ "aspect ratio 1:1"μ λͺ
μμ μΌλ‘ ν¬ν¨ν©λλ€.
|
209 |
-
5. μνμ λ°λμ μ μ¬κ°ν ꡬλμ μ μ€μμ λ°°μΉλμ΄μΌ ν©λλ€.
|
210 |
-
6. μνμ μ΄λ―Έμ§μ μ£Όμ μ΄μ μΌλ‘ λΆκ°μν€κ³ , μνμ λΉμ¨μ΄ μ 체 μ΄λ―Έμ§μμ ν¬κ² μ°¨μ§νλλ‘ ν©λλ€.
|
211 |
-
7. μν μ΄λ―Έμ§ μ»·μμ(#1)μ κΈ°λ³Έ ννμ μμμ μ μ§νλ©΄μ, μ νν νκ²½μ μμ°μ€λ½κ² ν΅ν©λλλ‘ ν©λλ€.
|
212 |
-
8. κ³ κΈμ€λ¬μ΄ μμ
μ μ΄λ―Έμ§λ₯Ό μν λ€μ νκ²½ μμλ€μ ν¬οΏ½οΏ½νμΈμ:
|
213 |
-
- μνκ³Ό μ΄μΈλ¦¬λ μ£Όλ³ νκ²½/λ°°κ²½ μμ
|
214 |
-
- νκ²½μ μ‘°λͺ
ν¨κ³Όλ λΆλλ½κ³ μμ°μ€λ¬μ΄ μ‘°λͺ
λ§ μ μ©νλ©°, μν ν
λ리μ λΉ ν¨κ³Όλ μ΅μνν©λλ€.
|
215 |
-
- μμ°μ€λ¬μ΄ κ·Έλ¦Όμμ λΉ νν
|
216 |
-
- μνμ μ©λλ μ₯μ μ μμνλ λ°°κ²½ μμ
|
217 |
-
- νλ‘νμ
λν μμ
μ¬μ§ ν¨κ³Ό (νΌμ¬κ³ μ¬λ, μννΈ ν¬μ»€μ€, μ€νλμ€ μ‘°λͺ
λ±)
|
218 |
-
9. ν둬ννΈμ λ€μ μμλ€μ λͺ
μμ μΌλ‘ ν¬ν¨νμΈμ:
|
219 |
-
- "highly detailed commercial photography"
|
220 |
-
- "award-winning product photography"
|
221 |
-
- "professional advertising imagery"
|
222 |
-
- "studio quality"
|
223 |
-
- "magazine advertisement quality"
|
224 |
-
10. λ°°κ²½ νκ²½ μμλ₯Ό μν μΉ΄ν
κ³ λ¦¬μ λ§κ² μ νν©λλ€.
|
225 |
-
11. μ¬μ©μκ° μ 곡ν ꡬ체μ μΈ λ°°κ²½κ³Ό μΆκ° μμ²μ¬νμ μ νν λ°μν©λλ€.
|
226 |
-
12. ν둬ννΈλ λ―Έλμ λ AIμ μ΅μ νλμ΄μΌ ν©λλ€.
|
227 |
-
13. ν둬ννΈ λμ "--ar 1:1 --s 750 --q 2" νλΌλ―Έν°λ₯Ό μΆκ°νμ¬ λ―Έλμ λμμ κ³ νμ§ μ μ¬κ°ν λΉμ¨μ κ°μ ν©λλ€.
|
228 |
-
"""
|
229 |
-
|
230 |
-
def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
|
231 |
-
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
|
232 |
-
if not GEMINI_API_KEY:
|
233 |
-
return "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€. νκ²½ λ³μ GEMINI_API_KEYλ₯Ό μ€μ νκ±°λ μ½λμ μ§μ μ
λ ₯νμΈμ."
|
234 |
-
try:
|
235 |
-
genai_generative.configure(api_key=GEMINI_API_KEY)
|
236 |
-
prompt_request = f"""
|
237 |
-
μνλͺ
: {product_name}
|
238 |
-
λ°°κ²½ μ ν: {background_info.get('english', 'studio')}
|
239 |
-
λ°°κ²½ μΉ΄ν
κ³ λ¦¬: {background_info.get('category', '')}
|
240 |
-
λ°°κ²½ μ΄λ¦: {background_info.get('name', '')}
|
241 |
-
μΆκ° μμ²μ¬ν: {additional_info}
|
242 |
-
μ€μ μꡬμ¬ν:
|
243 |
-
1. μνμ΄ ν¬κ² λΆκ°λκ³ μ΄λ―Έμ§μμ μ€μ¬μ μΈ μμΉλ₯Ό μ°¨μ§νλλ‘ ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ.
|
244 |
-
2. μ΄λ―Έμ§λ μ νν 1:1 λΉμ¨(μ μ¬κ°ν)μ΄μ΄μΌ ν©λλ€.
|
245 |
-
3. μνμ μ μ¬κ°ν νλ μμ μ μ€μμ μμΉν΄μΌ ν©λλ€.
|
246 |
-
4. μνμ λμμΈ, μμ, νν, λ‘κ³ λ± λ³Έμ§μ νΉμ±μ μ λ μμ νμ§ λ§μΈμ.
|
247 |
-
5. νκ²½κ³Όμ μμ°μ€λ¬μ΄ ν΅ν©μ μν μ‘°λͺ
ν¨κ³Όμ κ·Έλ¦Όμλ μ μ©νλ, μν ν
λ리μ λΉ ν¨κ³Όλ μ΅μνν©λλ€.
|
248 |
-
6. μνμ λ λ보μ΄κ² νλ λ°°κ²½ νκ²½μ μ€λͺ
ν΄μ£ΌμΈμ.
|
249 |
-
7. κ³ κΈμ€λ¬μ΄ μμ
κ΄κ³ νμ§μ μ΄λ―Έμ§κ° λλλ‘ νκ²½ μ€λͺ
μ ν΄μ£ΌμΈμ.
|
250 |
-
8. ν둬ννΈ λμ λ―Έλμ λ νλΌλ―Έν° "--ar 1:1 --s 750 --q 2"λ₯Ό μΆκ°ν΄μ£ΌμΈμ.
|
251 |
-
νκ΅μ΄ μ
λ ₯ λ΄μ©μ μμ΄λ‘ μ μ ν λ²μνμ¬ λ°μν΄μ£ΌμΈμ.
|
252 |
-
"""
|
253 |
-
model = genai_generative.GenerativeModel(
|
254 |
-
'gemini-2.0-flash',
|
255 |
-
system_instruction=generate_system_instruction()
|
256 |
-
)
|
257 |
-
response = model.generate_content(
|
258 |
-
prompt_request,
|
259 |
-
generation_config=genai_generative.types.GenerationConfig(
|
260 |
-
temperature=0.7,
|
261 |
-
top_p=0.95,
|
262 |
-
top_k=64,
|
263 |
-
max_output_tokens=1024,
|
264 |
-
)
|
265 |
-
)
|
266 |
-
response_text = response.text.strip()
|
267 |
-
if "--ar 1:1" not in response_text:
|
268 |
-
response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2"
|
269 |
-
return response_text
|
270 |
-
except Exception as e:
|
271 |
-
return f"ν둬ννΈ μμ± μ€ μ€λ₯κ° λ°μνμ΅λλ€: {str(e)}"
|
272 |
|
273 |
-
|
|
|
|
|
274 |
if bg_type == "μ¬ν λ°°κ²½":
|
275 |
return {
|
276 |
"category": "μ¬ν λ°°κ²½",
|
@@ -295,6 +267,18 @@ def get_selected_background_info(bg_type, simple, studio, nature, indoor, abstra
|
|
295 |
"name": indoor,
|
296 |
"english": INDOOR_BACKGROUNDS.get(indoor, "indoor environment")
|
297 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
elif bg_type == "μΆμ/νΉμ λ°°κ²½":
|
299 |
return {
|
300 |
"category": "μΆμ/νΉμ λ°°κ²½",
|
@@ -308,24 +292,114 @@ def get_selected_background_info(bg_type, simple, studio, nature, indoor, abstra
|
|
308 |
"english": "white background"
|
309 |
}
|
310 |
|
311 |
-
#
|
312 |
-
def
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
|
323 |
# ------------------- λ¨μΌ μ΄λ―Έμ§ μμ± ν¨μ -------------------
|
324 |
-
def generate_product_image(image, bg_type, simple, studio, nature, indoor, abstract, product_name, additional_info):
|
325 |
if image is None:
|
326 |
return None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ.", "μ΄λ―Έμ§λ₯Ό μ
λ‘λ ν ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ."
|
327 |
product_name = product_name.strip() or "μ ν"
|
328 |
-
background_info = get_selected_background_info(bg_type, simple, studio, nature, indoor, abstract)
|
329 |
generated_prompt = generate_prompt_with_gemini(product_name, background_info, additional_info)
|
330 |
if "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€" in generated_prompt:
|
331 |
warning_msg = (
|
@@ -341,11 +415,11 @@ def generate_product_image(image, bg_type, simple, studio, nature, indoor, abstr
|
|
341 |
return result_image, status, final_prompt
|
342 |
|
343 |
# ------------------- 4μ₯ μ΄λ―Έμ§ μμ± ν¨μ -------------------
|
344 |
-
def generate_product_images(image, bg_type, simple, studio, nature, indoor, abstract, product_name, additional_info):
|
345 |
if image is None:
|
346 |
return None, None, None, None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ.", "μ΄λ―Έμ§λ₯Ό μ
λ‘λ ν ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ."
|
347 |
product_name = product_name.strip() or "μ ν"
|
348 |
-
background_info = get_selected_background_info(bg_type, simple, studio, nature, indoor, abstract)
|
349 |
generated_prompt = generate_prompt_with_gemini(product_name, background_info, additional_info)
|
350 |
if "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€" in generated_prompt:
|
351 |
warning_msg = (
|
@@ -377,9 +451,9 @@ def create_app():
|
|
377 |
)
|
378 |
with gr.Row():
|
379 |
with gr.Column(scale=1):
|
380 |
-
product_name = gr.Textbox(label="μνλͺ
(νκ΅μ΄ μ
λ ₯)", placeholder="μ: μ€ν¨μΌμ΄ νλΈ,
|
381 |
background_type = gr.Radio(
|
382 |
-
choices=["μ¬ν λ°°κ²½", "μ€νλμ€ λ°°κ²½", "μμ° νκ²½", "μ€λ΄ νκ²½", "μΆμ/νΉμ λ°°κ²½"],
|
383 |
label="λ°°κ²½ μ ν",
|
384 |
value="μ¬ν λ°°κ²½"
|
385 |
)
|
@@ -411,6 +485,20 @@ def create_app():
|
|
411 |
visible=False,
|
412 |
interactive=True
|
413 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
414 |
abstract_dropdown = gr.Dropdown(
|
415 |
choices=list(ABSTRACT_BACKGROUNDS.keys()),
|
416 |
value=list(ABSTRACT_BACKGROUNDS.keys())[0] if ABSTRACT_BACKGROUNDS else None,
|
@@ -430,12 +518,14 @@ def create_app():
|
|
430 |
studio_dropdown: gr.update(visible=(bg_type == "μ€νλμ€ λ°°κ²½")),
|
431 |
nature_dropdown: gr.update(visible=(bg_type == "μμ° νκ²½")),
|
432 |
indoor_dropdown: gr.update(visible=(bg_type == "μ€λ΄ νκ²½")),
|
|
|
|
|
433 |
abstract_dropdown: gr.update(visible=(bg_type == "μΆμ/νΉμ λ°°κ²½"))
|
434 |
}
|
435 |
background_type.change(
|
436 |
fn=update_dropdowns,
|
437 |
inputs=[background_type],
|
438 |
-
outputs=[simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown]
|
439 |
)
|
440 |
image_input = gr.Image(label="μν μ΄λ―Έμ§ μ
λ‘λ", type="pil")
|
441 |
with gr.Row():
|
@@ -455,17 +545,21 @@ def create_app():
|
|
455 |
prompt_output_multi = gr.Textbox(label="μμ±λ ν둬ννΈ (μμ΄)", lines=6)
|
456 |
single_btn.click(
|
457 |
fn=generate_product_image,
|
458 |
-
inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown, product_name, additional_info],
|
459 |
outputs=[image_output, status_output, prompt_output]
|
460 |
)
|
461 |
multi_btn.click(
|
462 |
fn=generate_product_images,
|
463 |
-
inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown, product_name, additional_info],
|
464 |
outputs=[image_output1, image_output2, image_output3, image_output4, status_output_multi, prompt_output_multi]
|
465 |
)
|
466 |
return demo
|
467 |
|
|
|
468 |
if __name__ == "__main__":
|
|
|
|
|
|
|
469 |
app = create_app()
|
470 |
app.queue()
|
471 |
-
app.launch()
|
|
|
17 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
18 |
logger = logging.getLogger(__name__)
|
19 |
|
20 |
+
# ------------------- λ°°κ²½ λλ ν 리 μ€μ -------------------
|
21 |
+
BACKGROUNDS_DIR = "./background"
|
22 |
+
if not os.path.exists(BACKGROUNDS_DIR):
|
23 |
+
os.makedirs(BACKGROUNDS_DIR)
|
24 |
+
logger.info(f"λ°°κ²½ λλ ν 리λ₯Ό μμ±νμ΅λλ€: {BACKGROUNDS_DIR}")
|
25 |
+
|
26 |
+
# ------------------- μ μ λ³μ μ€μ -------------------
|
27 |
+
SIMPLE_BACKGROUNDS = {}
|
28 |
+
STUDIO_BACKGROUNDS = {}
|
29 |
+
NATURE_BACKGROUNDS = {}
|
30 |
+
INDOOR_BACKGROUNDS = {}
|
31 |
+
TECHNOLOGY_BACKGROUNDS = {}
|
32 |
+
COLORFUL_PATTERN_BACKGROUNDS = {}
|
33 |
+
ABSTRACT_BACKGROUNDS = {}
|
34 |
+
|
35 |
+
# ------------------- λ°°κ²½ JSON νμΌ λ‘λ ν¨μ -------------------
|
36 |
+
def load_background_json(filename):
|
37 |
+
file_path = os.path.join(BACKGROUNDS_DIR, filename)
|
38 |
+
try:
|
39 |
+
with open(file_path, 'r', encoding='utf-8') as f:
|
40 |
+
data = json.load(f)
|
41 |
+
logger.info(f"{filename} νμΌμ μ±κ³΅μ μΌλ‘ λ‘λνμ΅λλ€. {len(data)} νλͺ© ν¬ν¨.")
|
42 |
+
return data
|
43 |
+
except FileNotFoundError:
|
44 |
+
logger.info(f"{filename} νμΌμ΄ μμ΅λλ€.")
|
45 |
+
return {}
|
46 |
+
except Exception as e:
|
47 |
+
logger.warning(f"{filename} νμΌ λ‘λ μ€ μ€λ₯ λ°μ: {str(e)}.")
|
48 |
+
return {}
|
49 |
+
|
50 |
+
# ------------------- λ°°κ²½ μ΄κΈ°ν ν¨μ -------------------
|
51 |
+
def initialize_backgrounds():
|
52 |
+
global SIMPLE_BACKGROUNDS, STUDIO_BACKGROUNDS, NATURE_BACKGROUNDS, INDOOR_BACKGROUNDS
|
53 |
+
global TECHNOLOGY_BACKGROUNDS, COLORFUL_PATTERN_BACKGROUNDS, ABSTRACT_BACKGROUNDS
|
54 |
+
|
55 |
+
SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
|
56 |
+
STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
|
57 |
+
NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
|
58 |
+
INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
|
59 |
+
TECHNOLOGY_BACKGROUNDS = load_background_json("technology_backgrounds.json")
|
60 |
+
COLORFUL_PATTERN_BACKGROUNDS = load_background_json("colorful_pattern_backgrounds.json")
|
61 |
+
ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
|
62 |
+
|
63 |
+
# κΈ°λ³Έκ° μ€μ (JSON νμΌμ΄ μκ±°λ λΉμ΄μλ κ²½μ°)
|
64 |
+
if not SIMPLE_BACKGROUNDS:
|
65 |
+
SIMPLE_BACKGROUNDS = {"νμ΄νΈ λ°°κ²½": "white background"}
|
66 |
+
if not STUDIO_BACKGROUNDS:
|
67 |
+
STUDIO_BACKGROUNDS = {"λ―Έλλ© νλ«λ μ΄": "minimalist flat lay with clean white background"}
|
68 |
+
if not NATURE_BACKGROUNDS:
|
69 |
+
NATURE_BACKGROUNDS = {"μ΄λ ν΄λ³": "tropical beach with crystal clear water"}
|
70 |
+
if not INDOOR_BACKGROUNDS:
|
71 |
+
INDOOR_BACKGROUNDS = {"λ―Έλλ© μ€μΉΈλλλΉμ κ±°μ€": "minimalist Scandinavian living room"}
|
72 |
+
if not TECHNOLOGY_BACKGROUNDS:
|
73 |
+
TECHNOLOGY_BACKGROUNDS = {"λ€μ΄λλ―Ή μ€νλμ": "dynamic water splash interaction with product"}
|
74 |
+
if not COLORFUL_PATTERN_BACKGROUNDS:
|
75 |
+
COLORFUL_PATTERN_BACKGROUNDS = {"νλ €ν κ½ ν¨ν΄": "vibrant floral pattern backdrop"}
|
76 |
+
if not ABSTRACT_BACKGROUNDS:
|
77 |
+
ABSTRACT_BACKGROUNDS = {"λ€μ¨ μ‘°λͺ
": "neon lights abstract background"}
|
78 |
+
|
79 |
+
logger.info("λͺ¨λ λ°°κ²½ μ΅μ
λ‘λ μλ£")
|
80 |
+
|
81 |
# ------------------- κΈ°λ³Έ μ΄λ―Έμ§ μμ± κ΄λ ¨ ν¨μ -------------------
|
82 |
def save_binary_file(file_name, data):
|
83 |
with open(file_name, "wb") as f:
|
|
|
147 |
return None, "API ν€κ° μ€μ λμ§ μμμ΅λλ€. νκ²½λ³μλ₯Ό νμΈν΄μ£ΌμΈμ."
|
148 |
client = genai.Client(api_key=api_key)
|
149 |
logger.info(f"Gemini API μμ² μμ - ν둬ννΈ: {prompt}, λ³ν μΈλ±μ€: {variation_index}")
|
150 |
+
|
151 |
+
# ν₯μλ λ³ν μ λ―Έμ¬
|
152 |
variation_suffixes = [
|
153 |
+
" Create this as a professional studio product shot with precise focus on the product details. Do not add any text, watermarks, or labels to the image.",
|
154 |
+
" Create this as a high-contrast artistic studio shot with dramatic lighting and shadows. Do not add any text, watermarks, or labels to the image.",
|
155 |
+
" Create this as a soft-lit elegantly styled product shot with complementary elements. Do not add any text, watermarks, or labels to the image.",
|
156 |
+
" Create this as a high-definition product photography with perfect color accuracy and detail preservation. Do not add any text, watermarks, or labels to the image."
|
157 |
]
|
158 |
+
|
159 |
if variation_index < len(variation_suffixes):
|
160 |
prompt = prompt + variation_suffixes[variation_index]
|
161 |
else:
|
162 |
+
prompt = prompt + " Create as high-end commercial product photography. Do not add any text, watermarks, or labels to the image."
|
163 |
+
|
164 |
contents = [prompt]
|
165 |
for idx, img in enumerate(images, 1):
|
166 |
if img is not None:
|
167 |
contents.append(img)
|
168 |
logger.info(f"μ΄λ―Έμ§ #{idx} μΆκ°λ¨")
|
169 |
+
|
170 |
+
# ν₯μλ μμ± μ€μ - λ λμ temperatureλ‘ μ°½μμ± μ¦κ°, λ λμ max_output_tokens
|
171 |
response = client.models.generate_content(
|
172 |
model="gemini-2.0-flash-exp-image-generation",
|
173 |
contents=contents,
|
174 |
config=types.GenerateContentConfig(
|
175 |
response_modalities=['Text', 'Image'],
|
176 |
+
temperature=1.05, # μ½κ° λμ μ¨λλ‘ λ λ€μν κ²°κ³Ό
|
177 |
+
top_p=0.97, # μ½κ° λμ
|
178 |
+
top_k=50, # λ€μμ± μ¦κ°
|
179 |
+
max_output_tokens=10240 # λ λμ ν ν° νλ
|
180 |
)
|
181 |
)
|
182 |
+
|
183 |
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
|
184 |
temp_path = tmp.name
|
185 |
result_text = ""
|
|
|
228 |
time.sleep(1)
|
229 |
return None, f"μ΅λ μ¬μλ νμ({max_retries}ν) μ΄κ³Ό ν μ€ν¨: {last_error}", prompt
|
230 |
|
231 |
+
# ------------------- ν둬ννΈμμ μ€μ§ Midjourney ν둬ννΈ ν
μ€νΈλ§ μΆμΆνλ ν¨μ -------------------
|
232 |
+
def filter_prompt_only(prompt):
|
233 |
+
idx = prompt.find("Highly detailed commercial photography")
|
234 |
+
if idx != -1:
|
235 |
+
prompt_text = prompt[idx:].strip()
|
236 |
+
end_idx = prompt_text.rfind("--ar 1:1 --s 750 --q 2")
|
237 |
+
if end_idx != -1:
|
238 |
+
end_idx += len("--ar 1:1 --s 750 --q 2")
|
239 |
+
prompt_text = prompt_text[:end_idx].strip()
|
240 |
+
return prompt_text
|
241 |
+
return prompt.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
|
243 |
+
# ------------------- μ νλ λ°°κ²½ μ 보 κ°μ Έμ€κΈ° ν¨μ -------------------
|
244 |
+
def get_selected_background_info(bg_type, simple, studio, nature, indoor, tech, colorful, abstract):
|
245 |
+
"""μ νλ λ°°κ²½ μ 보λ₯Ό κ°μ Έμ€λ ν¨μ"""
|
246 |
if bg_type == "μ¬ν λ°°κ²½":
|
247 |
return {
|
248 |
"category": "μ¬ν λ°°κ²½",
|
|
|
267 |
"name": indoor,
|
268 |
"english": INDOOR_BACKGROUNDS.get(indoor, "indoor environment")
|
269 |
}
|
270 |
+
elif bg_type == "ν
ν¬λλ‘μ§ λ°°κ²½":
|
271 |
+
return {
|
272 |
+
"category": "ν
ν¬λλ‘μ§ λ°°κ²½",
|
273 |
+
"name": tech,
|
274 |
+
"english": TECHNOLOGY_BACKGROUNDS.get(tech, "technology environment")
|
275 |
+
}
|
276 |
+
elif bg_type == "컬λ¬ν ν¨ν΄ λ°°κ²½":
|
277 |
+
return {
|
278 |
+
"category": "컬λ¬ν ν¨ν΄ λ°°κ²½",
|
279 |
+
"name": colorful,
|
280 |
+
"english": COLORFUL_PATTERN_BACKGROUNDS.get(colorful, "colorful pattern background")
|
281 |
+
}
|
282 |
elif bg_type == "μΆμ/νΉμ λ°°κ²½":
|
283 |
return {
|
284 |
"category": "μΆμ/νΉμ λ°°κ²½",
|
|
|
292 |
"english": "white background"
|
293 |
}
|
294 |
|
295 |
+
# ------------------- ν₯μλ μμ€ν
μΈμ€νΈλμ
μμ± ν¨μ -------------------
|
296 |
+
def generate_enhanced_system_instruction():
|
297 |
+
"""ν₯μλ μμ€ν
μΈμ€νΈλμ
μμ± ν¨μ"""
|
298 |
+
return """λΉμ μ μν μ΄λ―Έμ§μ λ°°κ²½μ λ³κ²½νκΈ° μν μ΅κ³ νμ§μ ν둬ννΈλ₯Ό μμ±νλ μ λ¬Έκ°μ
λλ€.
|
299 |
+
μ¬μ©μκ° μ 곡νλ μνλͺ
, λ°°κ²½ μ ν, μΆκ° μμ²μ¬νμ λ°νμΌλ‘ λ―Έλμ λ(Midjourney)μ μ¬μ©ν μ μλ μμΈνκ³ μ λ¬Έμ μΈ ν둬ννΈλ₯Ό μμ΄λ‘ μμ±ν΄μ£ΌμΈμ.
|
300 |
+
|
301 |
+
λ€μ κ°μ΄λλΌμΈμ λ°λμ μ€μν΄μΌ ν©λλ€:
|
302 |
+
|
303 |
+
1. μνμ "#1"λ‘ μ§μ νμ¬ μ°Έμ‘°ν©λλ€. (μ: "skincare tube (#1)")
|
304 |
+
|
305 |
+
2. *** λ§€μ° μ€μ: μνμ μλ νΉμ±(λμμΈ, μμ, νν, λ‘κ³ , ν¨ν€μ§ λ±)μ μ΄λ€ μν©μμλ μ λ λ³κ²½νμ§ μμ΅λλ€. ***
|
306 |
+
|
307 |
+
3. *** μνμ λ³Έμ§μ νΉμ±μ μ μ§νλ, μνμ ν¬μ»€μ€λ₯Ό λ§μΆ° λͺ¨λ μΈλΆ μ¬νμ΄ μ λͺ
νκ² λλ¬λλλ‘ νλ©°,
|
308 |
+
8K ν΄μλ(8K resolution), μ€λ²μ€νλ μλ μ΄κ³ νμ§(ultra high definition without oversharpening)λ‘ λ λλ§λμ΄μΌ ν©λλ€. ***
|
309 |
+
|
310 |
+
4. μ΄λ―Έμ§ λΉμ¨μ μ νν 1:1(μ μ¬κ°ν) νμμΌλ‘ μ§μ ν©λλ€. ν둬ννΈμ "square format", "1:1 ratio" λλ "aspect ratio 1:1"μ λͺ
μμ μΌλ‘ ν¬ν¨ν©λλ€.
|
311 |
+
|
312 |
+
5. μνμ λ°λμ μ μ¬κ°ν ꡬλμ μ μ€μμ λ°°μΉλμ΄μΌ νλ©°, μ μ ν ν¬κΈ°λ‘ νννμ¬ λν
μΌμ΄ μλ²½νκ² λ³΄μ΄λλ‘ ν©λλ€.
|
313 |
+
|
314 |
+
6. μνμ μ΄λ―Έμ§μ μ£Όμ μ΄μ μΌλ‘ λΆκ°μν€κ³ , μνμ λΉμ¨μ΄ μ 체 μ΄λ―Έμ§μμ 60-70% μ΄μ μ°¨μ§νλλ‘ ν©λλ€.
|
315 |
+
|
316 |
+
7. μ‘°λͺ
μ€λͺ
μ λ§€μ° κ΅¬μ²΄μ μΌλ‘ ν΄μ£ΌμΈμ. μ: "soft directional lighting from left side", "dramatic rim lighting", "diffused natural light through windows"
|
317 |
+
|
318 |
+
8. λ°°κ²½μ μ¬μ§κ³Ό μ§κ°μ μμΈν μ€λͺ
ν΄μ£ΌμΈμ. μ: "polished marble surface", "rustic wooden table with visible grain", "matte concrete wall with subtle texture"
|
319 |
+
|
320 |
+
9. ν둬ννΈμ λ€μ μμλ€μ λͺ
μμ μΌλ‘ ν¬ν¨νλ, μ¬μ© λ§₯λ½μ μ μ νκ² λ³ννμΈμ:
|
321 |
+
- "award-winning product photography"
|
322 |
+
- "magazine-worthy commercial product shot"
|
323 |
+
- "professional advertising imagery with perfect exposure"
|
324 |
+
- "studio lighting with color-accurate rendering"
|
325 |
+
- "8K ultra high definition product showcase"
|
326 |
+
- "commercial product photography with precise detail rendering"
|
327 |
+
- "ultra high definition"
|
328 |
+
- "crystal clear details"
|
329 |
+
|
330 |
+
10. μ¬μ©μκ° μ 곡ν ꡬ체μ μΈ λ°°κ²½κ³Ό μΆκ° μμ²μ¬νμ ν둬ννΈμ μ νν λ°μνκ³ νμ₯ν©λλ€.
|
331 |
+
|
332 |
+
11. ν둬ννΈ λμ "--ar 1:1 --s 750 --q 2 --v 5.2" νλΌλ―Έν°λ₯Ό μΆκ°νμ¬ λ―Έλμ λμμ κ³ νμ§ μ μ¬κ°ν λΉμ¨μ κ°μ ν©λλ€.
|
333 |
+
"""
|
334 |
+
|
335 |
+
# ------------------- ν둬ννΈ μμ± ν¨μ -------------------
|
336 |
+
def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
|
337 |
+
"""ν₯μλ ν둬ννΈ μμ± ν¨μ"""
|
338 |
+
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
|
339 |
+
if not GEMINI_API_KEY:
|
340 |
+
return "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€. νκ²½ λ³μ GEMINI_API_KEYλ₯Ό μ€μ νκ±°λ μ½λμ μ§μ μ
λ ₯νμΈμ."
|
341 |
+
|
342 |
+
try:
|
343 |
+
genai_generative.configure(api_key=GEMINI_API_KEY)
|
344 |
+
|
345 |
+
# λ μμΈν ν둬ννΈ μμ² ν
νλ¦Ώ
|
346 |
+
prompt_request = f"""
|
347 |
+
μνλͺ
: {product_name}
|
348 |
+
λ°°κ²½ μ ν: {background_info.get('english', 'studio')}
|
349 |
+
λ°°κ²½ μΉ΄ν
κ³ λ¦¬: {background_info.get('category', '')}
|
350 |
+
λ°°κ²½ μ΄λ¦: {background_info.get('name', '')}
|
351 |
+
μΆκ° μμ²μ¬ν: {additional_info}
|
352 |
+
|
353 |
+
μ€μ μꡬμ¬ν:
|
354 |
+
1. μν(#1)μ΄ μ΄λ―Έμ§ ꡬλμμ μ€μ¬μ μΈ μμΉλ₯Ό μ°¨μ§νλ©° μ μ ν ν¬κΈ°(μ΄λ―Έμ§μ 60-70%)λ‘ ννλλλ‘ ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ.
|
355 |
+
2. μ΄λ―Έμ§λ μ νν 1:1 λΉμ¨(μ μ¬κ°ν)μ΄μ΄μΌ ν©λλ€.
|
356 |
+
3. μνμ λμμΈ, μμ, νν, λ‘κ³ λ± λ³Έμ§μ νΉμ±μ μ λ μμ νμ§ λ§μΈμ.
|
357 |
+
4. ꡬ체μ μΈ μ‘°λͺ
κΈ°λ²μ μμΈν λͺ
μν΄μ£ΌμΈμ:
|
358 |
+
- μ νν μ‘°λͺ
μμΉ (μ: "45-degree key light from upper left")
|
359 |
+
- μ‘°λͺ
νμ§ (μ: "soft diffused light", "hard directional light")
|
360 |
+
- μ‘°λͺ
κ°λμ μμ¨λ (μ: "warm tungsten key light with cool blue fill")
|
361 |
+
- λ°μ¬μ κ·Έλ¦Όμ μ²λ¦¬ λ°©μ (μ: "controlled specular highlights with soft shadow transitions")
|
362 |
+
5. μνμ λ λ보μ΄κ² νλ 보쑰 μμ(props)λ₯Ό μμ°μ€λ½κ² νμ©νλ, μνμ΄ νμ μ£ΌμΈκ³΅μ΄μ΄μΌ ν©λλ€.
|
363 |
+
6. λ°°κ²½ μ¬μ§κ³Ό νλ©΄ μ§κ°μ ꡬ체μ μΌλ‘ μ€λͺ
νκ³ , μνκ³Όμ μνΈμμ© λ°©μμ λͺ
μν΄μ£ΌμΈμ.
|
364 |
+
7. μμ ꡬμ±(color palette, color harmonies)μ λͺ
νν ν΄μ£ΌμΈμ.
|
365 |
+
8. κ³ κΈμ€λ¬μ΄ μμ
κ΄κ³ νμ§μ μ΄λ―Έμ§κ° λλλ‘ ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ.
|
366 |
+
9. ν둬ννΈ λμ λ―Έλμ λ νλΌλ―Έν° "--ar 1:1 --s 750 --q 2 --v 5.2"λ₯Ό μΆκ°ν΄μ£ΌμΈμ.
|
367 |
+
|
368 |
+
νκ΅μ΄ μ
λ ₯ λ΄μ©μ μ λ¬Έμ μΈ μμ΄λ‘ λ²μνμ¬ λ°μν΄μ£ΌμΈμ.
|
369 |
+
"""
|
370 |
+
# ν₯μλ μμ€ν
μΈμ€νΈλμ
μ¬μ©
|
371 |
+
model = genai_generative.GenerativeModel(
|
372 |
+
'gemini-2.0-flash',
|
373 |
+
system_instruction=generate_enhanced_system_instruction()
|
374 |
+
)
|
375 |
+
|
376 |
+
# λ μ°½μμ μΈ κ²°κ³Όλ₯Ό μν μμ± μ€μ μ‘°μ
|
377 |
+
response = model.generate_content(
|
378 |
+
prompt_request,
|
379 |
+
generation_config=genai_generative.types.GenerationConfig(
|
380 |
+
temperature=0.8, # λ μ°½μμ μΈ κ²°κ³Όλ₯Ό μν΄ μ¨λ μν₯
|
381 |
+
top_p=0.97,
|
382 |
+
top_k=64,
|
383 |
+
max_output_tokens=1600, # λ μμΈν ν둬ννΈ νμ©
|
384 |
+
)
|
385 |
+
)
|
386 |
+
|
387 |
+
response_text = response.text.strip()
|
388 |
+
|
389 |
+
# λ―Έλμ λ νλΌλ―Έν°κ° μμ κ²½μ° μΆκ°
|
390 |
+
if "--ar 1:1" not in response_text:
|
391 |
+
response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2 --v 5.2"
|
392 |
+
|
393 |
+
return response_text
|
394 |
+
except Exception as e:
|
395 |
+
return f"ν둬ννΈ μμ± μ€ μ€λ₯κ° λ°μνμ΅λλ€: {str(e)}"
|
396 |
|
397 |
# ------------------- λ¨μΌ μ΄λ―Έμ§ μμ± ν¨μ -------------------
|
398 |
+
def generate_product_image(image, bg_type, simple, studio, nature, indoor, tech, colorful, abstract, product_name, additional_info):
|
399 |
if image is None:
|
400 |
return None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ.", "μ΄λ―Έμ§λ₯Ό μ
λ‘λ ν ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ."
|
401 |
product_name = product_name.strip() or "μ ν"
|
402 |
+
background_info = get_selected_background_info(bg_type, simple, studio, nature, indoor, tech, colorful, abstract)
|
403 |
generated_prompt = generate_prompt_with_gemini(product_name, background_info, additional_info)
|
404 |
if "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€" in generated_prompt:
|
405 |
warning_msg = (
|
|
|
415 |
return result_image, status, final_prompt
|
416 |
|
417 |
# ------------------- 4μ₯ μ΄λ―Έμ§ μμ± ν¨μ -------------------
|
418 |
+
def generate_product_images(image, bg_type, simple, studio, nature, indoor, tech, colorful, abstract, product_name, additional_info):
|
419 |
if image is None:
|
420 |
return None, None, None, None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ.", "μ΄λ―Έμ§λ₯Ό μ
λ‘λ ν ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ."
|
421 |
product_name = product_name.strip() or "μ ν"
|
422 |
+
background_info = get_selected_background_info(bg_type, simple, studio, nature, indoor, tech, colorful, abstract)
|
423 |
generated_prompt = generate_prompt_with_gemini(product_name, background_info, additional_info)
|
424 |
if "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€" in generated_prompt:
|
425 |
warning_msg = (
|
|
|
451 |
)
|
452 |
with gr.Row():
|
453 |
with gr.Column(scale=1):
|
454 |
+
product_name = gr.Textbox(label="μνλͺ
(νκ΅μ΄ μ
λ ₯)", placeholder="μ: μ€ν¨μΌμ΄ νλΈ, μ€λ§νΈμμΉ, ν₯μ, μ΄λν λ±", interactive=True)
|
455 |
background_type = gr.Radio(
|
456 |
+
choices=["μ¬ν λ°°κ²½", "μ€νλμ€ λ°°κ²½", "μμ° νκ²½", "μ€λ΄ νκ²½", "ν
ν¬λλ‘μ§ λ°°κ²½", "컬λ¬ν ν¨ν΄ λ°°κ²½", "μΆμ/νΉμ λ°°κ²½"],
|
457 |
label="λ°°κ²½ μ ν",
|
458 |
value="μ¬ν λ°°κ²½"
|
459 |
)
|
|
|
485 |
visible=False,
|
486 |
interactive=True
|
487 |
)
|
488 |
+
tech_dropdown = gr.Dropdown(
|
489 |
+
choices=list(TECHNOLOGY_BACKGROUNDS.keys()),
|
490 |
+
value=list(TECHNOLOGY_BACKGROUNDS.keys())[0] if TECHNOLOGY_BACKGROUNDS else None,
|
491 |
+
label="ν
ν¬λλ‘μ§ λ°°κ²½ μ ν",
|
492 |
+
visible=False,
|
493 |
+
interactive=True
|
494 |
+
)
|
495 |
+
colorful_dropdown = gr.Dropdown(
|
496 |
+
choices=list(COLORFUL_PATTERN_BACKGROUNDS.keys()),
|
497 |
+
value=list(COLORFUL_PATTERN_BACKGROUNDS.keys())[0] if COLORFUL_PATTERN_BACKGROUNDS else None,
|
498 |
+
label="컬λ¬ν ν¨ν΄ λ°°κ²½ μ ν",
|
499 |
+
visible=False,
|
500 |
+
interactive=True
|
501 |
+
)
|
502 |
abstract_dropdown = gr.Dropdown(
|
503 |
choices=list(ABSTRACT_BACKGROUNDS.keys()),
|
504 |
value=list(ABSTRACT_BACKGROUNDS.keys())[0] if ABSTRACT_BACKGROUNDS else None,
|
|
|
518 |
studio_dropdown: gr.update(visible=(bg_type == "μ€νλμ€ λ°°κ²½")),
|
519 |
nature_dropdown: gr.update(visible=(bg_type == "μμ° νκ²½")),
|
520 |
indoor_dropdown: gr.update(visible=(bg_type == "μ€λ΄ νκ²½")),
|
521 |
+
tech_dropdown: gr.update(visible=(bg_type == "ν
ν¬λλ‘μ§ λ°°κ²½")),
|
522 |
+
colorful_dropdown: gr.update(visible=(bg_type == "컬λ¬ν ν¨ν΄ λ°°κ²½")),
|
523 |
abstract_dropdown: gr.update(visible=(bg_type == "μΆμ/νΉμ λ°°κ²½"))
|
524 |
}
|
525 |
background_type.change(
|
526 |
fn=update_dropdowns,
|
527 |
inputs=[background_type],
|
528 |
+
outputs=[simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown]
|
529 |
)
|
530 |
image_input = gr.Image(label="μν μ΄λ―Έμ§ μ
λ‘λ", type="pil")
|
531 |
with gr.Row():
|
|
|
545 |
prompt_output_multi = gr.Textbox(label="μμ±λ ν둬ννΈ (μμ΄)", lines=6)
|
546 |
single_btn.click(
|
547 |
fn=generate_product_image,
|
548 |
+
inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown, product_name, additional_info],
|
549 |
outputs=[image_output, status_output, prompt_output]
|
550 |
)
|
551 |
multi_btn.click(
|
552 |
fn=generate_product_images,
|
553 |
+
inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown, product_name, additional_info],
|
554 |
outputs=[image_output1, image_output2, image_output3, image_output4, status_output_multi, prompt_output_multi]
|
555 |
)
|
556 |
return demo
|
557 |
|
558 |
+
# ------------------- λ©μΈ μ€ν ν¨μ -------------------
|
559 |
if __name__ == "__main__":
|
560 |
+
# λ°°κ²½ μ΅μ
μ΄κΈ°ν
|
561 |
+
initialize_backgrounds()
|
562 |
+
# μ± μμ± λ° μ€ν
|
563 |
app = create_app()
|
564 |
app.queue()
|
565 |
+
app.launch()
|