Update app.py
Browse files
app.py
CHANGED
@@ -47,16 +47,31 @@ def merge_images(person_img_path, product_img_path, background_img_path, prompt,
|
|
47 |
product_img = Image.open(product_img_path)
|
48 |
|
49 |
# ์ปจํ
์ธ ๋ฆฌ์คํธ ์์ฑ
|
50 |
-
contents = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
# ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง๊ฐ ์์ผ๋ฉด ์ถ๊ฐ
|
53 |
if background_img_path:
|
54 |
background_img = Image.open(background_img_path)
|
55 |
-
contents.append(
|
|
|
|
|
56 |
logger.debug("๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ถ๊ฐ๋จ")
|
57 |
|
58 |
# ๋ง์ง๋ง์ ํ๋กฌํํธ ์ถ๊ฐ
|
59 |
-
contents.append(
|
|
|
|
|
|
|
60 |
logger.debug(f"์ปจํ
์ธ ๊ฐ์ฒด ์์ฑ ์๋ฃ: {len(contents)} ์์ดํ
")
|
61 |
|
62 |
# ์์ฑ ์ค์
|
@@ -65,7 +80,7 @@ def merge_images(person_img_path, product_img_path, background_img_path, prompt,
|
|
65 |
top_p=0.95,
|
66 |
top_k=40,
|
67 |
max_output_tokens=8192,
|
68 |
-
response_modalities=["
|
69 |
)
|
70 |
logger.debug(f"์์ฑ ์ค์ : {generate_content_config}")
|
71 |
|
@@ -73,43 +88,70 @@ def merge_images(person_img_path, product_img_path, background_img_path, prompt,
|
|
73 |
temp_path = tmp.name
|
74 |
logger.debug(f"์์ ํ์ผ ์์ฑ๋จ: {temp_path}")
|
75 |
|
76 |
-
#
|
77 |
-
|
78 |
model=model,
|
79 |
-
contents=
|
|
|
|
|
|
|
|
|
|
|
80 |
config=generate_content_config,
|
81 |
)
|
82 |
|
83 |
-
logger.debug("์๋ต ์ฒ๋ฆฌ ์์...")
|
84 |
|
85 |
# ์๋ต์์ ์ด๋ฏธ์ง์ ํ
์คํธ ์ถ์ถ
|
86 |
image_saved = False
|
87 |
response_text = ""
|
88 |
|
89 |
-
for
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
if not image_saved:
|
99 |
logger.warning("์ด๋ฏธ์ง๊ฐ ์์ฑ๋์ง ์์์ต๋๋ค.")
|
100 |
-
return None, response_text
|
101 |
|
102 |
logger.debug("์ด๋ฏธ์ง ์์ฑ ์๋ฃ.")
|
103 |
return temp_path, response_text
|
104 |
|
105 |
except Exception as e:
|
106 |
logger.exception("์ด๋ฏธ์ง ์์ฑ ์ค ์ค๋ฅ ๋ฐ์:")
|
107 |
-
return None, str(e) # ์ค๋ฅ ๋ฐ์ ์ None๊ณผ ์ค๋ฅ ๋ฉ์์ง ๋ฐํ
|
108 |
|
109 |
|
110 |
def process_images_and_prompt(person_pil, product_pil, background_pil, prompt):
|
111 |
logger.debug(f"process_images_and_prompt ํจ์ ์์ - ํ๋กฌํํธ: '{prompt}'")
|
112 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
# ๊ธฐ๋ณธ ํ๋กฌํํธ ์ค์ (๋น์ด์๋ ๊ฒฝ์ฐ)
|
114 |
if not prompt or not prompt.strip():
|
115 |
if background_pil:
|
@@ -125,22 +167,34 @@ def process_images_and_prompt(person_pil, product_pil, background_pil, prompt):
|
|
125 |
prompt += " Create a realistic composite image of this person with this product."
|
126 |
|
127 |
# ์ด๋ฏธ์ง ์ ์ฅ
|
128 |
-
with tempfile.NamedTemporaryFile(suffix=".
|
129 |
person_path = tmp_person.name
|
130 |
-
|
|
|
|
|
|
|
|
|
131 |
logger.debug(f"์ฌ๋ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ: {person_path}")
|
132 |
|
133 |
-
with tempfile.NamedTemporaryFile(suffix=".
|
134 |
product_path = tmp_product.name
|
135 |
-
|
|
|
|
|
|
|
|
|
136 |
logger.debug(f"์ํ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ: {product_path}")
|
137 |
|
138 |
# ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ ์ฅ (์๋ ๊ฒฝ์ฐ)
|
139 |
background_path = None
|
140 |
if background_pil is not None:
|
141 |
-
with tempfile.NamedTemporaryFile(suffix=".
|
142 |
background_path = tmp_bg.name
|
143 |
-
|
|
|
|
|
|
|
|
|
144 |
logger.debug(f"๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ: {background_path}")
|
145 |
|
146 |
# ์ด๋ฏธ์ง ํฉ์ฑ ์คํ
|
@@ -154,27 +208,31 @@ def process_images_and_prompt(person_pil, product_pil, background_pil, prompt):
|
|
154 |
# ์ด๋ฏธ์ง ๋ฐํ ๋ฐ ์์ ํ์ผ ์ ๋ฆฌ
|
155 |
if result_path:
|
156 |
logger.debug(f"์ด๋ฏธ์ง ์์ฑ ์๋ฃ. ๊ฒฝ๋ก: {result_path}")
|
157 |
-
result_img = Image.open(result_path)
|
158 |
-
if result_img.mode == "RGBA":
|
159 |
-
result_img = result_img.convert("RGB")
|
160 |
-
|
161 |
-
# ์์ ํ์ผ ์ ๋ฆฌ
|
162 |
try:
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
except Exception as e:
|
168 |
-
logger.
|
169 |
-
|
170 |
-
return [result_img], response_text
|
171 |
else:
|
172 |
logger.error("merge_images ํจ์์์ None ๋ฐํ๋จ.")
|
173 |
-
return [], response_text
|
174 |
|
175 |
except Exception as e:
|
176 |
logger.exception("process_images_and_prompt ํจ์์์ ์ค๋ฅ ๋ฐ์:")
|
177 |
-
return [], str(e) # ์ค๋ฅ
|
178 |
|
179 |
|
180 |
# --- Gradio ์ธํฐํ์ด์ค ๊ตฌ์ฑ ---
|
|
|
47 |
product_img = Image.open(product_img_path)
|
48 |
|
49 |
# ์ปจํ
์ธ ๋ฆฌ์คํธ ์์ฑ
|
50 |
+
contents = []
|
51 |
+
|
52 |
+
# ์ฌ๋ ์ด๋ฏธ์ง ์ถ๊ฐ
|
53 |
+
contents.append(
|
54 |
+
types.Part.from_data(data=person_img, mime_type="image/jpeg")
|
55 |
+
)
|
56 |
+
|
57 |
+
# ์ํ ์ด๋ฏธ์ง ์ถ๊ฐ
|
58 |
+
contents.append(
|
59 |
+
types.Part.from_data(data=product_img, mime_type="image/jpeg")
|
60 |
+
)
|
61 |
|
62 |
# ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง๊ฐ ์์ผ๋ฉด ์ถ๊ฐ
|
63 |
if background_img_path:
|
64 |
background_img = Image.open(background_img_path)
|
65 |
+
contents.append(
|
66 |
+
types.Part.from_data(data=background_img, mime_type="image/jpeg")
|
67 |
+
)
|
68 |
logger.debug("๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ถ๊ฐ๋จ")
|
69 |
|
70 |
# ๋ง์ง๋ง์ ํ๋กฌํํธ ์ถ๊ฐ
|
71 |
+
contents.append(
|
72 |
+
types.Part.from_text(text=prompt)
|
73 |
+
)
|
74 |
+
|
75 |
logger.debug(f"์ปจํ
์ธ ๊ฐ์ฒด ์์ฑ ์๋ฃ: {len(contents)} ์์ดํ
")
|
76 |
|
77 |
# ์์ฑ ์ค์
|
|
|
80 |
top_p=0.95,
|
81 |
top_k=40,
|
82 |
max_output_tokens=8192,
|
83 |
+
response_modalities=["image", "text"],
|
84 |
)
|
85 |
logger.debug(f"์์ฑ ์ค์ : {generate_content_config}")
|
86 |
|
|
|
88 |
temp_path = tmp.name
|
89 |
logger.debug(f"์์ ํ์ผ ์์ฑ๋จ: {temp_path}")
|
90 |
|
91 |
+
# ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ ์์ (์๋ ์ฝ๋ ๋ฐฉ์์ผ๋ก ๋ณต์)
|
92 |
+
response_stream = client.models.generate_content_stream(
|
93 |
model=model,
|
94 |
+
contents=[
|
95 |
+
types.Content(
|
96 |
+
role="user",
|
97 |
+
parts=contents,
|
98 |
+
),
|
99 |
+
],
|
100 |
config=generate_content_config,
|
101 |
)
|
102 |
|
103 |
+
logger.debug("์๋ต ์คํธ๋ฆผ ์ฒ๋ฆฌ ์์...")
|
104 |
|
105 |
# ์๋ต์์ ์ด๋ฏธ์ง์ ํ
์คํธ ์ถ์ถ
|
106 |
image_saved = False
|
107 |
response_text = ""
|
108 |
|
109 |
+
for chunk in response_stream:
|
110 |
+
logger.debug(f"chunk ์์ : {chunk}")
|
111 |
+
|
112 |
+
# ์๋ต ๊ฒ์ฆ
|
113 |
+
if not hasattr(chunk, 'candidates') or not chunk.candidates:
|
114 |
+
logger.warning("chunk์ candidates๊ฐ ์์ต๋๋ค. ๊ฑด๋๋๋๋ค.")
|
115 |
+
continue
|
116 |
+
|
117 |
+
if not hasattr(chunk.candidates[0], 'content') or not chunk.candidates[0].content:
|
118 |
+
logger.warning("chunk.candidates[0]์ content๊ฐ ์์ต๋๋ค. ๊ฑด๋๋๋๋ค.")
|
119 |
+
continue
|
120 |
+
|
121 |
+
if not hasattr(chunk.candidates[0].content, 'parts') or not chunk.candidates[0].content.parts:
|
122 |
+
logger.warning("chunk.candidates[0].content์ parts๊ฐ ์์ต๋๋ค. ๊ฑด๋๋๋๋ค.")
|
123 |
+
continue
|
124 |
+
|
125 |
+
for part in chunk.candidates[0].content.parts:
|
126 |
+
if hasattr(part, 'text') and part.text:
|
127 |
+
response_text += part.text
|
128 |
+
logger.info(f"์์ ๋ ํ
์คํธ: {part.text}")
|
129 |
+
elif hasattr(part, 'inline_data') and part.inline_data:
|
130 |
+
save_binary_file(temp_path, part.inline_data.data)
|
131 |
+
logger.info(f"MIME ํ์
{part.inline_data.mime_type}์ ํ์ผ์ด ์ ์ฅ๋จ: {temp_path}")
|
132 |
+
image_saved = True
|
133 |
|
134 |
if not image_saved:
|
135 |
logger.warning("์ด๋ฏธ์ง๊ฐ ์์ฑ๋์ง ์์์ต๋๋ค.")
|
136 |
+
return None, response_text or "์ด๋ฏธ์ง๊ฐ ์์ฑ๋์ง ์์์ต๋๋ค. ๋ค๋ฅธ ํ๋กฌํํธ๋ ์ด๋ฏธ์ง๋ก ์๋ํด๋ณด์ธ์."
|
137 |
|
138 |
logger.debug("์ด๋ฏธ์ง ์์ฑ ์๋ฃ.")
|
139 |
return temp_path, response_text
|
140 |
|
141 |
except Exception as e:
|
142 |
logger.exception("์ด๋ฏธ์ง ์์ฑ ์ค ์ค๋ฅ ๋ฐ์:")
|
143 |
+
return None, f"์ค๋ฅ ๋ฐ์: {str(e)}" # ์ค๋ฅ ๋ฐ์ ์ None๊ณผ ์ค๋ฅ ๋ฉ์์ง ๋ฐํ
|
144 |
|
145 |
|
146 |
def process_images_and_prompt(person_pil, product_pil, background_pil, prompt):
|
147 |
logger.debug(f"process_images_and_prompt ํจ์ ์์ - ํ๋กฌํํธ: '{prompt}'")
|
148 |
try:
|
149 |
+
# ํ์ ์ด๋ฏธ์ง ํ์ธ
|
150 |
+
if person_pil is None:
|
151 |
+
return [], "์ฌ๋ ์ด๋ฏธ์ง๋ฅผ ์
๋ก๋ํด์ฃผ์ธ์."
|
152 |
+
if product_pil is None:
|
153 |
+
return [], "์ํ ์ด๋ฏธ์ง๋ฅผ ์
๋ก๋ํด์ฃผ์ธ์."
|
154 |
+
|
155 |
# ๊ธฐ๋ณธ ํ๋กฌํํธ ์ค์ (๋น์ด์๋ ๊ฒฝ์ฐ)
|
156 |
if not prompt or not prompt.strip():
|
157 |
if background_pil:
|
|
|
167 |
prompt += " Create a realistic composite image of this person with this product."
|
168 |
|
169 |
# ์ด๋ฏธ์ง ์ ์ฅ
|
170 |
+
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp_person:
|
171 |
person_path = tmp_person.name
|
172 |
+
# RGB๋ก ๋ณํํ์ฌ ์ ์ฅ
|
173 |
+
person_img = person_pil
|
174 |
+
if person_img.mode != 'RGB':
|
175 |
+
person_img = person_img.convert('RGB')
|
176 |
+
person_img.save(person_path, 'JPEG')
|
177 |
logger.debug(f"์ฌ๋ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ: {person_path}")
|
178 |
|
179 |
+
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp_product:
|
180 |
product_path = tmp_product.name
|
181 |
+
# RGB๋ก ๋ณํํ์ฌ ์ ์ฅ
|
182 |
+
product_img = product_pil
|
183 |
+
if product_img.mode != 'RGB':
|
184 |
+
product_img = product_img.convert('RGB')
|
185 |
+
product_img.save(product_path, 'JPEG')
|
186 |
logger.debug(f"์ํ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ: {product_path}")
|
187 |
|
188 |
# ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ ์ฅ (์๋ ๊ฒฝ์ฐ)
|
189 |
background_path = None
|
190 |
if background_pil is not None:
|
191 |
+
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp_bg:
|
192 |
background_path = tmp_bg.name
|
193 |
+
# RGB๋ก ๋ณํํ์ฌ ์ ์ฅ
|
194 |
+
background_img = background_pil
|
195 |
+
if background_img.mode != 'RGB':
|
196 |
+
background_img = background_img.convert('RGB')
|
197 |
+
background_img.save(background_path, 'JPEG')
|
198 |
logger.debug(f"๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ ์ฅ ์๋ฃ: {background_path}")
|
199 |
|
200 |
# ์ด๋ฏธ์ง ํฉ์ฑ ์คํ
|
|
|
208 |
# ์ด๋ฏธ์ง ๋ฐํ ๋ฐ ์์ ํ์ผ ์ ๋ฆฌ
|
209 |
if result_path:
|
210 |
logger.debug(f"์ด๋ฏธ์ง ์์ฑ ์๋ฃ. ๊ฒฝ๋ก: {result_path}")
|
|
|
|
|
|
|
|
|
|
|
211 |
try:
|
212 |
+
result_img = Image.open(result_path)
|
213 |
+
if result_img.mode == "RGBA":
|
214 |
+
result_img = result_img.convert("RGB")
|
215 |
+
|
216 |
+
# ์์ ํ์ผ ์ ๋ฆฌ
|
217 |
+
try:
|
218 |
+
os.unlink(person_path)
|
219 |
+
os.unlink(product_path)
|
220 |
+
if background_path:
|
221 |
+
os.unlink(background_path)
|
222 |
+
except Exception as e:
|
223 |
+
logger.warning(f"์์ ํ์ผ ์ญ์ ์ค ์ค๋ฅ: {str(e)}")
|
224 |
+
|
225 |
+
return [result_img], response_text or "์ด๋ฏธ์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์์ต๋๋ค."
|
226 |
except Exception as e:
|
227 |
+
logger.exception(f"๊ฒฐ๊ณผ ์ด๋ฏธ์ง ๋ก๋ ์ค ์ค๋ฅ: {str(e)}")
|
228 |
+
return [], f"๊ฒฐ๊ณผ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ์ค ์ค๋ฅ: {str(e)}"
|
|
|
229 |
else:
|
230 |
logger.error("merge_images ํจ์์์ None ๋ฐํ๋จ.")
|
231 |
+
return [], response_text or "์ด๋ฏธ์ง ์์ฑ์ ์คํจํ์ต๋๋ค. ๋ค๋ฅธ ์ด๋ฏธ์ง๋ ํ๋กฌํํธ๋ก ์๋ํด๋ณด์ธ์."
|
232 |
|
233 |
except Exception as e:
|
234 |
logger.exception("process_images_and_prompt ํจ์์์ ์ค๋ฅ ๋ฐ์:")
|
235 |
+
return [], f"์ค๋ฅ ๋ฐ์: {str(e)}" # ์ค๋ฅ ์ ๋น ๋ฆฌ์คํธ์ ์ค๋ฅ ๋ฉ์์ง ๋ฐํ
|
236 |
|
237 |
|
238 |
# --- Gradio ์ธํฐํ์ด์ค ๊ตฌ์ฑ ---
|