df3esdf / app.py
ssboost's picture
Update app.py
6cf20c5 verified
import gradio as gr
import replicate
import os
import requests
from PIL import Image, ImageDraw, ImageFilter, ImageEnhance
import io
import tempfile
import numpy as np
# Replicate API ํ† ํฐ ์„ค์ •
REPLICATE_API_TOKEN = os.getenv("REPLICATE_API_TOKEN")
if REPLICATE_API_TOKEN:
os.environ["REPLICATE_API_TOKEN"] = REPLICATE_API_TOKEN
def upload_image_to_temp_url(image):
"""์ด๋ฏธ์ง€๋ฅผ ์ž„์‹œ ํŒŒ์ผ๋กœ ์ €์žฅ"""
if image is None:
return None
with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as tmp_file:
image.save(tmp_file.name, format='PNG')
return tmp_file.name
def remove_background_with_ai(image_path):
"""AI ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ"""
if not REPLICATE_API_TOKEN:
return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
try:
output = replicate.run(
"851-labs/background-remover:a029dff38972b5fda4ec5d75d7d1cd25aeff621d2cf4946a41055d7db66b80bc",
input={"image": open(image_path, "rb")}
)
response = requests.get(output)
if response.status_code == 200:
return Image.open(io.BytesIO(response.content)), "๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ์™„๋ฃŒ"
else:
return None, "๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ์‹คํŒจ"
except Exception as e:
return None, f"๋ฐฐ๊ฒฝ ์ œ๊ฑฐ ์˜ค๋ฅ˜: {str(e)}"
def upscale_with_clarity(image_path):
"""ํ™”์งˆ ๊ฐœ์„  ์—…์Šค์ผ€์ผ๋Ÿฌ"""
if not REPLICATE_API_TOKEN:
return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
try:
output = replicate.run(
"philz1337x/clarity-upscaler:dfad41707589d68ecdccd1dfa600d55a208f9310748e44bfe35b4a6291453d5e",
input={"image": open(image_path, "rb")}
)
# output์€ ๋ฆฌ์ŠคํŠธ์ด๋ฏ€๋กœ ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ ์‚ฌ์šฉ
response = requests.get(output[0])
if response.status_code == 200:
return Image.open(io.BytesIO(response.content)), "ํ™”์งˆ ๊ฐœ์„  ์™„๋ฃŒ"
else:
return None, "ํ™”์งˆ ๊ฐœ์„  ์‹คํŒจ"
except Exception as e:
return None, f"ํ™”์งˆ ๊ฐœ์„  ์˜ค๋ฅ˜: {str(e)}"
def change_product_angle(image_path):
"""์นด๋ฉ”๋ผ ์œ„์น˜๋ฅผ ๋ฐ”๊ฟ”์„œ ๋‹ค๋ฅธ ์•ต๊ธ€๋กœ ์ดฌ์˜"""
if not REPLICATE_API_TOKEN:
return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
try:
# Gen4 Image๋กœ ์นด๋ฉ”๋ผ ์œ„์น˜ ๋ณ€๊ฒฝ (ํŒŒ์ผ ์ง์ ‘ ์—…๋กœ๋“œ)
angle_prompt = "Professional product photography of @product from 45-degree side angle, three-quarter view, diagonal perspective, different camera position, clean background"
with open(image_path, "rb") as image_file:
output = replicate.run(
"runwayml/gen4-image",
input={
"prompt": angle_prompt,
"aspect_ratio": "1:1",
"resolution": "1080p",
"reference_images": [image_file],
"reference_tags": ["product"]
}
)
response = requests.get(output)
if response.status_code == 200:
return Image.open(io.BytesIO(response.content)), "์นด๋ฉ”๋ผ ์•ต๊ธ€ ๋ณ€๊ฒฝ ์™„๋ฃŒ (Gen4)"
else:
return None, "์นด๋ฉ”๋ผ ์•ต๊ธ€ ๋ณ€๊ฒฝ ์‹คํŒจ"
except Exception as e:
return None, f"์นด๋ฉ”๋ผ ์•ต๊ธ€ ๋ณ€๊ฒฝ ์˜ค๋ฅ˜: {str(e)}"
def add_shadow_only(image_path):
"""๋ฐฐ๊ฒฝ ์ œ๊ฑฐ๋œ ์ƒํ’ˆ์— ๊ทธ๋ฆผ์ž๋งŒ ์ถ”๊ฐ€ (์™„์ „ํ•œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ)"""
if not REPLICATE_API_TOKEN:
return None, "Replicate API ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
try:
# Gen4 Image๋กœ ๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ (ํŒŒ์ผ ์ง์ ‘ ์—…๋กœ๋“œ)
shadow_prompt = "Professional product photography of @product on pure white background with natural soft drop shadow, clean white backdrop, subtle shadow effect, e-commerce style"
with open(image_path, "rb") as image_file:
output = replicate.run(
"runwayml/gen4-image",
input={
"prompt": shadow_prompt,
"aspect_ratio": "1:1",
"resolution": "1080p",
"reference_images": [image_file],
"reference_tags": ["product"]
}
)
response = requests.get(output)
if response.status_code == 200:
return Image.open(io.BytesIO(response.content)), "๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ์™„๋ฃŒ (Gen4)"
else:
return None, "๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ์‹คํŒจ"
except Exception as e:
return None, f"๊ทธ๋ฆผ์ž ์ถ”๊ฐ€ ์˜ค๋ฅ˜: {str(e)}"
def process_image(image, remove_bg, upscale_quality):
"""๋ฉ”์ธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
if image is None:
return None, "์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
try:
result_image = image.copy()
status_messages = []
# 1๋‹จ๊ณ„: ์ƒํ’ˆ ๊ฐ๋„ ๋ณ€๊ฒฝ
temp_path = upload_image_to_temp_url(result_image)
if temp_path:
angled_img, angle_msg = change_product_angle(temp_path)
if angled_img:
result_image = angled_img
status_messages.append(f"โœ… {angle_msg}")
else:
status_messages.append(f"โŒ {angle_msg}")
os.unlink(temp_path)
# 2๋‹จ๊ณ„: ๋ฐฐ๊ฒฝ ์ œ๊ฑฐ (๋ˆ„๋ผ)
if remove_bg:
temp_path = upload_image_to_temp_url(result_image)
if temp_path:
bg_removed_img, bg_msg = remove_background_with_ai(temp_path)
if bg_removed_img:
result_image = bg_removed_img
status_messages.append(f"โœ… {bg_msg}")
else:
status_messages.append(f"โŒ {bg_msg}")
os.unlink(temp_path)
# 3๋‹จ๊ณ„: ๊ทธ๋ฆผ์ž๋งŒ ์ถ”๊ฐ€ (์™„์ „ํ•œ ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ)
temp_path = upload_image_to_temp_url(result_image)
if temp_path:
shadow_img, shadow_msg = add_shadow_only(temp_path)
if shadow_img:
result_image = shadow_img
status_messages.append(f"โœ… {shadow_msg}")
else:
status_messages.append(f"โŒ {shadow_msg}")
os.unlink(temp_path)
# 4๋‹จ๊ณ„: ํ™”์งˆ ๊ฐœ์„  (์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ›„)
if upscale_quality:
temp_path = upload_image_to_temp_url(result_image)
if temp_path:
upscaled_img, upscale_msg = upscale_with_clarity(temp_path)
if upscaled_img:
result_image = upscaled_img
status_messages.append(f"โœ… {upscale_msg}")
else:
status_messages.append(f"โŒ {upscale_msg}")
os.unlink(temp_path)
# 5๋‹จ๊ณ„: ์ตœ์ข… ํฌ๊ธฐ ์กฐ์ •
result_image = result_image.resize((1000, 1000), Image.Resampling.LANCZOS)
status_messages.append("โœ… 1000x1000 ํฌ๊ธฐ ์กฐ์ • ์™„๋ฃŒ")
return result_image, "\n".join(status_messages)
except Exception as e:
return None, f"์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜: {str(e)}"
# Gradio ์ธํ„ฐํŽ˜์ด์Šค
def create_interface():
with gr.Blocks(title="์ฟ ํŒก ์ธ๋„ค์ผ ์ƒ์„ฑ๊ธฐ", theme=gr.themes.Soft()) as iface:
with gr.Row():
with gr.Column(scale=1):
# ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
input_image = gr.Image(
label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ",
type="pil",
height=400
)
# ์„ ํƒ ๊ธฐ๋Šฅ 2๊ฐ€์ง€
with gr.Group():
remove_bg = gr.Checkbox(
label="๋ฐฐ๊ฒฝ ์ œ๊ฑฐ",
value=True,
info="AI๋กœ ๋ฐฐ๊ฒฝ์„ ์ž๋™ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค"
)
upscale_quality = gr.Checkbox(
label="ํ™”์งˆ ๊ฐœ์„ ๊ธฐ",
value=True,
info="AI๋กœ ํ™”์งˆ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค"
)
# ์‹คํ–‰ ๋ฒ„ํŠผ
process_btn = gr.Button("๐Ÿš€ ์ธ๋„ค์ผ ์ƒ์„ฑ", variant="primary", size="lg")
with gr.Column(scale=1):
# ์ถœ๋ ฅ ์ด๋ฏธ์ง€
output_image = gr.Image(
label="์ฟ ํŒก ์ธ๋„ค์ผ ๊ฒฐ๊ณผ",
height=400
)
status_output = gr.Textbox(
label="์ฒ˜๋ฆฌ ์ƒํƒœ",
lines=6,
max_lines=10
)
# ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
process_btn.click(
process_image,
inputs=[input_image, remove_bg, upscale_quality],
outputs=[output_image, status_output]
)
return iface
# ์•ฑ ์‹คํ–‰
if __name__ == "__main__":
app = create_interface()
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=True,
show_error=True
)