Kims12 commited on
Commit
f9d2a46
ยท
verified ยท
1 Parent(s): 7bb926b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +333 -209
app.py CHANGED
@@ -6,7 +6,9 @@ import logging
6
  import re
7
  import time
8
  import json
9
- import google.generativeai as genai
 
 
10
  from dotenv import load_dotenv
11
 
12
  load_dotenv()
@@ -18,20 +20,64 @@ logger = logging.getLogger(__name__)
18
  # Gemini API ํ‚ค ์„ค์ •
19
  GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
20
 
21
- # ๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๊ฒฝ๋กœ ์„ค์ •
 
 
 
22
  BACKGROUNDS_DIR = "./background"
23
 
24
- # ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์—†์œผ๋ฉด ์ƒ์„ฑ
 
 
 
 
25
  if not os.path.exists(BACKGROUNDS_DIR):
26
  os.makedirs(BACKGROUNDS_DIR)
27
- logger.info(f"๋ฐฐ๊ฒฝ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: {BACKGROUNDS_DIR}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- # ๊ธฐ๋ณธ ๋ฐฐ๊ฒฝ ์ƒ์„ฑ
30
- SIMPLE_BACKGROUNDS = {"ํ™”์ดํŠธ ๋ฐฐ๊ฒฝ": "white background", "๋ธ”๋ž™ ๋ฐฐ๊ฒฝ": "black background", "๊ทธ๋ ˆ์ด ๋ฐฐ๊ฒฝ": "gray background"}
31
- STUDIO_BACKGROUNDS = {"์ œํ’ˆ ์‚ฌ์ง„ ์ŠคํŠœ๋””์˜ค": "product photography studio", "๋ฏธ๋‹ˆ๋ฉ€ ์ŠคํŠœ๋””์˜ค": "minimal studio setup"}
32
- NATURE_BACKGROUNDS = {"์—ด๋Œ€ ํ•ด๋ณ€": "tropical beach", "์ˆฒ์†": "lush forest", "์‚ฐ์•… ํ’๊ฒฝ": "mountain landscape"}
33
- INDOOR_BACKGROUNDS = {"๋ชจ๋˜ ๋ฆฌ๋น™๋ฃธ": "modern living room", "๋Ÿญ์…”๋ฆฌ ์‡ผ๋ฃธ": "luxury showroom", "์นดํŽ˜": "cozy cafe"}
34
- ABSTRACT_BACKGROUNDS = {"๋„ค์˜จ ์กฐ๋ช…": "neon lights", "๊ทธ๋ผ๋ฐ์ด์…˜": "gradient background", "๊ธฐํ•˜ํ•™์  ํŒจํ„ด": "geometric pattern"}
 
 
 
 
 
35
 
36
  def save_binary_file(file_name, data):
37
  with open(file_name, "wb") as f:
@@ -39,22 +85,42 @@ def save_binary_file(file_name, data):
39
 
40
  def generate_system_instruction():
41
  return """๋‹น์‹ ์€ ์ƒํ’ˆ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ๊ณ ํ’ˆ์งˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
42
- ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ƒํ’ˆ๋ช…, ๋ฐฐ๊ฒฝ ์œ ํ˜•, ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ณ ํ’ˆ์งˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์˜์–ด๋กœ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
 
43
  ๋‹ค์Œ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋ฐ˜๋“œ์‹œ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค:
44
  1. ์ƒํ’ˆ์„ "#1"๋กœ ์ง€์ •ํ•˜์—ฌ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: "skincare tube (#1)")
45
  2. *** ๋งค์šฐ ์ค‘์š”: ์ƒํ’ˆ์˜ ์›๋ž˜ ํŠน์„ฑ(๋””์ž์ธ, ์ƒ‰์ƒ, ํ˜•ํƒœ, ๋กœ๊ณ , ํŒจํ‚ค์ง€ ๋“ฑ)์€ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ ์ ˆ๋Œ€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ***
46
- 3. *** ์ƒํ’ˆ์˜ ๋ณธ์งˆ์  ํŠน์„ฑ์€ ์œ ์ง€ํ•˜๋˜, ์ž์—ฐ์Šค๋Ÿฌ์šด ํ™˜๊ฒฝ ํ†ตํ•ฉ์„ ์œ„ํ•œ ์กฐ๋ช…๊ณผ ๊ทธ๋ฆผ์ž๋Š” ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค ***
47
- 4. ์ด๋ฏธ์ง€ ๋น„์œจ์€ ์ •ํ™•ํžˆ 1:1(์ •์‚ฌ๊ฐํ˜•) ํ˜•์‹์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
 
 
 
 
48
  5. ์ƒํ’ˆ์€ ๋ฐ˜๋“œ์‹œ ์ •์‚ฌ๊ฐํ˜• ๊ตฌ๋„์˜ ์ •์ค‘์•™์— ๋ฐฐ์น˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
49
  6. ์ƒํ’ˆ์„ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์ดˆ์ ์œผ๋กœ ๋ถ€๊ฐ์‹œํ‚ค๊ณ , ์ƒํ’ˆ์˜ ๋น„์œจ์ด ์ „์ฒด ์ด๋ฏธ์ง€์—์„œ ํฌ๊ฒŒ ์ฐจ์ง€ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
50
  7. ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์ปท์•„์›ƒ(#1)์˜ ๊ธฐ๋ณธ ํ˜•ํƒœ์™€ ์ƒ‰์ƒ์€ ์œ ์ง€ํ•˜๋ฉด์„œ, ์„ ํƒํ•œ ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
51
- 8. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—…์  ์ด๋ฏธ์ง€๋ฅผ ์œ„ํ•œ ํ™˜๊ฒฝ ์š”์†Œ๋“ค์„ ํฌํ•จํ•˜์„ธ์š”.
 
 
 
 
 
52
  9. ํ”„๋กฌํ”„ํŠธ์— ๋‹ค์Œ ์š”์†Œ๋“ค์„ ๋ช…์‹œ์ ์œผ๋กœ ํฌํ•จํ•˜์„ธ์š”:
53
  - "highly detailed commercial photography"
54
  - "award-winning product photography"
55
  - "professional advertising imagery"
56
- 10. ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฐ๊ฒฝ๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
57
- ์ถœ๋ ฅ ํ˜•์‹์€ ์˜์–ด๋กœ ๋œ ๋‹จ์ผ ๋‹จ๋ฝ์˜ ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
 
 
 
 
 
 
 
 
 
 
58
  """
59
 
60
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
@@ -75,58 +141,93 @@ def generate_prompt_with_gemini(product_name, background_info, additional_info="
75
  5. ํ™˜๊ฒฝ๊ณผ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ†ตํ•ฉ์„ ์œ„ํ•œ ์กฐ๋ช… ํšจ๊ณผ์™€ ๊ทธ๋ฆผ์ž๋Š” ํฌํ•จํ•ด์ฃผ์„ธ์š”.
76
  6. ์ƒํ’ˆ์„ ๋” ๋‹๋ณด์ด๊ฒŒ ํ•˜๋Š” ๋ฐฐ๊ฒฝ ํ™˜๊ฒฝ์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.
77
  7. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—… ๊ด‘๊ณ  ํ’ˆ์งˆ์˜ ์ด๋ฏธ์ง€๊ฐ€ ๋˜๋„๋ก ํ™˜๊ฒฝ ์„ค๋ช…์„ ํ•ด์ฃผ์„ธ์š”.
 
78
  ํ•œ๊ตญ์–ด ์ž…๋ ฅ ๋‚ด์šฉ์„ ์˜์–ด๋กœ ์ ์ ˆํžˆ ๋ฒˆ์—ญํ•˜์—ฌ ๋ฐ˜์˜ํ•ด์ฃผ์„ธ์š”.
79
  """
80
- genai.configure(api_key=GEMINI_API_KEY)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- model = genai.GenerativeModel('gemini-2.0-flash')
83
 
84
- response = model.generate_content(prompt_request)
85
- response_text = response.text.strip()
 
86
 
87
- # ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ ์ œ๊ฑฐํ•˜๊ณ  ๋ฐ˜ํ™˜ (์ด๋ฏธ์ง€ ์ƒ์„ฑ์—์„œ๋Š” ํ•„์š”์—†์Œ)
88
- cleaned_response = re.sub(r'--ar \d+:\d+|--s \d+|--q \d+', '', response_text).strip()
89
- return cleaned_response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  except Exception as e:
91
- return f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
 
 
92
 
93
- def get_selected_background_info(bg_type, simple, studio, nature, indoor, abstract):
94
- if bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ":
95
- return {
96
- "category": "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ",
97
- "name": simple,
98
- "english": SIMPLE_BACKGROUNDS.get(simple, "white background")
99
- }
100
- elif bg_type == "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ":
101
- return {
102
- "category": "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ",
103
- "name": studio,
104
- "english": STUDIO_BACKGROUNDS.get(studio, "product photography studio")
105
- }
106
- elif bg_type == "์ž์—ฐ ํ™˜๊ฒฝ":
107
- return {
108
- "category": "์ž์—ฐ ํ™˜๊ฒฝ",
109
- "name": nature,
110
- "english": NATURE_BACKGROUNDS.get(nature, "natural environment")
111
- }
112
- elif bg_type == "์‹ค๋‚ด ํ™˜๊ฒฝ":
113
- return {
114
- "category": "์‹ค๋‚ด ํ™˜๊ฒฝ",
115
- "name": indoor,
116
- "english": INDOOR_BACKGROUNDS.get(indoor, "indoor environment")
117
- }
118
- elif bg_type == "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ":
119
- return {
120
- "category": "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ",
121
- "name": abstract,
122
- "english": ABSTRACT_BACKGROUNDS.get(abstract, "abstract background")
123
- }
124
  else:
125
- return {
126
- "category": "๊ธฐ๋ณธ ๋ฐฐ๊ฒฝ",
127
- "name": "ํ™”์ดํŠธ ๋ฐฐ๊ฒฝ",
128
- "english": "white background"
129
- }
130
 
131
  def generate_with_images(prompt, images, variation_index=0):
132
  try:
@@ -134,7 +235,7 @@ def generate_with_images(prompt, images, variation_index=0):
134
  if not api_key:
135
  return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
136
 
137
- genai.configure(api_key=api_key)
138
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
139
 
140
  variation_suffixes = [
@@ -149,44 +250,37 @@ def generate_with_images(prompt, images, variation_index=0):
149
  else:
150
  prompt = prompt + " Do not add any text, watermarks, or labels to the image."
151
 
152
- model = genai.GenerativeModel('gemini-1.5-flash')
153
-
154
- parts = [prompt]
155
- for img in images:
156
  if img is not None:
157
- if isinstance(img, str): # If it's a file path
158
- with open(img, "rb") as f:
159
- img_data = f.read()
160
- parts.append({"mime_type": "image/jpeg", "data": img_data})
161
- else: # If it's a PIL Image
162
- img_bytes = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False)
163
- img.save(img_bytes, format="JPEG")
164
- img_bytes.close()
165
-
166
- with open(img_bytes.name, "rb") as f:
167
- img_data = f.read()
168
-
169
- parts.append({"mime_type": "image/jpeg", "data": img_data})
170
- os.unlink(img_bytes.name) # Clean up temp file
171
 
172
- response = model.generate_content(parts)
 
 
 
 
 
 
 
 
 
 
173
 
174
  # ์ž„์‹œ ํŒŒ์ผ์€ ํ•ญ์ƒ JPG ํ™•์žฅ์ž๋กœ ์ƒ์„ฑ
175
  with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
176
  temp_path = tmp.name
177
  result_text = ""
178
  image_found = False
179
-
180
- for part in response.parts:
181
  if hasattr(part, 'text') and part.text:
182
  result_text += part.text
183
  logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
184
  elif hasattr(part, 'inline_data') and part.inline_data:
185
- img_data = part.inline_data.data
186
- save_binary_file(temp_path, img_data)
187
  image_found = True
188
  logger.info("์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
189
-
190
  if not image_found:
191
  return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
192
 
@@ -215,6 +309,7 @@ def process_images_with_prompt(image1, prompt, variation_index=0, max_retries=3)
215
  return None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
216
 
217
  if prompt and prompt.strip():
 
218
  final_prompt = prompt
219
  else:
220
  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."
@@ -271,105 +366,144 @@ def generate_multiple_images(image1, prompt, progress=gr.Progress()):
271
 
272
  return results[0], results[1], results[2], results[3], combined_status, combined_prompts
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  # UI ๊ตฌ์„ฑ
275
- with gr.Blocks(title="์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ & ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ๊ธฐ") as demo:
276
- gr.Markdown("# ์ด์ปค๋จธ์Šค ์ด๋ฏธ์ง€ ๋ณ€ํ™˜ ์ƒ์„ฑ๊ธฐ")
277
-
278
- with gr.Row():
279
- with gr.Column(scale=1):
280
- # ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์„น์…˜
281
- image_input = gr.Image(type="pil", label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", image_mode="RGB")
282
-
283
- # ์ƒํ’ˆ๋ช… ์„น์…˜
284
- product_name = gr.Textbox(label="์ƒํ’ˆ๋ช…", placeholder="์˜ˆ: ์Šคํ‚จ์ผ€์–ด ํŠœ๋ธŒ, ํ…€๋ธ”๋Ÿฌ ๋“ฑ", interactive=True)
285
-
286
- # ๋ฐฐ๊ฒฝ ์œ ํ˜•์„ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•œ ๋ผ๋””์˜ค ๋ฒ„ํŠผ
287
- bg_type = gr.Radio(
288
- choices=["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"],
289
- label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
290
- value="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"
291
- )
292
-
293
- # ๊ฐ ๋ฐฐ๊ฒฝ ์œ ํ˜•์— ๋งž๋Š” ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ๋“ค
294
- with gr.Group():
295
- simple_dropdown = gr.Dropdown(
296
- choices=list(SIMPLE_BACKGROUNDS.keys()),
297
- value=list(SIMPLE_BACKGROUNDS.keys())[0] if SIMPLE_BACKGROUNDS else None,
298
- label="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ ์„ ํƒ",
299
- visible=True,
300
- interactive=True
301
- )
302
-
303
- studio_dropdown = gr.Dropdown(
304
- choices=list(STUDIO_BACKGROUNDS.keys()),
305
- value=list(STUDIO_BACKGROUNDS.keys())[0] if STUDIO_BACKGROUNDS else None,
306
- label="์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ ์„ ํƒ",
307
- visible=False,
308
- interactive=True
309
- )
310
-
311
- nature_dropdown = gr.Dropdown(
312
- choices=list(NATURE_BACKGROUNDS.keys()),
313
- value=list(NATURE_BACKGROUNDS.keys())[0] if NATURE_BACKGROUNDS else None,
314
- label="์ž์—ฐ ํ™˜๊ฒฝ ์„ ํƒ",
315
- visible=False,
316
- interactive=True
317
- )
318
 
319
- indoor_dropdown = gr.Dropdown(
320
- choices=list(INDOOR_BACKGROUNDS.keys()),
321
- value=list(INDOOR_BACKGROUNDS.keys())[0] if INDOOR_BACKGROUNDS else None,
322
- label="์‹ค๋‚ด ํ™˜๊ฒฝ ์„ ํƒ",
323
- visible=False,
324
- interactive=True
325
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
- abstract_dropdown = gr.Dropdown(
328
- choices=list(ABSTRACT_BACKGROUNDS.keys()),
329
- value=list(ABSTRACT_BACKGROUNDS.keys())[0] if ABSTRACT_BACKGROUNDS else None,
330
- label="์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ ์„ ํƒ",
331
- visible=False,
332
- interactive=True
333
- )
334
-
335
- additional_info = gr.Textbox(
336
- label="์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ (์„ ํƒ์‚ฌํ•ญ)",
337
- placeholder="์˜ˆ: ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋А๋‚Œ, ๋ฐ์€ ์กฐ๋ช…, ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณด์กฐ์ ์ธ ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š” ๋“ฑ",
338
- lines=3,
339
- interactive=True
340
- )
341
-
342
- # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ
343
- generate_prompt_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ")
344
-
345
- # ์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
346
- prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ", lines=5)
347
 
348
- # ์ปค์Šคํ…€ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์„ ํƒ์ )
349
- custom_prompt = gr.Textbox(
350
- label="์ปค์Šคํ…€ ํ”„๋กฌํ”„ํŠธ (์„ ํƒ์‚ฌํ•ญ)",
351
- placeholder="์ง์ ‘ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ์œ„์—์„œ ์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค",
352
- lines=3,
353
- interactive=True
354
- )
355
-
356
- with gr.Row():
357
- submit_single_btn = gr.Button('์ด๋ฏธ์ง€ 1์žฅ ์ƒ์„ฑ')
358
- submit_btn = gr.Button('์ด๋ฏธ์ง€ 4์žฅ ์ƒ์„ฑ')
359
-
360
- with gr.Column(scale=1):
361
- # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ์„น์…˜
362
- with gr.Row():
363
- with gr.Column():
364
- output_image1 = gr.Image(label="์ด๋ฏธ์ง€ #1", type="filepath")
365
- output_image3 = gr.Image(label="์ด๋ฏธ์ง€ #3", type="filepath")
366
- with gr.Column():
367
- output_image2 = gr.Image(label="์ด๋ฏธ์ง€ #2", type="filepath")
368
- output_image4 = gr.Image(label="์ด๋ฏธ์ง€ #4", type="filepath")
369
-
370
- # ๊ฒฐ๊ณผ ์ •๋ณด
371
- output_text = gr.Textbox(label="๊ฒฐ๊ณผ ์ •๋ณด", lines=2)
372
- prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", lines=2)
373
 
374
  # ๋ฐฐ๊ฒฝ ์œ ํ˜•์— ๋”ฐ๋ผ ๋“œ๋กญ๋‹ค์šด ํ‘œ์‹œ ์—…๋ฐ์ดํŠธ
375
  def update_dropdowns(bg_type):
@@ -381,8 +515,15 @@ with gr.Blocks(title="์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ & ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ๊ธฐ") as demo:
381
  abstract_dropdown: gr.update(visible=(bg_type == "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"))
382
  }
383
 
 
 
 
 
 
 
 
384
  # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ํ•จ์ˆ˜
385
- def generate_product_prompt(image, bg_type, simple, studio, nature, indoor, abstract, product_text, additional_text):
386
  if image is None:
387
  return "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
388
 
@@ -395,28 +536,19 @@ with gr.Blocks(title="์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ & ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ๊ธฐ") as demo:
395
  prompt = generate_prompt_with_gemini(product_text, background_info, additional_text)
396
 
397
  if not GEMINI_API_KEY:
398
- return "Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ GEMINI_API_KEY๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ์ฝ”๋“œ์— ์ง์ ‘ ์ž…๋ ฅํ•˜์„ธ์š”."
399
 
400
  return prompt
401
  except Exception as e:
402
- return f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
403
-
404
- # ํ”„๋กฌํ”„ํŠธ ์ถœ๋ ฅ์„ ์ปค์Šคํ…€ ํ”„๋กฌํ”„ํŠธ์— ๋ณต์‚ฌ
405
- def copy_to_custom(prompt):
406
- return prompt
407
-
408
- # ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
409
- bg_type.change(
410
- fn=update_dropdowns,
411
- inputs=[bg_type],
412
- outputs=[simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown]
413
- )
414
 
 
415
  generate_prompt_btn.click(
416
- fn=generate_product_prompt,
417
  inputs=[
418
- image_input,
419
- bg_type,
420
  simple_dropdown,
421
  studio_dropdown,
422
  nature_dropdown,
@@ -428,27 +560,19 @@ with gr.Blocks(title="์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ & ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ๊ธฐ") as demo:
428
  outputs=prompt_output
429
  )
430
 
431
- # ์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ปค์Šคํ…€ ํ”„๋กฌํ”„ํŠธ ํ•„๋“œ์— ๋ณต์‚ฌ
432
- prompt_output.change(
433
- fn=copy_to_custom,
434
- inputs=[prompt_output],
435
- outputs=[custom_prompt]
436
- )
437
-
438
  # ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
439
  submit_single_btn.click(
440
  fn=lambda image1, prompt: process_images_with_prompt(image1, prompt, 0),
441
- inputs=[image_input, custom_prompt],
442
  outputs=[output_image1, output_text, prompt_display],
443
  )
444
 
445
  # 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
446
  submit_btn.click(
447
  fn=generate_multiple_images,
448
- inputs=[image_input, custom_prompt],
449
  outputs=[output_image1, output_image2, output_image3, output_image4, output_text, prompt_display],
450
  )
451
 
452
- if __name__ == "__main__":
453
- demo.queue()
454
- demo.launch()
 
6
  import re
7
  import time
8
  import json
9
+
10
+ from google import genai
11
+ from google.genai import types
12
  from dotenv import load_dotenv
13
 
14
  load_dotenv()
 
20
  # Gemini API ํ‚ค ์„ค์ •
21
  GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
22
 
23
+ # Gemini API ์ดˆ๊ธฐํ™”
24
+ genai.configure(api_key=GEMINI_API_KEY)
25
+
26
+ # ๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๊ฒฝ๋กœ ์„ค์ • - ์ƒ๋Œ€ ๊ฒฝ๋กœ ์‚ฌ์šฉ
27
  BACKGROUNDS_DIR = "./background"
28
 
29
+ # ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ์ •๋ณด ์ถœ๋ ฅ
30
+ print(f"ํ˜„์žฌ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ: {os.getcwd()}")
31
+ print(f"์‚ฌ์šฉ ์ค‘์ธ ๋ฐฐ๊ฒฝ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ: {BACKGROUNDS_DIR}")
32
+
33
+ # JSON ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
34
  if not os.path.exists(BACKGROUNDS_DIR):
35
  os.makedirs(BACKGROUNDS_DIR)
36
+ print(f"๋ฐฐ๊ฒฝ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค: {BACKGROUNDS_DIR}")
37
+ else:
38
+ print(f"๋ฐฐ๊ฒฝ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค: {BACKGROUNDS_DIR}")
39
+ try:
40
+ for file in os.listdir(BACKGROUNDS_DIR):
41
+ print(f"๋ฐœ๊ฒฌ๋œ ํŒŒ์ผ: {file}")
42
+ except Exception as e:
43
+ print(f"๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์šฉ์„ ๋‚˜์—ดํ•˜๋Š” ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
44
+
45
+ # JSON ํŒŒ์ผ ๋กœ๋“œ ํ•จ์ˆ˜
46
+ def load_background_json(filename):
47
+ file_path = os.path.join(BACKGROUNDS_DIR, filename)
48
+ try:
49
+ with open(file_path, 'r', encoding='utf-8') as f:
50
+ data = json.load(f)
51
+ print(f"{filename} ํŒŒ์ผ์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œํ–ˆ์Šต๋‹ˆ๋‹ค. {len(data)} ํ•ญ๋ชฉ ํฌํ•จ.")
52
+ return data
53
+ except FileNotFoundError:
54
+ print(f"๊ฒฝ๊ณ : {filename} ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
55
+ return {}
56
+ except json.JSONDecodeError:
57
+ print(f"๊ฒฝ๊ณ : {filename} ํŒŒ์ผ์˜ JSON ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
58
+ return {}
59
+ except Exception as e:
60
+ print(f"๊ฒฝ๊ณ : {filename} ํŒŒ์ผ ๋กœ๋“œ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}. ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
61
+ return {}
62
+
63
+ # ๋ฐฐ๊ฒฝ ๋ฐ์ดํ„ฐ ๋กœ๋“œ
64
+ SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
65
+ STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
66
+ NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
67
+ INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
68
+ ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
69
 
70
+ # ๋ฐฐ๊ฒฝ์ด ๋กœ๋“œ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •
71
+ if not SIMPLE_BACKGROUNDS:
72
+ SIMPLE_BACKGROUNDS = {"ํ™”์ดํŠธ ๋ฐฐ๊ฒฝ": "white background"}
73
+ if not STUDIO_BACKGROUNDS:
74
+ STUDIO_BACKGROUNDS = {"์ œํ’ˆ ์‚ฌ์ง„ ์ŠคํŠœ๋””์˜ค": "product photography studio"}
75
+ if not NATURE_BACKGROUNDS:
76
+ NATURE_BACKGROUNDS = {"์—ด๋Œ€ ํ•ด๋ณ€": "tropical beach"}
77
+ if not INDOOR_BACKGROUNDS:
78
+ INDOOR_BACKGROUNDS = {"๋ชจ๋˜ ๋ฆฌ๋น™๋ฃธ": "modern living room"}
79
+ if not ABSTRACT_BACKGROUNDS:
80
+ ABSTRACT_BACKGROUNDS = {"๋„ค์˜จ ์กฐ๋ช…": "neon lights"}
81
 
82
  def save_binary_file(file_name, data):
83
  with open(file_name, "wb") as f:
 
85
 
86
  def generate_system_instruction():
87
  return """๋‹น์‹ ์€ ์ƒํ’ˆ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ๊ณ ํ’ˆ์งˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
88
+ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ƒํ’ˆ๋ช…, ๋ฐฐ๊ฒฝ ์œ ํ˜•, ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฏธ๋“œ์ €๋‹ˆ(Midjourney)์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”
89
+ ์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์˜์–ด๋กœ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
90
  ๋‹ค์Œ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋ฐ˜๋“œ์‹œ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค:
91
  1. ์ƒํ’ˆ์„ "#1"๋กœ ์ง€์ •ํ•˜์—ฌ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: "skincare tube (#1)")
92
  2. *** ๋งค์šฐ ์ค‘์š”: ์ƒํ’ˆ์˜ ์›๋ž˜ ํŠน์„ฑ(๋””์ž์ธ, ์ƒ‰์ƒ, ํ˜•ํƒœ, ๋กœ๊ณ , ํŒจํ‚ค์ง€ ๋“ฑ)์€ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ ์ ˆ๋Œ€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ***
93
+ 3. *** ์ƒํ’ˆ์˜ ๋ณธ์งˆ์  ํŠน์„ฑ์€ ์œ ์ง€ํ•˜๋˜, ์ž์—ฐ์Šค๋Ÿฌ์šด ํ™˜๊ฒฝ ํ†ตํ•ฉ์„ ์œ„ํ•œ ์กฐ๋ช…๊ณผ ๊ทธ๋ฆผ์ž๋Š” ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค: ***
94
+ - ์ƒํ’ˆ ์ž์ฒด์˜ ์ƒ‰์ƒ, ๋””์ž์ธ, ํ˜•ํƒœ, ํ…์Šค์ฒ˜๋Š” ์ ˆ๋Œ€ ์ˆ˜์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
95
+ - ํ™˜๊ฒฝ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์–ด์šธ๋ฆฌ๋Š” ๊ทธ๋ฆผ์ž, ์ฃผ๋ณ€ ์กฐ๋ช… ํšจ๊ณผ๋Š” ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.
96
+ - ์ƒํ’ˆ์— ๋ฌผ๋ฐฉ์šธ, ์‘์ถ•, ๊ธˆ, ์€๊ณผ ๊ฐ™์€ ์ถ”๊ฐ€ ์š”์†Œ๋‚˜ ๋ฌผ๋ฆฌ์  ํšจ๊ณผ๋Š” ์ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
97
+ - ํ™˜๊ฒฝ์— ์–ด์šธ๋ฆฌ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋น› ๋ฐ˜์‚ฌ, ์ฃผ๋ณ€ ์กฐ๋ช…, ๊ทธ๋ฆผ์ž๋Š” ์‚ฌ์‹ค์  ํ†ตํ•ฉ๊ฐ์„ ์œ„ํ•ด ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
98
+ 4. ์ด๋ฏธ์ง€ ๋น„์œจ์€ ์ •ํ™•ํžˆ 1:1(์ •์‚ฌ๊ฐํ˜•) ํ˜•์‹์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ์— "square format", "1:1 ratio" ๋˜๋Š” "aspect ratio 1:1"์„ ๋ช…์‹œ์ ์œผ๋กœ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
99
  5. ์ƒํ’ˆ์€ ๋ฐ˜๋“œ์‹œ ์ •์‚ฌ๊ฐํ˜• ๊ตฌ๋„์˜ ์ •์ค‘์•™์— ๋ฐฐ์น˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
100
  6. ์ƒํ’ˆ์„ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์ดˆ์ ์œผ๋กœ ๋ถ€๊ฐ์‹œํ‚ค๊ณ , ์ƒํ’ˆ์˜ ๋น„์œจ์ด ์ „์ฒด ์ด๋ฏธ์ง€์—์„œ ํฌ๊ฒŒ ์ฐจ์ง€ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
101
  7. ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์ปท์•„์›ƒ(#1)์˜ ๊ธฐ๋ณธ ํ˜•ํƒœ์™€ ์ƒ‰์ƒ์€ ์œ ์ง€ํ•˜๋ฉด์„œ, ์„ ํƒํ•œ ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ตํ•ฉ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
102
+ 8. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—…์  ์ด๋ฏธ์ง€๋ฅผ ์œ„ํ•œ ๋‹ค์Œ ํ™˜๊ฒฝ ์š”์†Œ๋“ค์„ ํฌํ•จํ•˜์„ธ์š”:
103
+ - ์ƒํ’ˆ๊ณผ ์–ด์šธ๋ฆฌ๋Š” ์ฃผ๋ณ€ ํ™˜๊ฒฝ/๋ฐฐ๊ฒฝ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ™”์žฅํ’ˆ ์ฃผ๋ณ€์— ๊ฝƒ์ด๋‚˜ ํ—ˆ๋ธŒ, ์Œ๋ฃŒ ์ œํ’ˆ ์˜†์— ๊ณผ์ผ, ์ „์ž์ œํ’ˆ ๊ทผ์ฒ˜์— ํ˜„๋Œ€์  ์†Œํ’ˆ ๋“ฑ.
104
+ - ํ™˜๊ฒฝ์˜ ์กฐ๋ช… ํšจ๊ณผ(๋ฆผ ๋ผ์ดํŠธ, ๋ฐฑ๋ผ์ดํŠธ, ์†Œํ”„ํŠธ๋ฐ•์Šค ๋“ฑ)๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
105
+ - ์ƒํ’ˆ์ด ํ™˜๊ฒฝ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋„๋ก ์ ์ ˆํ•œ ๊ทธ๋ฆผ์ž์™€ ๋น› ํ‘œํ˜„์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
106
+ - ์ƒํ’ˆ์˜ ์šฉ๋„๋‚˜ ์žฅ์ ์„ ๊ฐ„์ ‘์ ์œผ๋กœ ์•”์‹œํ•˜๋Š” ๋ฐฐ๊ฒฝ ์š”์†Œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
107
+ - ํ”„๋กœํŽ˜์…”๋„ํ•œ ์ƒ์—… ์‚ฌ์ง„ ํšจ๊ณผ(์„ ํƒ์  ํ”ผ์‚ฌ๊ณ„ ์‹ฌ๋„, ์†Œํ”„ํŠธ ํฌ์ปค์Šค, ์ŠคํŠœ๋””์˜ค ์กฐ๋ช… ๋“ฑ)๋ฅผ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.
108
  9. ํ”„๋กฌํ”„ํŠธ์— ๋‹ค์Œ ์š”์†Œ๋“ค์„ ๋ช…์‹œ์ ์œผ๋กœ ํฌํ•จํ•˜์„ธ์š”:
109
  - "highly detailed commercial photography"
110
  - "award-winning product photography"
111
  - "professional advertising imagery"
112
+ - "studio quality"
113
+ - "magazine advertisement quality"
114
+ 10. ๋ฐฐ๊ฒฝ ํ™˜๊ฒฝ ์š”์†Œ๋ฅผ ์ƒํ’ˆ ์นดํ…Œ๊ณ ๋ฆฌ์— ๋งž๊ฒŒ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค:
115
+ - ์Šคํ‚จ์ผ€์–ด ์ œํ’ˆ: ๊นจ๋—ํ•œ ์š•์‹ค ์„ ๋ฐ˜, ์šฐ์•„ํ•œ ํ™”์žฅ๋Œ€, ์ŠคํŒŒ ๊ฐ™์€ ํ™˜๊ฒฝ ๋“ฑ
116
+ - ์Œ๋ฃŒ ์ œํ’ˆ: ์„ธ๋ จ๋œ ํ…Œ์ด๋ธ”, ํŒŒํ‹ฐ ํ™˜๊ฒฝ, ์•ผ์™ธ ํ”ผํฌ๋‹‰ ์žฅ๋ฉด ๋“ฑ
117
+ - ์ „์ž ์ œํ’ˆ: ์„ธ๋ จ๋œ ์ž‘์—… ๊ณต๊ฐ„, ํ˜„๋Œ€์ ์ธ ๊ฑฐ์‹ค, ๋ฏธ๋‹ˆ๋ฉ€ํ•œ ์ฑ…์ƒ ๋“ฑ
118
+ - ํŒจ์…˜/์˜๋ฅ˜: ์„ธ๋ จ๋œ ์‡ผ๋ฃธ, ๋„์‹œ ๊ฑฐ๋ฆฌ, ์—˜๋ ˆ๊ฐ•์Šคํ•œ ๋ผ์ดํ”„์Šคํƒ€์ผ ํ™˜๊ฒฝ ๋“ฑ
119
+ - ์‹ํ’ˆ ์ œํ’ˆ: ๊น”๋”ํ•œ ์ฃผ๋ฐฉ, ์‹ํƒ, ์š”๋ฆฌ ํ™˜๊ฒฝ ๋“ฑ
120
+ 11. ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฐ๊ฒฝ๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.
121
+ 12. ํ”„๋กฌํ”„ํŠธ๋Š” ๋ฏธ๋“œ์ €๋‹ˆ AI์— ์ตœ์ ํ™”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
122
+ 13. ํ”„๋กฌํ”„ํŠธ ๋์— "--ar 1:1 --s 750 --q 2" ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฏธ๋“œ์ €๋‹ˆ์—์„œ ๊ณ ํ’ˆ์งˆ ์ •์‚ฌ๊ฐํ˜• ๋น„์œจ์„ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
123
+ ์ถœ๋ ฅ ํ˜•์‹์€ ์˜์–ด๋กœ ๋œ ๋‹จ์ผ ๋‹จ๋ฝ์˜ ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ์—ฌ์•ผ ํ•˜๋ฉฐ, ๋์— ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
124
  """
125
 
126
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
 
141
  5. ํ™˜๊ฒฝ๊ณผ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ†ตํ•ฉ์„ ์œ„ํ•œ ์กฐ๋ช… ํšจ๊ณผ์™€ ๊ทธ๋ฆผ์ž๋Š” ํฌํ•จํ•ด์ฃผ์„ธ์š”.
142
  6. ์ƒํ’ˆ์„ ๋” ๋‹๋ณด์ด๊ฒŒ ํ•˜๋Š” ๋ฐฐ๊ฒฝ ํ™˜๊ฒฝ์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.
143
  7. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—… ๊ด‘๊ณ  ํ’ˆ์งˆ์˜ ์ด๋ฏธ์ง€๊ฐ€ ๋˜๋„๋ก ํ™˜๊ฒฝ ์„ค๋ช…์„ ํ•ด์ฃผ์„ธ์š”.
144
+ 8. ํ”„๋กฌํ”„ํŠธ ๋์— ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ "--ar 1:1 --s 750 --q 2"๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
145
  ํ•œ๊ตญ์–ด ์ž…๋ ฅ ๋‚ด์šฉ์„ ์˜์–ด๋กœ ์ ์ ˆํžˆ ๋ฒˆ์—ญํ•˜์—ฌ ๋ฐ˜์˜ํ•ด์ฃผ์„ธ์š”.
146
  """
147
+ model = genai.GenerativeModel(
148
+ 'gemini-2.0-flash',
149
+ system_instruction=generate_system_instruction()
150
+ )
151
+ response = model.generate_content(
152
+ prompt_request,
153
+ generation_config=genai.types.GenerationConfig(
154
+ temperature=0.7,
155
+ top_p=0.95,
156
+ top_k=64,
157
+ max_output_tokens=1024,
158
+ )
159
+ )
160
+ response_text = response.text.strip()
161
+ if "--ar 1:1" not in response_text:
162
+ response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2"
163
+ return response_text
164
+ except Exception as e:
165
+ return f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
166
+
167
+ def translate_prompt_to_english(prompt):
168
+ if not re.search("[๊ฐ€-ํžฃ]", prompt):
169
+ return prompt
170
+
171
+ prompt = prompt.replace("#1", "IMAGE_TAG_ONE")
172
+
173
+ try:
174
+ api_key = os.environ.get("GEMINI_API_KEY")
175
+ if not api_key:
176
+ logger.error("Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
177
+ prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
178
+ return prompt
179
+
180
+ client = genai.Client(api_key=api_key)
181
+ translation_prompt = f"""
182
+ Translate the following Korean text to English:
183
 
184
+ {prompt}
185
 
186
+ IMPORTANT: The token IMAGE_TAG_ONE is a special tag
187
+ and must be preserved exactly as is in your translation. Do not translate this token.
188
+ """
189
 
190
+ logger.info(f"Translation prompt: {translation_prompt}")
191
+ response = client.models.generate_content(
192
+ model="gemini-2.0-flash",
193
+ contents=[translation_prompt],
194
+ config=types.GenerateContentConfig(
195
+ response_modalities=['Text'],
196
+ temperature=0.2,
197
+ top_p=0.95,
198
+ top_k=40,
199
+ max_output_tokens=512
200
+ )
201
+ )
202
+
203
+ translated_text = ""
204
+ for part in response.candidates[0].content.parts:
205
+ if hasattr(part, 'text') and part.text:
206
+ translated_text += part.text
207
+
208
+ if translated_text.strip():
209
+ translated_text = translated_text.replace("IMAGE_TAG_ONE", "#1")
210
+ logger.info(f"Translated text: {translated_text.strip()}")
211
+ return translated_text.strip()
212
+ else:
213
+ logger.warning("๋ฒˆ์—ญ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์›๋ณธ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ")
214
+ prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
215
+ return prompt
216
  except Exception as e:
217
+ logger.exception("๋ฒˆ์—ญ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
218
+ prompt = prompt.replace("IMAGE_TAG_ONE", "#1")
219
+ return prompt
220
 
221
+ def preprocess_prompt(prompt, image1):
222
+ has_img1 = image1 is not None
223
+
224
+ if "#1" in prompt and not has_img1:
225
+ prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  else:
227
+ prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
228
+
229
+ prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ์ด๋ฏธ์ง€์— ํ…์ŠคํŠธ๋‚˜ ๊ธ€์ž๋ฅผ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”."
230
+ return prompt
 
231
 
232
  def generate_with_images(prompt, images, variation_index=0):
233
  try:
 
235
  if not api_key:
236
  return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
237
 
238
+ client = genai.Client(api_key=api_key)
239
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
240
 
241
  variation_suffixes = [
 
250
  else:
251
  prompt = prompt + " Do not add any text, watermarks, or labels to the image."
252
 
253
+ contents = [prompt]
254
+ for idx, img in enumerate(images, 1):
 
 
255
  if img is not None:
256
+ contents.append(img)
257
+ logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
 
 
 
 
 
 
 
 
 
 
 
 
258
 
259
+ response = client.models.generate_content(
260
+ model="gemini-2.0-flash-exp-image-generation",
261
+ contents=contents,
262
+ config=types.GenerateContentConfig(
263
+ response_modalities=['Text', 'Image'],
264
+ temperature=1,
265
+ top_p=0.95,
266
+ top_k=40,
267
+ max_output_tokens=8192
268
+ )
269
+ )
270
 
271
  # ์ž„์‹œ ํŒŒ์ผ์€ ํ•ญ์ƒ JPG ํ™•์žฅ์ž๋กœ ์ƒ์„ฑ
272
  with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
273
  temp_path = tmp.name
274
  result_text = ""
275
  image_found = False
276
+ for part in response.candidates[0].content.parts:
 
277
  if hasattr(part, 'text') and part.text:
278
  result_text += part.text
279
  logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
280
  elif hasattr(part, 'inline_data') and part.inline_data:
281
+ save_binary_file(temp_path, part.inline_data.data)
 
282
  image_found = True
283
  logger.info("์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
 
284
  if not image_found:
285
  return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
286
 
 
309
  return None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.", ""
310
 
311
  if prompt and prompt.strip():
312
+ # ์ด๋ฏธ ์˜์–ด๋กœ ๋œ ํ”„๋กฌํ”„ํŠธ๋ผ๋ฉด ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
313
  final_prompt = prompt
314
  else:
315
  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."
 
366
 
367
  return results[0], results[1], results[2], results[3], combined_status, combined_prompts
368
 
369
+ # ์„ ํƒ๋œ ๋ฐฐ๊ฒฝ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ
370
+ def get_selected_background_info(bg_type, simple, studio, nature, indoor, abstract):
371
+ if bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ":
372
+ return {
373
+ "category": "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ",
374
+ "name": simple,
375
+ "english": SIMPLE_BACKGROUNDS.get(simple, "white background")
376
+ }
377
+ elif bg_type == "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ":
378
+ return {
379
+ "category": "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ",
380
+ "name": studio,
381
+ "english": STUDIO_BACKGROUNDS.get(studio, "product photography studio")
382
+ }
383
+ elif bg_type == "์ž์—ฐ ํ™˜๊ฒฝ":
384
+ return {
385
+ "category": "์ž์—ฐ ํ™˜๊ฒฝ",
386
+ "name": nature,
387
+ "english": NATURE_BACKGROUNDS.get(nature, "natural environment")
388
+ }
389
+ elif bg_type == "์‹ค๋‚ด ํ™˜๊ฒฝ":
390
+ return {
391
+ "category": "์‹ค๋‚ด ํ™˜๊ฒฝ",
392
+ "name": indoor,
393
+ "english": INDOOR_BACKGROUNDS.get(indoor, "indoor environment")
394
+ }
395
+ elif bg_type == "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ":
396
+ return {
397
+ "category": "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ",
398
+ "name": abstract,
399
+ "english": ABSTRACT_BACKGROUNDS.get(abstract, "abstract background")
400
+ }
401
+ else:
402
+ return {
403
+ "category": "๊ธฐ๋ณธ ๋ฐฐ๊ฒฝ",
404
+ "name": "ํ™”์ดํŠธ ๋ฐฐ๊ฒฝ",
405
+ "english": "white background"
406
+ }
407
+
408
  # UI ๊ตฌ์„ฑ
409
+ with gr.Blocks() as demo:
410
+ with gr.Column():
411
+ with gr.Group():
412
+ with gr.Column():
413
+ with gr.Row():
414
+ image1_input = gr.Image(type="pil", label="์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", image_mode="RGB")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
 
416
+ # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ ์˜์—ญ
417
+ with gr.Row():
418
+ with gr.Column():
419
+ # ์ƒํ’ˆ๋ช… ์ž…๋ ฅ
420
+ product_name = gr.Textbox(label="์ƒํ’ˆ๋ช…", placeholder="์˜ˆ: ์Šคํ‚จ์ผ€์–ด ํŠœ๋ธŒ, ํ…€๋ธ”๋Ÿฌ ๋“ฑ", interactive=True)
421
+
422
+ # ๋ฐฐ๊ฒฝ ์œ ํ˜• ์„ ํƒ ๋ผ๋””์˜ค ๋ฒ„ํŠผ
423
+ background_type = gr.Radio(
424
+ choices=["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"],
425
+ label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
426
+ value="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"
427
+ )
428
+
429
+ # ๊ฐ ๋ฐฐ๊ฒฝ ์œ ํ˜•๋ณ„ ๋“œ๋กญ๋‹ค์šด
430
+ with gr.Row():
431
+ # ์‹ฌํ”Œ ๋ฐฐ๊ฒฝ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด
432
+ simple_dropdown = gr.Dropdown(
433
+ choices=list(SIMPLE_BACKGROUNDS.keys()),
434
+ value=list(SIMPLE_BACKGROUNDS.keys())[0] if SIMPLE_BACKGROUNDS else None,
435
+ label="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ ์„ ํƒ",
436
+ visible=True,
437
+ interactive=True
438
+ )
439
+
440
+ # ์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด
441
+ studio_dropdown = gr.Dropdown(
442
+ choices=list(STUDIO_BACKGROUNDS.keys()),
443
+ value=list(STUDIO_BACKGROUNDS.keys())[0] if STUDIO_BACKGROUNDS else None,
444
+ label="์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ ์„ ํƒ",
445
+ visible=False,
446
+ interactive=True
447
+ )
448
+
449
+ # ์ž์—ฐ ํ™˜๊ฒฝ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด
450
+ nature_dropdown = gr.Dropdown(
451
+ choices=list(NATURE_BACKGROUNDS.keys()),
452
+ value=list(NATURE_BACKGROUNDS.keys())[0] if NATURE_BACKGROUNDS else None,
453
+ label="์ž์—ฐ ํ™˜๊ฒฝ ์„ ํƒ",
454
+ visible=False,
455
+ interactive=True
456
+ )
457
+
458
+ # ์‹ค๋‚ด ํ™˜๊ฒฝ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด
459
+ indoor_dropdown = gr.Dropdown(
460
+ choices=list(INDOOR_BACKGROUNDS.keys()),
461
+ value=list(INDOOR_BACKGROUNDS.keys())[0] if INDOOR_BACKGROUNDS else None,
462
+ label="์‹ค๋‚ด ํ™˜๊ฒฝ ์„ ํƒ",
463
+ visible=False,
464
+ interactive=True
465
+ )
466
+
467
+ # ์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด
468
+ abstract_dropdown = gr.Dropdown(
469
+ choices=list(ABSTRACT_BACKGROUNDS.keys()),
470
+ value=list(ABSTRACT_BACKGROUNDS.keys())[0] if ABSTRACT_BACKGROUNDS else None,
471
+ label="์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ ์„ ํƒ",
472
+ visible=False,
473
+ interactive=True
474
+ )
475
+
476
+ # ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ
477
+ additional_info = gr.Textbox(
478
+ label="์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ (์„ ํƒ์‚ฌํ•ญ)",
479
+ placeholder="์˜ˆ: ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋А๋‚Œ, ๋ฐ์€ ์กฐ๋ช…, ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณด์กฐ์ ์ธ ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š” ๋“ฑ",
480
+ lines=2,
481
+ interactive=True
482
+ )
483
+
484
+ # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ
485
+ generate_prompt_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ")
486
+
487
+ with gr.Column():
488
+ # ์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
489
+ prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ", lines=5)
490
 
491
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ
492
+ with gr.Row():
493
+ submit_single_btn = gr.Button('์ด๋ฏธ์ง€ ์ƒ์„ฑ (1์žฅ)')
494
+ submit_btn = gr.Button('์ด๋ฏธ์ง€ ์ƒ์„ฑ (4์žฅ)')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
 
496
+ with gr.Column():
497
+ with gr.Row():
498
+ with gr.Column():
499
+ output_image1 = gr.Image(label="์ด๋ฏธ์ง€ #1", type="filepath")
500
+ output_image3 = gr.Image(label="์ด๋ฏธ์ง€ #3", type="filepath")
501
+ with gr.Column():
502
+ output_image2 = gr.Image(label="์ด๋ฏธ์ง€ #2", type="filepath")
503
+ output_image4 = gr.Image(label="์ด๋ฏธ์ง€ #4", type="filepath")
504
+
505
+ output_text = gr.Textbox(label="๊ฒฐ๊ณผ ์ •๋ณด", lines=2)
506
+ prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", lines=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
 
508
  # ๋ฐฐ๊ฒฝ ์œ ํ˜•์— ๋”ฐ๋ผ ๋“œ๋กญ๋‹ค์šด ํ‘œ์‹œ ์—…๋ฐ์ดํŠธ
509
  def update_dropdowns(bg_type):
 
515
  abstract_dropdown: gr.update(visible=(bg_type == "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ"))
516
  }
517
 
518
+ # ๋ฐฐ๊ฒฝ ์œ ํ˜• ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
519
+ background_type.change(
520
+ fn=update_dropdowns,
521
+ inputs=[background_type],
522
+ outputs=[simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, abstract_dropdown]
523
+ )
524
+
525
  # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ํ•จ์ˆ˜
526
+ def generate_output(image, bg_type, simple, studio, nature, indoor, abstract, product_text, additional_text):
527
  if image is None:
528
  return "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
529
 
 
536
  prompt = generate_prompt_with_gemini(product_text, background_info, additional_text)
537
 
538
  if not GEMINI_API_KEY:
539
+ return "Gemini API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„ ์„ค์ •ํ•ด์ฃผ์„ธ์š”."
540
 
541
  return prompt
542
  except Exception as e:
543
+ error_msg = f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
544
+ return error_msg
 
 
 
 
 
 
 
 
 
 
545
 
546
+ # ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
547
  generate_prompt_btn.click(
548
+ fn=generate_output,
549
  inputs=[
550
+ image1_input,
551
+ background_type,
552
  simple_dropdown,
553
  studio_dropdown,
554
  nature_dropdown,
 
560
  outputs=prompt_output
561
  )
562
 
 
 
 
 
 
 
 
563
  # ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
564
  submit_single_btn.click(
565
  fn=lambda image1, prompt: process_images_with_prompt(image1, prompt, 0),
566
+ inputs=[image1_input, prompt_output],
567
  outputs=[output_image1, output_text, prompt_display],
568
  )
569
 
570
  # 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
571
  submit_btn.click(
572
  fn=generate_multiple_images,
573
+ inputs=[image1_input, prompt_output],
574
  outputs=[output_image1, output_image2, output_image3, output_image4, output_text, prompt_display],
575
  )
576
 
577
+ demo.queue()
578
+ demo.launch()