Kims12 commited on
Commit
b32830a
ยท
verified ยท
1 Parent(s): ad645a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -177
app.py CHANGED
@@ -17,7 +17,7 @@ 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:
23
  f.write(data)
@@ -144,15 +144,8 @@ def process_images_with_prompt(image1, prompt, variation_index=0, max_retries=3)
144
  valid_images = [img for img in images if img is not None]
145
  if not valid_images:
146
  return None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
147
- if prompt and prompt.strip():
148
- processed_prompt = preprocess_prompt(prompt, image1)
149
- if re.search("[๊ฐ€-ํžฃ]", processed_prompt):
150
- final_prompt = translate_prompt_to_english(processed_prompt)
151
- else:
152
- final_prompt = processed_prompt
153
- else:
154
- 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."
155
- logger.info("Default prompt generated for single image")
156
  result_img, status = generate_with_images(final_prompt, valid_images, variation_index)
157
  if result_img is not None:
158
  return result_img, status, final_prompt
@@ -168,34 +161,7 @@ def process_images_with_prompt(image1, prompt, variation_index=0, max_retries=3)
168
  time.sleep(1)
169
  return None, f"์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜({max_retries}ํšŒ) ์ดˆ๊ณผ ํ›„ ์‹คํŒจ: {last_error}", prompt
170
 
