Update app.py
Browse files
app.py
CHANGED
|
@@ -81,9 +81,44 @@ def enhance_image_quality(image):
|
|
| 81 |
|
| 82 |
return image
|
| 83 |
|
| 84 |
-
def
|
| 85 |
-
"""
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
def check_white_background_ratio(image, threshold=0.85):
|
| 89 |
"""ν°μ λ°°κ²½ λΉμ¨ νμΈ (85% κ·μΉ)"""
|
|
@@ -134,7 +169,7 @@ def process_with_ai_enhancement(image_path, prompt_option):
|
|
| 134 |
except Exception as e:
|
| 135 |
return None, f"AI μ²λ¦¬ μ€ μ€λ₯: {str(e)}"
|
| 136 |
|
| 137 |
-
def create_coupang_thumbnail(image, apply_shadow,
|
| 138 |
"""μΏ ν‘ μΈλ€μΌ μμ± λ©μΈ ν¨μ"""
|
| 139 |
if image is None:
|
| 140 |
return None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ."
|
|
@@ -143,7 +178,21 @@ def create_coupang_thumbnail(image, apply_shadow, apply_rotation, rotation_angle
|
|
| 143 |
result_image = image.copy()
|
| 144 |
status_messages = []
|
| 145 |
|
| 146 |
-
# 1λ¨κ³:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
if ai_enhancement and REPLICATE_API_TOKEN:
|
| 148 |
temp_path = upload_image_to_temp_url(result_image)
|
| 149 |
if temp_path:
|
|
@@ -155,15 +204,10 @@ def create_coupang_thumbnail(image, apply_shadow, apply_rotation, rotation_angle
|
|
| 155 |
status_messages.append(f"β AI ν₯μ: {ai_msg}")
|
| 156 |
os.unlink(temp_path) # μμ νμΌ μμ
|
| 157 |
|
| 158 |
-
#
|
| 159 |
result_image = enhance_image_quality(result_image)
|
| 160 |
status_messages.append("β
νμ§ ν₯μ μλ£")
|
| 161 |
|
| 162 |
-
# 3λ¨κ³: κ°λ λ³κ²½ (μμ΄ν
μλ ννΌ)
|
| 163 |
-
if apply_rotation:
|
| 164 |
-
result_image = rotate_image_slightly(result_image, rotation_angle)
|
| 165 |
-
status_messages.append(f"β
κ°λ λ³κ²½: {rotation_angle}λ νμ ")
|
| 166 |
-
|
| 167 |
# 4λ¨κ³: ν° λ°°κ²½ + κ·Έλ¦Όμ ν¨κ³Ό
|
| 168 |
if apply_shadow:
|
| 169 |
result_image = create_white_background_shadow(result_image)
|
|
@@ -202,7 +246,7 @@ def create_interface():
|
|
| 202 |
## π‘ μ μ©λλ μΏ ν‘ κ·μ λμ μ λ΅:
|
| 203 |
- β
**ν° λ°°κ²½ + 85% κ·μΉ** μλ²½ μ€μ
|
| 204 |
- β
**AI λ§λ² ν둬ννΈ**λ‘ νμ§ ν₯μ
|
| 205 |
-
- β
|
| 206 |
- β
**κ·Έλ¦Όμ ν¨κ³Ό**λ‘ μμ°μ€λ¬μ΄ μ
μ²΄κ° μ°μΆ
|
| 207 |
""")
|
| 208 |
|
|
@@ -224,17 +268,16 @@ def create_interface():
|
|
| 224 |
value=True,
|
| 225 |
info="μμ°μ€λ¬μ΄ μ
μ²΄κ° μ°μΆ"
|
| 226 |
)
|
| 227 |
-
|
| 228 |
-
label="κ°λ λ³κ²½
|
| 229 |
value=True,
|
| 230 |
-
info="
|
| 231 |
)
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
label="νμ κ°λ",
|
| 238 |
visible=True
|
| 239 |
)
|
| 240 |
|
|
@@ -270,9 +313,18 @@ def create_interface():
|
|
| 270 |
---
|
| 271 |
## π μ¬μ© λ°©λ²
|
| 272 |
1. **λ°°κ²½μ΄ μ κ±°λ μν μ΄λ―Έμ§**λ₯Ό μ
λ‘λνμΈμ
|
| 273 |
-
2.
|
| 274 |
-
3.
|
| 275 |
-
4. **
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
|
| 277 |
## π API μ€μ (μ νμ¬ν)
|
| 278 |
AI ν₯μ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νκ²½λ³μλ₯Ό μ€μ νμΈμ:
|
|
@@ -282,18 +334,18 @@ def create_interface():
|
|
| 282 |
""")
|
| 283 |
|
| 284 |
# μ΄λ²€νΈ μ²λ¦¬
|
| 285 |
-
def
|
| 286 |
-
return gr.update(visible=
|
| 287 |
|
| 288 |
-
|
| 289 |
|
| 290 |
process_btn.click(
|
| 291 |
create_coupang_thumbnail,
|
| 292 |
inputs=[
|
| 293 |
input_image,
|
| 294 |
apply_shadow,
|
| 295 |
-
|
| 296 |
-
|
| 297 |
ai_enhancement,
|
| 298 |
prompt_option
|
| 299 |
],
|
|
|
|
| 81 |
|
| 82 |
return image
|
| 83 |
|
| 84 |
+
def change_product_angle_with_ai(image_path, angle_option):
|
| 85 |
+
"""AIλ₯Ό μ΄μ©ν μν κ°λ/λ°©ν₯ λ³κ²½μΌλ‘ μμ΄ν
μλ ννΌ"""
|
| 86 |
+
if not REPLICATE_API_TOKEN:
|
| 87 |
+
return None, "Replicate API ν ν°μ΄ μ€μ λμ§ μμμ΅λλ€."
|
| 88 |
+
|
| 89 |
+
try:
|
| 90 |
+
# κ°λ λ³κ²½ ν둬ννΈ μ΅μ
|
| 91 |
+
angle_prompts = {
|
| 92 |
+
"μΌμͺ½ 45λ": "Change the product angle to show it from 45-degree left side view, professional product photography, white background",
|
| 93 |
+
"μ€λ₯Έμͺ½ 45λ": "Change the product angle to show it from 45-degree right side view, professional product photography, white background",
|
| 94 |
+
"μλ¨ μ΅κΈ": "Change to top-down angle view of the product, bird's eye view, professional product photography, white background",
|
| 95 |
+
"3/4 λ·°": "Change to 3/4 angle view of the product, three-quarter perspective, professional product photography, white background",
|
| 96 |
+
"μ λ©΄μμ μΈ‘λ©΄": "Change from front view to side view of the product, profile angle, professional product photography, white background",
|
| 97 |
+
"μΈ‘λ©΄μμ μ λ©΄": "Change from side view to front view of the product, frontal angle, professional product photography, white background"
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
selected_prompt = angle_prompts.get(angle_option, angle_prompts["3/4 λ·°"])
|
| 101 |
+
|
| 102 |
+
# Replicate API νΈμΆ
|
| 103 |
+
output = replicate.run(
|
| 104 |
+
"black-forest-labs/flux-kontext-pro",
|
| 105 |
+
input={
|
| 106 |
+
"prompt": selected_prompt,
|
| 107 |
+
"input_image": open(image_path, "rb"),
|
| 108 |
+
"output_format": "jpg"
|
| 109 |
+
}
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
# κ²°κ³Ό μ΄λ―Έμ§ λ€μ΄λ‘λ
|
| 113 |
+
response = requests.get(output)
|
| 114 |
+
if response.status_code == 200:
|
| 115 |
+
angled_image = Image.open(io.BytesIO(response.content))
|
| 116 |
+
return angled_image, f"μν κ°λ λ³κ²½ μλ£: {angle_option}"
|
| 117 |
+
else:
|
| 118 |
+
return None, "κ°λ λ³κ²½ μ€ν¨"
|
| 119 |
+
|
| 120 |
+
except Exception as e:
|
| 121 |
+
return None, f"κ°λ λ³κ²½ μ€ μ€λ₯: {str(e)}"
|
| 122 |
|
| 123 |
def check_white_background_ratio(image, threshold=0.85):
|
| 124 |
"""ν°μ λ°°κ²½ λΉμ¨ νμΈ (85% κ·μΉ)"""
|
|
|
|
| 169 |
except Exception as e:
|
| 170 |
return None, f"AI μ²λ¦¬ μ€ μ€λ₯: {str(e)}"
|
| 171 |
|
| 172 |
+
def create_coupang_thumbnail(image, apply_shadow, apply_angle_change, angle_option, ai_enhancement, prompt_option):
|
| 173 |
"""μΏ ν‘ μΈλ€μΌ μμ± λ©μΈ ν¨μ"""
|
| 174 |
if image is None:
|
| 175 |
return None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ."
|
|
|
|
| 178 |
result_image = image.copy()
|
| 179 |
status_messages = []
|
| 180 |
|
| 181 |
+
# 1λ¨κ³: μν κ°λ λ³κ²½ (μμ΄ν
μλ ννΌ)
|
| 182 |
+
if apply_angle_change and REPLICATE_API_TOKEN:
|
| 183 |
+
temp_path = upload_image_to_temp_url(result_image)
|
| 184 |
+
if temp_path:
|
| 185 |
+
angled_img, angle_msg = change_product_angle_with_ai(temp_path, angle_option)
|
| 186 |
+
if angled_img:
|
| 187 |
+
result_image = angled_img
|
| 188 |
+
status_messages.append(f"β
μν κ°λ λ³κ²½: {angle_msg}")
|
| 189 |
+
else:
|
| 190 |
+
status_messages.append(f"β κ°λ λ³κ²½: {angle_msg}")
|
| 191 |
+
os.unlink(temp_path) # μμ νμΌ μμ
|
| 192 |
+
elif apply_angle_change and not REPLICATE_API_TOKEN:
|
| 193 |
+
status_messages.append("β οΈ κ°λ λ³κ²½μλ Replicate API ν ν°μ΄ νμν©λλ€")
|
| 194 |
+
|
| 195 |
+
# 2λ¨κ³: AI νμ§ ν₯μ (μ νμ¬ν)
|
| 196 |
if ai_enhancement and REPLICATE_API_TOKEN:
|
| 197 |
temp_path = upload_image_to_temp_url(result_image)
|
| 198 |
if temp_path:
|
|
|
|
| 204 |
status_messages.append(f"β AI ν₯μ: {ai_msg}")
|
| 205 |
os.unlink(temp_path) # μμ νμΌ μμ
|
| 206 |
|
| 207 |
+
# 3λ¨κ³: νμ§ ν₯μ
|
| 208 |
result_image = enhance_image_quality(result_image)
|
| 209 |
status_messages.append("β
νμ§ ν₯μ μλ£")
|
| 210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
# 4λ¨κ³: ν° λ°°κ²½ + κ·Έλ¦Όμ ν¨κ³Ό
|
| 212 |
if apply_shadow:
|
| 213 |
result_image = create_white_background_shadow(result_image)
|
|
|
|
| 246 |
## π‘ μ μ©λλ μΏ ν‘ κ·μ λμ μ λ΅:
|
| 247 |
- β
**ν° λ°°κ²½ + 85% κ·μΉ** μλ²½ μ€μ
|
| 248 |
- β
**AI λ§λ² ν둬ννΈ**λ‘ νμ§ ν₯μ
|
| 249 |
+
- β
**μν κ°λ λ³κ²½**μΌλ‘ μμ΄ν
μλ(μ€λ³΅) ννΌ
|
| 250 |
- β
**κ·Έλ¦Όμ ν¨κ³Ό**λ‘ μμ°μ€λ¬μ΄ μ
μ²΄κ° μ°μΆ
|
| 251 |
""")
|
| 252 |
|
|
|
|
| 268 |
value=True,
|
| 269 |
info="μμ°μ€λ¬μ΄ μ
μ²΄κ° μ°μΆ"
|
| 270 |
)
|
| 271 |
+
apply_angle_change = gr.Checkbox(
|
| 272 |
+
label="μν κ°λ λ³κ²½ (μμ΄ν
μλ ννΌ)",
|
| 273 |
value=True,
|
| 274 |
+
info="AIλ‘ μνμ κ°λ/λ°©ν₯μ λ³κ²½νμ¬ μ€λ³΅ ννΌ"
|
| 275 |
)
|
| 276 |
+
angle_option = gr.Dropdown(
|
| 277 |
+
choices=["μΌμͺ½ 45λ", "μ€λ₯Έμͺ½ 45λ", "μλ¨ μ΅κΈ", "3/4 λ·°", "μ λ©΄μμ μΈ‘λ©΄", "μΈ‘λ©΄μμ μ λ©΄"],
|
| 278 |
+
value="3/4 λ·°",
|
| 279 |
+
label="λ³κ²½ν κ°λ",
|
| 280 |
+
info="μνμ μ΄λ€ κ°λλ‘ λ³κ²½ν μ§ μ ν",
|
|
|
|
| 281 |
visible=True
|
| 282 |
)
|
| 283 |
|
|
|
|
| 313 |
---
|
| 314 |
## π μ¬μ© λ°©λ²
|
| 315 |
1. **λ°°κ²½μ΄ μ κ±°λ μν μ΄λ―Έμ§**λ₯Ό μ
λ‘λνμΈμ
|
| 316 |
+
2. **μν κ°λ λ³κ²½ μ΅μ
**μ μ ννμ¬ μμ΄ν
μλ(μ€λ³΅)λ₯Ό ννΌνμΈμ
|
| 317 |
+
3. μνλ **ν¨κ³Ό μ΅μ
**μ μ ννμΈμ
|
| 318 |
+
4. **AI ν₯μ**μ μ¬μ©νλ €λ©΄ Replicate API ν ν°μ νκ²½λ³μλ‘ μ€μ νμΈμ
|
| 319 |
+
5. **'μΏ ν‘ μΈλ€μΌ μμ±'** λ²νΌμ ν΄λ¦νμΈμ
|
| 320 |
+
|
| 321 |
+
## π― μν κ°λ λ³κ²½ μ΅μ
μ€λͺ
|
| 322 |
+
- **μΌμͺ½ 45λ**: μνμ μΌμͺ½μμ 45λ κ°λλ‘ μ΄¬μν λλ
|
| 323 |
+
- **μ€λ₯Έμͺ½ 45λ**: μνμ μ€λ₯Έμͺ½μμ 45λ κ°λλ‘ μ΄¬μν λλ
|
| 324 |
+
- **μλ¨ μ΅κΈ**: μμμ λ΄λ €λ€λ³Έ νλ·° κ°λ
|
| 325 |
+
- **3/4 λ·°**: κ°μ₯ μΌλ°μ μΈ μν 촬μ κ°λ (μΆμ²)
|
| 326 |
+
- **μ λ©΄μμ μΈ‘λ©΄**: μ λ©΄ μ΄λ―Έμ§λ₯Ό μΈ‘λ©΄ κ°λλ‘ λ³κ²½
|
| 327 |
+
- **μΈ‘λ©΄μμ μ λ©΄**: μΈ‘λ©΄ μ΄λ―Έμ§λ₯Ό μ λ©΄ κ°λλ‘ λ³κ²½
|
| 328 |
|
| 329 |
## π API μ€μ (μ νμ¬ν)
|
| 330 |
AI ν₯μ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νκ²½λ³μλ₯Ό μ€μ νμΈμ:
|
|
|
|
| 334 |
""")
|
| 335 |
|
| 336 |
# μ΄λ²€νΈ μ²λ¦¬
|
| 337 |
+
def update_angle_visibility(apply_angle):
|
| 338 |
+
return gr.update(visible=apply_angle)
|
| 339 |
|
| 340 |
+
apply_angle_change.change(update_angle_visibility, apply_angle_change, angle_option)
|
| 341 |
|
| 342 |
process_btn.click(
|
| 343 |
create_coupang_thumbnail,
|
| 344 |
inputs=[
|
| 345 |
input_image,
|
| 346 |
apply_shadow,
|
| 347 |
+
apply_angle_change,
|
| 348 |
+
angle_option,
|
| 349 |
ai_enhancement,
|
| 350 |
prompt_option
|
| 351 |
],
|