171
- def generate_multiple_images(image1, prompt, progress=gr.Progress()):
172
- results = []
173
- statuses = []
174
- prompts = []
175
- num_images = 4
176
- max_retries = 3
177
- progress(0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค€๋น„ ์ค‘...")
178
- for i in range(num_images):
179
- progress((i / num_images), desc=f"{i+1}/{num_images} ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘...")
180
- result_img, status, final_prompt = process_images_with_prompt(image1, prompt, i, max_retries)
181
- if result_img is not None:
182
- results.append(result_img)
183
- statuses.append(f"์ด๋ฏธ์ง€ #{i+1}: {status}")
184
- prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
185
- else:
186
- results.append(None)
187
- statuses.append(f"์ด๋ฏธ์ง€ #{i+1} ์ƒ์„ฑ ์‹คํŒจ: {status}")
188
- prompts.append(f"์ด๋ฏธ์ง€ #{i+1}: {final_prompt}")
189
- time.sleep(1)
190
- progress(1.0, desc="์ด๋ฏธ์ง€ ์ƒ์„ฑ ์™„๋ฃŒ!")
191
- while len(results) < 4:
192
- results.append(None)
193
- combined_status = "\n".join(statuses)
194
- combined_prompts = "\n".join(prompts)
195
- return results[0], results[1], results[2], results[3], combined_status, combined_prompts
196
-
197
- # ------------------- ์ƒํ’ˆ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๊ด€๋ จ ํ•จ์ˆ˜ (์ฐธ์กฐ์ฝ”๋“œ) -------------------
198
-
199
  # ๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๊ฒฝ๋กœ ์„ค์ •
200
  BACKGROUNDS_DIR = "./background"
201
  if not os.path.exists(BACKGROUNDS_DIR):
@@ -250,7 +216,7 @@ def generate_system_instruction():
250
  6. ์ƒํ’ˆ์„ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์ดˆ์ ์œผ๋กœ ๋ถ€๊ฐ์‹œํ‚ค๊ณ , ์ƒํ’ˆ์˜ ๋น„์œจ์ด ์ „์ฒด ์ด๋ฏธ์ง€์—์„œ ํฌ๊ฒŒ ์ฐจ์ง€ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
251
  7. ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์ปท์•„์›ƒ(#1)์˜ ๊ธฐ๋ณธ ํ˜•ํƒœ์™€ ์ƒ‰์ƒ์€ ์œ ์ง€ํ•˜๋ฉด์„œ, ์„ ํƒํ•œ ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
252
  8. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—…์  ์ด๋ฏธ์ง€๋ฅผ ์œ„ํ•œ ๋‹ค์Œ ํ™˜๊ฒฝ ์š”์†Œ๋“ค์„ ํฌํ•จํ•˜์„ธ์š”:
253
- - ์ƒํ’ˆ๊ณผ ์–ด์šธ๋ฆฌ๋Š” ์ฃผ๋ณ€ ํ™˜๊ฒฝ/๋ฐฐ๊ฒฝ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ™”์žฅํ’ˆ ์ฃผ๋ณ€์— ๊ฝƒ์ด๋‚˜ ํ—ˆ๋ธŒ, ์Œ๋ฃŒ ์ œํ’ˆ ์˜†์— ๊ณผ์ผ, ์ „์ž์ œํ’ˆ ๊ทผ์ฒ˜์— ํ˜„๋Œ€์  ์†Œํ’ˆ ๋“ฑ.
254
  - ํ™˜๊ฒฝ์˜ ์กฐ๋ช… ํšจ๊ณผ(๋ฆผ ๋ผ์ดํŠธ, ๋ฐฑ๋ผ์ดํŠธ, ์†Œํ”„ํŠธ๋ฐ•์Šค ๋“ฑ)๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
255
  - ์ƒํ’ˆ์ด ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋„๋ก ์ ์ ˆํ•œ ๊ทธ๋ฆผ์ž์™€ ๋น› ํ‘œํ˜„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
256
  - ์ƒํ’ˆ์˜ ์šฉ๋„๋‚˜ ์žฅ์ ์„ ๊ฐ„์ ‘์ ์œผ๋กœ ์•”์‹œํ•˜๋Š” ๋ฐฐ๊ฒฝ ์š”์†Œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
@@ -261,16 +227,10 @@ def generate_system_instruction():
261
  - "professional advertising imagery"
262
  - "studio quality"
263
  - "magazine advertisement quality"
264
- 10. ๋ฐฐ๊ฒฝ ํ™˜๊ฒฝ ์š”์†Œ๋ฅผ ์ƒํ’ˆ ์นดํ…Œ๊ณ ๋ฆฌ์— ๋งž๊ฒŒ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค:
265
- - ์Šคํ‚จ์ผ€์–ด ์ œํ’ˆ: ๊นจ๋—ํ•œ ์š•์‹ค ์„ ๋ฐ˜, ์šฐ์•„ํ•œ ํ™”์žฅ๋Œ€, ์ŠคํŒŒ ๊ฐ™์€ ํ™˜๊ฒฝ ๋“ฑ
266
- - ์Œ๋ฃŒ ์ œํ’ˆ: ์„ธ๋ จ๋œ ํ…Œ์ด๋ธ”, ํŒŒํ‹ฐ ํ™˜๊ฒฝ, ์•ผ์™ธ ํ”ผํฌ๋‹‰ ์žฅ๋ฉด ๋“ฑ
267
- - ์ „์ž ์ œํ’ˆ: ์„ธ๋ จ๋œ ์ž‘์—… ๊ณต๊ฐ„, ํ˜„๋Œ€์ ์ธ ๊ฑฐ์‹ค, ๋ฏธ๋‹ˆ๋ฉ€ํ•œ ์ฑ…์ƒ ๋“ฑ
268
- - ํŒจ์…˜/์˜๋ฅ˜: ์„ธ๋ จ๋œ ์‡ผ๋ฃธ, ๋„์‹œ ๊ฑฐ๋ฆฌ, ์—˜๋ ˆ๊ฐ•์Šคํ•œ ๋ผ์ดํ”„์Šคํƒ€์ผ ํ™˜๊ฒฝ ๋“ฑ
269
- - ์‹ํ’ˆ ์ œํ’ˆ: ๊น”๋”ํ•œ ์ฃผ๋ฐฉ, ์‹ํƒ, ์š”๋ฆฌ ํ™˜๊ฒฝ ๋“ฑ
270
  11. ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฐ๊ฒฝ๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
271
  12. ํ”„๋กฌํ”„ํŠธ๋Š” ๋ฏธ๋“œ์ €๋‹ˆ AI์— ์ตœ์ ํ™”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
272
  13. ํ”„๋กฌํ”„ํŠธ ๋์— "--ar 1:1 --s 750 --q 2" ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฏธ๋“œ์ €๋‹ˆ์—์„œ ๊ณ ํ’ˆ์งˆ ์ •์‚ฌ๊ฐํ˜• ๋น„์œจ์„ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
273
- ์ถœ๋ ฅ ํ˜•์‹์€ ์˜์–ด๋กœ ๋œ ๋‹จ์ผ ๋‹จ๋ฝ์˜ ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ์—ฌ์•ผ ํ•˜๋ฉฐ, ๋์— ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
274
  """
275
 
276
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
@@ -354,91 +314,40 @@ def get_selected_background_info(bg_type, simple, studio, nature, indoor, abstra
354
  "english": "white background"
355
  }
356
 
357
- def generate_product_prompt_output(image, bg_type, simple, studio, nature, indoor, abstract, product_name, additional_info):
 
358
  if image is None:
359
- gr.Warning("์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.")
360
- return "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œ ํ›„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
361
  product_name = product_name.strip() or "์ œํ’ˆ"
362
  background_info = get_selected_background_info(bg_type, simple, studio, nature, indoor, abstract)
363
- try:
364
- prompt = generate_prompt_with_gemini(product_name, background_info, additional_info)
365
- if "Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค" in prompt:
366
- gr.Warning("Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.")
367
- prompt = """
368
- [Gemini API ํ‚ค ๋ˆ„๋ฝ]
369
- API ํ‚ค ์„ค์ • ๋ฐฉ๋ฒ•:
370
- 1. ํ™˜๊ฒฝ ๋ณ€์ˆ˜: export GEMINI_API_KEY="your-api-key"
371
- 2. ์ฝ”๋“œ ๋‚ด ์ง์ ‘ ์ž…๋ ฅ: GEMINI_API_KEY = "your-api-key"
372
- ํ‚ค ๋ฐœ๊ธ‰: https://makersuite.google.com/
373
- """
374
- return prompt, image, "API ํ‚ค๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."
375
- preview = f"""
376
- <div style="padding:10px; border:1px solid #ddd; border-radius:8px; margin-top:10px;">
377
- <h3>ํ”„๋กฌํ”„ํŠธ ์š”์•ฝ</h3>
378
- <p><strong>์ด ๊ธธ์ด:</strong> {len(prompt)} ๊ธ€์ž</p>
379
- <p><strong>๋ฐฐ๊ฒฝ:</strong> {background_info['category']} &gt; {background_info['name']}</p>
380
- <p><strong>๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ:</strong> {" ".join([param for param in ["--ar 1:1", "--s 750", "--q 2"] if param in prompt])}</p>
381
- </div>
382
- """
383
- return prompt, image, preview
384
- except Exception as e:
385
- error_msg = f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
386
- gr.Error(error_msg)
387
- return error_msg, image, "์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."
388
-
389
- # ------------------- Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ -------------------
390
-
391
- def create_basic_app():
392
- with gr.Blocks() as basic_app:
393
- with gr.Column():
394
- with gr.Group():
395
- with gr.Column():
396
- with gr.Row():
397
- image1_input = gr.Image(type="pil", label="์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", image_mode="RGB")
398
- prompt_input = gr.Textbox(
399
- lines=3,
400
- placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”. '#1'์œผ๋กœ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.",
401
- label="ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ"
402
- )
403
- with gr.Row():
404
- submit_single_btn = gr.Button('์ด๋ฏธ์ง€ ์ƒ์„ฑ (1์žฅ)')
405
- submit_btn = gr.Button('์ด๋ฏธ์ง€ ์ƒ์„ฑ (4์žฅ)')
406
- with gr.Column():
407
- with gr.Row():
408
- with gr.Column():
409
- output_image1 = gr.Image(label="์ด๋ฏธ์ง€ #1", type="filepath")
410
- output_image3 = gr.Image(label="์ด๋ฏธ์ง€ #3", type="filepath")
411
- with gr.Column():
412
- output_image2 = gr.Image(label="์ด๋ฏธ์ง€ #2", type="filepath")
413
- output_image4 = gr.Image(label="์ด๋ฏธ์ง€ #4", type="filepath")
414
- output_text = gr.Textbox(label="๊ฒฐ๊ณผ ์ •๋ณด", lines=2)
415
- prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", lines=2)
416
- submit_single_btn.click(
417
- fn=lambda image1, prompt: process_images_with_prompt(image1, prompt, 0),
418
- inputs=[image1_input, prompt_input],
419
- outputs=[output_image1, output_text, prompt_display],
420
  )
421
- submit_btn.click(
422
- fn=generate_multiple_images,
423
- inputs=[image1_input, prompt_input],
424
- outputs=[output_image1, output_image2, output_image3, output_image4, output_text, prompt_display],
425
- )
426
- return basic_app
427
 
428
- def create_product_prompt_app():
429
- with gr.Blocks(title="๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ๊ธฐ") as product_app:
430
- gr.Markdown("# ๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ๊ธฐ")
431
- gr.Markdown("์ƒํ’ˆ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด ๊ณ ํ’ˆ์งˆ ์ƒ์—…์šฉ ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.")
432
- with gr.Row():
433
- product_name = gr.Textbox(label="์ƒํ’ˆ๋ช… (ํ•œ๊ตญ์–ด ์ž…๋ ฅ)", placeholder="์˜ˆ: ์Šคํ‚จ์ผ€์–ด ํŠœ๋ธŒ, ํ…€๋ธ”๋Ÿฌ ๋“ฑ", interactive=True)
434
- background_type = gr.Radio(
435
- choices=["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"],
436
- label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
437
- value="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"
438
- )
439
  with gr.Row():
440
  with gr.Column(scale=1):
441
- image_input = gr.Image(label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="pil")
 
 
 
 
 
442
  simple_dropdown = gr.Dropdown(
443
  choices=list(SIMPLE_BACKGROUNDS.keys()),
444
  value=list(SIMPLE_BACKGROUNDS.keys())[0] if SIMPLE_BACKGROUNDS else None,
@@ -476,63 +385,38 @@ def create_product_prompt_app():
476
  )
477
  additional_info = gr.Textbox(
478
  label="์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ (์„ ํƒ์‚ฌํ•ญ)",
479
- placeholder="์˜ˆ: ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋А๋‚Œ, ๋ฐ์€ ์กฐ๋ช…, ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณด์กฐ์ ์ธ ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š” ๋“ฑ",
480
  lines=3,
481
  interactive=True
482
  )
483
- submit_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  with gr.Column(scale=1):
485
- prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ", lines=10)
486
- image_preview = gr.Image(label="์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ (#1)", type="pil")
487
- preview_html = gr.HTML("ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์‹œ ์—ฌ๊ธฐ์— ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.")
488
- def update_dropdowns(bg_type):
489
- return {
490
- simple_dropdown: gr.update(visible=(bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ")),
491
- studio_dropdown: gr.update(visible=(bg_type == "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ")),
492
- nature_dropdown: gr.update(visible=(bg_type == "์ž์—ฐ ํ™˜๊ฒฝ")),
493
- indoor_dropdown: gr.update(visible=(bg_type == "์‹ค๋‚ด ํ™˜๊ฒฝ")),
494
- abstract_dropdown: gr.update(visible=(bg_type == "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"))
495
- }
496
- background_type.change(
497
- fn=update_dropdowns,
498
- inputs=[background_type],
499
- outputs=[simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown]
500
  )
501
- def generate_output(image, bg_type, simple, studio, nature, indoor, abstract, product_name, additional_text):
502
- return generate_product_prompt_output(image, bg_type, simple, studio, nature, indoor, abstract, product_name, additional_text)
503
- submit_btn.click(
504
- fn=generate_output,
505
- inputs=[
506
- image_input,
507
- background_type,
508
- simple_dropdown,
509
- studio_dropdown,
510
- nature_dropdown,
511
- indoor_dropdown,
512
- abstract_dropdown,
513
- product_name,
514
- additional_info
515
- ],
516
- outputs=[
517
- prompt_output,
518
- image_preview,
519
- preview_html
520
- ]
521
- )
522
- return product_app
523
-
524
- def main():
525
- basic_app = create_basic_app()
526
- product_app = create_product_prompt_app()
527
- with gr.Blocks() as demo:
528
- gr.Markdown("# ํ†ตํ•ฉ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฐ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์•ฑ")
529
- with gr.Tabs():
530
- with gr.TabItem("์ผ๋ฐ˜ ์ด๋ฏธ์ง€ ์ƒ์„ฑ"):
531
- basic_app.render()
532
- with gr.TabItem("์ƒํ’ˆ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ"):
533
- product_app.render()
534
- demo.queue()
535
- demo.launch()
536
 
537
  if __name__ == "__main__":
538
- main()
 
 
 
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:
23
  f.write(data)
 
144
  valid_images = [img for img in images if img is not None]
145
  if not valid_images:
146
  return None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
147
+ # ์ด๋ฏธ Gemini API๋กœ ์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ๋Š” ์˜์–ด์ด๋ฏ€๋กœ ์ถ”๊ฐ€ ๋ฒˆ์—ญ์€ ์ƒ๋žต
148
+ final_prompt = prompt.strip()
 
 
 
 
 
 
 
149
  result_img, status = generate_with_images(final_prompt, valid_images, variation_index)
150
  if result_img is not None:
151
  return result_img, status, final_prompt
 
161
  time.sleep(1)
162
  return None, f"์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜({max_retries}ํšŒ) ์ดˆ๊ณผ ํ›„ ์‹คํŒจ: {last_error}", prompt
163
 
164
+ # ------------------- ์ƒํ’ˆ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๊ด€๋ จ ํ•จ์ˆ˜ -------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  # ๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๊ฒฝ๋กœ ์„ค์ •
166
  BACKGROUNDS_DIR = "./background"
167
  if not os.path.exists(BACKGROUNDS_DIR):
 
216
  6. ์ƒํ’ˆ์„ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์ดˆ์ ์œผ๋กœ ๋ถ€๊ฐ์‹œํ‚ค๊ณ , ์ƒํ’ˆ์˜ ๋น„์œจ์ด ์ „์ฒด ์ด๋ฏธ์ง€์—์„œ ํฌ๊ฒŒ ์ฐจ์ง€ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
217
  7. ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์ปท์•„์›ƒ(#1)์˜ ๊ธฐ๋ณธ ํ˜•ํƒœ์™€ ์ƒ‰์ƒ์€ ์œ ์ง€ํ•˜๋ฉด์„œ, ์„ ํƒํ•œ ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
218
  8. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—…์  ์ด๋ฏธ์ง€๋ฅผ ์œ„ํ•œ ๋‹ค์Œ ํ™˜๊ฒฝ ์š”์†Œ๋“ค์„ ํฌํ•จํ•˜์„ธ์š”:
219
+ - ์ƒํ’ˆ๊ณผ ์–ด์šธ๋ฆฌ๋Š” ์ฃผ๋ณ€ ํ™˜๊ฒฝ/๋ฐฐ๊ฒฝ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
220
  - ํ™˜๊ฒฝ์˜ ์กฐ๋ช… ํšจ๊ณผ(๋ฆผ ๋ผ์ดํŠธ, ๋ฐฑ๋ผ์ดํŠธ, ์†Œํ”„ํŠธ๋ฐ•์Šค ๋“ฑ)๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
221
  - ์ƒํ’ˆ์ด ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋„๋ก ์ ์ ˆํ•œ ๊ทธ๋ฆผ์ž์™€ ๋น› ํ‘œํ˜„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
222
  - ์ƒํ’ˆ์˜ ์šฉ๋„๋‚˜ ์žฅ์ ์„ ๊ฐ„์ ‘์ ์œผ๋กœ ์•”์‹œํ•˜๋Š” ๋ฐฐ๊ฒฝ ์š”์†Œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
 
227
  - "professional advertising imagery"
228
  - "studio quality"
229
  - "magazine advertisement quality"
230
+ 10. ๋ฐฐ๊ฒฝ ํ™˜๊ฒฝ ์š”์†Œ๋ฅผ ์ƒํ’ˆ ์นดํ…Œ๊ณ ๏ฟฝ๏ฟฝ๏ฟฝ์— ๋งž๊ฒŒ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
 
 
 
 
 
231
  11. ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฐ๊ฒฝ๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
232
  12. ํ”„๋กฌํ”„ํŠธ๋Š” ๋ฏธ๋“œ์ €๋‹ˆ AI์— ์ตœ์ ํ™”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
233
  13. ํ”„๋กฌํ”„ํŠธ ๋์— "--ar 1:1 --s 750 --q 2" ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฏธ๋“œ์ €๋‹ˆ์—์„œ ๊ณ ํ’ˆ์งˆ ์ •์‚ฌ๊ฐํ˜• ๋น„์œจ์„ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
 
234
  """
235
 
236
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
 
314
  "english": "white background"
315
  }
316
 
317
+ # ------------------- ํ†ตํ•ฉ ๊ธฐ๋Šฅ: ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€ ์ƒ์„ฑ -------------------
318
+ def generate_product_image(image, bg_type, simple, studio, nature, indoor, abstract, product_name, additional_info):
319
  if image is None:
320
+ return None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œ ํ›„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
 
321
  product_name = product_name.strip() or "์ œํ’ˆ"
322
  background_info = get_selected_background_info(bg_type, simple, studio, nature, indoor, abstract)
323
+ # Gemini API๋กœ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ
324
+ generated_prompt = generate_prompt_with_gemini(product_name, background_info, additional_info)
325
+ if "Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค" in generated_prompt:
326
+ warning_msg = (
327
+ "[Gemini API ํ‚ค ๋ˆ„๋ฝ]\n"
328
+ "API ํ‚ค ์„ค์ • ๋ฐฉ๋ฒ•:\n"
329
+ "1. ํ™˜๊ฒฝ ๋ณ€์ˆ˜: export GEMINI_API_KEY=\"your-api-key\"\n"
330
+ "2. ์ฝ”๋“œ ๋‚ด ์ง์ ‘ ์ž…๋ ฅ: GEMINI_API_KEY = \"your-api-key\"\n"
331
+ "ํ‚ค ๋ฐœ๊ธ‰: https://makersuite.google.com/"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  )
333
+ return None, warning_msg, warning_msg
334
+ # ์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์ฐฝ์— ๋ฐ˜์˜ํ•˜๊ณ , ๊ทธ ํ”„๋กฌํ”„ํŠธ๋กœ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
335
+ result_image, status, final_prompt = process_images_with_prompt(image, generated_prompt, 0)
336
+ return result_image, status, final_prompt
 
 
337
 
338
+ # ------------------- Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ -------------------
339
+ def create_app():
340
+ with gr.Blocks(title="๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ") as demo:
341
+ gr.Markdown("# ๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ")
342
+ gr.Markdown("์ƒํ’ˆ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ , ์ œํ’ˆ๋ช… ๋ฐ ๋ฐฐ๊ฒฝ ์˜ต์…˜๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ž…๋ ฅํ•˜๋ฉด Gemini API๋ฅผ ์ด์šฉํ•˜์—ฌ ์˜์–ด ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ํ”„๋กฌํ”„ํŠธ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.")
 
 
 
 
 
 
343
  with gr.Row():
344
  with gr.Column(scale=1):
345
+ product_name = gr.Textbox(label="์ƒํ’ˆ๋ช… (ํ•œ๊ตญ์–ด ์ž…๋ ฅ)", placeholder="์˜ˆ: ์Šคํ‚จ์ผ€์–ด ํŠœ๋ธŒ, ํ…€๋ธ”๋Ÿฌ ๋“ฑ", interactive=True)
346
+ background_type = gr.Radio(
347
+ choices=["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"],
348
+ label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
349
+ value="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"
350
+ )
351
  simple_dropdown = gr.Dropdown(
352
  choices=list(SIMPLE_BACKGROUNDS.keys()),
353
  value=list(SIMPLE_BACKGROUNDS.keys())[0] if SIMPLE_BACKGROUNDS else None,
 
385
  )
386
  additional_info = gr.Textbox(
387
  label="์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ (์„ ํƒ์‚ฌํ•ญ)",
388
+ placeholder="์˜ˆ: ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋А๋‚Œ, ๋ฐ์€ ์กฐ๋ช…, ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณด์กฐ ๊ฐ์ฒด ๋“ฑ",
389
  lines=3,
390
  interactive=True
391
  )
392
+ # ๋ฐฐ๊ฒฝ ์œ ํ˜• ๋ณ€๊ฒฝ ์‹œ ํ•ด๋‹น ๋“œ๋กญ๋‹ค์šด๋งŒ ๋ณด์ด๋„๋ก ์—…๋ฐ์ดํŠธ
393
+ def update_dropdowns(bg_type):
394
+ return {
395
+ simple_dropdown: gr.update(visible=(bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ")),
396
+ studio_dropdown: gr.update(visible=(bg_type == "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ")),
397
+ nature_dropdown: gr.update(visible=(bg_type == "์ž์—ฐ ํ™˜๊ฒฝ")),
398
+ indoor_dropdown: gr.update(visible=(bg_type == "์‹ค๋‚ด ํ™˜๊ฒฝ")),
399
+ abstract_dropdown: gr.update(visible=(bg_type == "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"))
400
+ }
401
+ background_type.change(
402
+ fn=update_dropdowns,
403
+ inputs=[background_type],
404
+ outputs=[simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown]
405
+ )
406
+ image_input = gr.Image(label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="pil")
407
+ generate_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
408
  with gr.Column(scale=1):
409
+ prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", lines=6)
410
+ image_output = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€", type="filepath")
411
+ status_output = gr.Textbox(label="๊ฒฐ๊ณผ ์ •๋ณด", lines=3)
412
+ generate_btn.click(
413
+ fn=generate_product_image,
414
+ inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown, product_name, additional_info],
415
+ outputs=[image_output, status_output, prompt_output]
 
 
 
 
 
 
 
 
416
  )
417
+ return demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
  if __name__ == "__main__":
420
+ app = create_app()
421
+ app.queue()
422
+ app.launch()