File size: 15,996 Bytes
b4f5a78 388d5bc b4f5a78 388d5bc b4f5a78 61b020a f2fd5c3 61b020a f2fd5c3 61b020a b4f5a78 4793701 b4f5a78 47d6259 921b7e8 92cd85a 47d6259 92cd85a 47d6259 92cd85a 47d6259 92cd85a 47d6259 92cd85a 921b7e8 92cd85a f2fd5c3 92cd85a 4793701 92cd85a 921b7e8 43601cf b4f5a78 4793701 b4f5a78 92be696 5793d5f f2fd5c3 92be696 92cd85a 43601cf 921b7e8 92cd85a d8bd03e faa6b2a 6959787 faa6b2a 6959787 faa6b2a 388d5bc 43601cf 8c4b0db 43601cf 8c4b0db 43601cf 8c4b0db 43601cf 8c4b0db f2fd5c3 92cd85a f2fd5c3 61b020a f2fd5c3 92cd85a f2fd5c3 92cd85a f2fd5c3 61b020a f2fd5c3 92cd85a f2fd5c3 61b020a f2fd5c3 92cd85a f2fd5c3 61b020a f2fd5c3 92cd85a f2fd5c3 92cd85a f2fd5c3 61b020a f2fd5c3 92cd85a 336f8ae 8c4b0db 5ee2d8f e2935c8 07327dc 43601cf 8c4b0db 43601cf 8c4b0db 92cd85a f2fd5c3 92cd85a 5793d5f f2fd5c3 5793d5f 92cd85a f2fd5c3 3bfcb97 5793d5f 4793701 5793d5f 92cd85a 5793d5f 5ee2d8f 8c4b0db 43601cf 5793d5f ebbb2ff 5793d5f f2fd5c3 92cd85a f2fd5c3 92cd85a 8c4b0db ebbb2ff 8c4b0db 43601cf faa6b2a ac8c029 ebbb2ff |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
import gradio as gr
import google.generativeai as genai
from PIL import Image
import os
import json
# Gemini API ν€ μ€μ (νκ²½ λ³μμμ κ°μ Έμ€κ±°λ μ§μ μ
λ ₯)
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
# Gemini API μ΄κΈ°ν
genai.configure(api_key=GEMINI_API_KEY)
# λ°°κ²½ JSON νμΌ κ²½λ‘ μ€μ
BACKGROUNDS_DIR = os.path.join(os.path.dirname(__file__), "background")
# JSON νμΌμ΄ μ‘΄μ¬νμ§ μμ κ²½μ° λλ ν 리 μμ±
if not os.path.exists(BACKGROUNDS_DIR):
os.makedirs(BACKGROUNDS_DIR)
# JSON νμΌ λ‘λ ν¨μ
def load_background_json(filename):
file_path = os.path.join(BACKGROUNDS_DIR, filename)
try:
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
print(f"κ²½κ³ : {filename} νμΌμ μ°Ύμ μ μμ΅λλ€. κΈ°λ³Έκ°μ μ¬μ©ν©λλ€.")
return {}
# λ°°κ²½ λ°μ΄ν° λ‘λ
SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
def generate_system_instruction():
return """λΉμ μ μν μ΄λ―Έμ§μ λ°°κ²½μ λ³κ²½νκΈ° μν κ³ νμ§ ν둬ννΈλ₯Ό μμ±νλ μ λ¬Έκ°μ
λλ€.
μ¬μ©μκ° μ 곡νλ μνλͺ
, λ°°κ²½ μ ν, μΆκ° μμ²μ¬νμ λ°νμΌλ‘ λ―Έλμ λ(Midjourney)μ μ¬μ©ν μ μλ
μμΈνκ³ μ λ¬Έμ μΈ ν둬ννΈλ₯Ό μμ΄λ‘ μμ±ν΄μ£ΌμΈμ.
λ€μ κ°μ΄λλΌμΈμ λ°λμ λ°λΌμΌ ν©λλ€:
1. μνμ "#1"λ‘ μ§μ νμ¬ μ°Έμ‘°ν©λλ€. (μ: "skincare tube (#1)")
2. *** λ§€μ° μ€μ: μνμ μλ νΉμ±(λμμΈ, μμ, νν, λ‘κ³ , ν¨ν€μ§ λ±)μ μ΄λ€ μν©μμλ μ λ λ³κ²½νμ§ μμ΅λλ€. ***
3. *** μνμ λ³Έμ§μ νΉμ±μ μ μ§νλ, μμ°μ€λ¬μ΄ νκ²½ ν΅ν©μ μν μ‘°λͺ
κ³Ό κ·Έλ¦Όμλ νμ©ν©λλ€: ***
- μν μ체μ μμ, λμμΈ, νν, ν
μ€μ²λ μ λ μμ νμ§ μμ΅λλ€.
- νκ²½κ³Ό μμ°μ€λ½κ² μ΄μΈλ¦¬λ κ·Έλ¦Όμ, μ£Όλ³ μ‘°λͺ
ν¨κ³Όλ νμ©λ©λλ€.
- μνμ λ¬Όλ°©μΈ, μμΆ, κΈ, μκ³Ό κ°μ μΆκ° μμλ 물리μ ν¨κ³Όλ μ μ©νμ§ μμ΅λλ€.
- νκ²½μ μ΄μΈλ¦¬λ μμ°μ€λ¬μ΄ λΉ λ°μ¬, μ£Όλ³ μ‘°λͺ
, κ·Έλ¦Όμλ μ¬μ€μ ν΅ν©κ°μ μν΄ μ μ©ν μ μμ΅λλ€.
4. μ΄λ―Έμ§ λΉμ¨μ μ νν 1:1(μ μ¬κ°ν) νμμΌλ‘ μ§μ ν©λλ€. ν둬ννΈμ "square format", "1:1 ratio" λλ "aspect ratio 1:1"μ λͺ
μμ μΌλ‘ ν¬ν¨ν©λλ€.
5. μνμ λ°λμ μ μ¬κ°ν ꡬλμ μ μ€μμ λ°°μΉλμ΄μΌ ν©λλ€.
6. μνμ μ΄λ―Έμ§μ μ£Όμ μ΄μ μΌλ‘ λΆκ°μν€κ³ , μνμ λΉμ¨μ΄ μ 체 μ΄λ―Έμ§μμ ν¬κ² μ°¨μ§νλλ‘ ν©λλ€.
7. μν μ΄λ―Έμ§ μ»·μμ(#1)μ κΈ°λ³Έ ννμ μμμ μ μ§νλ©΄μ, μ νν νκ²½μ μμ°μ€λ½κ² ν΅ν©λλλ‘ ν©λλ€.
8. κ³ κΈμ€λ¬μ΄ μμ
μ μ΄λ―Έμ§λ₯Ό μν λ€μ νκ²½ μμλ€μ ν¬ν¨νμΈμ:
- μνκ³Ό μ΄μΈλ¦¬λ μ£Όλ³ νκ²½/λ°°κ²½ μμλ₯Ό μΆκ°ν©λλ€. μλ₯Ό λ€μ΄, νμ₯ν μ£Όλ³μ κ½μ΄λ νλΈ, μλ£ μ ν μμ κ³ΌμΌ, μ μμ ν κ·Όμ²μ νλμ μν λ±.
- νκ²½μ μ‘°λͺ
ν¨κ³Ό(λ¦Ό λΌμ΄νΈ, λ°±λΌμ΄νΈ, μννΈλ°μ€ λ±)λ₯Ό μ€λͺ
ν©λλ€.
- μνμ΄ νκ²½μ μμ°μ€λ½κ² μ‘΄μ¬νλ κ²μ²λΌ 보μ΄λλ‘ μ μ ν κ·Έλ¦Όμμ λΉ ννμ ν¬ν¨ν©λλ€.
- μνμ μ©λλ μ₯μ μ κ°μ μ μΌλ‘ μμνλ λ°°κ²½ μμλ₯Ό ν¬ν¨ν©λλ€.
- νλ‘νμ
λν μμ
μ¬μ§ ν¨κ³Ό(μ νμ νΌμ¬κ³ μ¬λ, μννΈ ν¬μ»€μ€, μ€νλμ€ μ‘°λͺ
λ±)λ₯Ό λͺ
μν©λλ€.
9. ν둬ννΈμ λ€μ μμλ€μ λͺ
μμ μΌλ‘ ν¬ν¨νμΈμ:
- "highly detailed commercial photography"
- "award-winning product photography"
- "professional advertising imagery"
- "studio quality"
- "magazine advertisement quality"
10. λ°°κ²½ νκ²½ μμλ₯Ό μν μΉ΄ν
κ³ λ¦¬μ λ§κ² μ νν©λλ€:
- μ€ν¨μΌμ΄ μ ν: κΉ¨λν μμ€ μ λ°, μ°μν νμ₯λ, μ€ν κ°μ νκ²½ λ±
- μλ£ μ ν: μΈλ ¨λ ν
μ΄λΈ, νν° νκ²½, μΌμΈ νΌν¬λ μ₯λ©΄ λ±
- μ μ μ ν: μΈλ ¨λ μμ
곡κ°, νλμ μΈ κ±°μ€, λ―Έλλ©ν μ±
μ λ±
- ν¨μ
/μλ₯: μΈλ ¨λ μΌλ£Έ, λμ 거리, μλ κ°μ€ν λΌμ΄νμ€νμΌ νκ²½ λ±
- μν μ ν: κΉλν μ£Όλ°©, μν, μ리 νκ²½ λ±
11. μ¬μ©μκ° μ 곡ν ꡬ체μ μΈ λ°°κ²½κ³Ό μΆκ° μμ²μ¬νμ μ νν λ°μν©λλ€.
12. ν둬ννΈλ λ―Έλμ λ AIμ μ΅μ νλμ΄μΌ ν©λλ€.
13. ν둬ννΈ λμ "--ar 1:1 --s 750 --q 2" νλΌλ―Έν°λ₯Ό μΆκ°νμ¬ λ―Έλμ λμμ κ³ νμ§ μ μ¬κ°ν λΉμ¨μ κ°μ ν©λλ€.
μΆλ ₯ νμμ μμ΄λ‘ λ λ¨μΌ λ¨λ½μ μμΈν ν둬ννΈμ¬μΌ νλ©°, λμ λ―Έλμ λ νλΌλ―Έν°κ° ν¬ν¨λμ΄μΌ ν©λλ€.
"""
def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
if not GEMINI_API_KEY:
return "Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€. νκ²½ λ³μ GEMINI_API_KEYλ₯Ό μ€μ νκ±°λ μ½λμ μ§μ μ
λ ₯νμΈμ."
try:
prompt_request = f"""
μνλͺ
: {product_name}
λ°°κ²½ μ ν: {background_info.get('english', 'studio')}
λ°°κ²½ μΉ΄ν
κ³ λ¦¬: {background_info.get('category', '')}
λ°°κ²½ μ΄λ¦: {background_info.get('name', '')}
μΆκ° μμ²μ¬ν: {additional_info}
μ€μ μꡬμ¬ν:
1. μνμ΄ ν¬κ² λΆκ°λκ³ μ΄λ―Έμ§μμ μ€μ¬μ μΈ μμΉλ₯Ό μ°¨μ§νλλ‘ ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ.
2. μ΄λ―Έμ§λ μ νν 1:1 λΉμ¨(μ μ¬κ°ν)μ΄μ΄μΌ ν©λλ€.
3. μνμ μ μ¬κ°ν νλ μμ μ μ€μμ μμΉν΄μΌ ν©λλ€.
4. μνμ λμμΈ, μμ, νν, λ‘κ³ λ± λ³Έμ§μ νΉμ±μ μ λ μμ νμ§ λ§μΈμ.
5. νκ²½κ³Όμ μμ°μ€λ¬μ΄ ν΅ν©μ μν μ‘°λͺ
ν¨κ³Όμ κ·Έλ¦Όμλ ν¬ν¨ν΄μ£ΌμΈμ.
6. μνμ λ λ보μ΄κ² νλ λ°°κ²½ νκ²½μ μ€λͺ
ν΄μ£ΌμΈμ.
7. κ³ κΈμ€λ¬μ΄ μμ
κ΄κ³ νμ§μ μ΄λ―Έμ§κ° λλλ‘ νκ²½ μ€λͺ
μ ν΄μ£ΌμΈμ.
8. ν둬ννΈ λμ λ―Έλμ λ νλΌλ―Έν° "--ar 1:1 --s 750 --q 2"λ₯Ό μΆκ°ν΄μ£ΌμΈμ.
νκ΅μ΄ μ
λ ₯ λ΄μ©μ μμ΄λ‘ μ μ ν λ²μνμ¬ λ°μν΄μ£ΌμΈμ.
"""
model = genai.GenerativeModel(
'gemini-2.0-flash',
system_instruction=generate_system_instruction()
)
response = model.generate_content(
prompt_request,
generation_config=genai.types.GenerationConfig(
temperature=0.7,
top_p=0.95,
top_k=64,
max_output_tokens=1024,
)
)
response_text = response.text.strip()
if "--ar 1:1" not in response_text:
response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2"
return response_text
except Exception as e:
return f"ν둬ννΈ μμ± μ€ μ€λ₯κ° λ°μνμ΅λλ€: {str(e)}"
def create_app():
with gr.Blocks(title="κ³ κΈ μν μ΄λ―Έμ§ λ°°κ²½ ν둬ννΈ μμ±κΈ°") as demo:
gr.Markdown("# κ³ κΈ μν μ΄λ―Έμ§ λ°°κ²½ ν둬ννΈ μμ±κΈ°")
gr.Markdown("μν μ΄λ―Έμ§λ₯Ό μ
λ‘λνκ³ μ΅μ
μ μ ννλ©΄ κ³ νμ§ μμ
μ© ν둬ννΈκ° μμ±λ©λλ€.")
# μνλͺ
μΉμ
with gr.Row():
product_name = gr.Textbox(label="μνλͺ
(νκ΅μ΄ μ
λ ₯)", placeholder="μ: μ€ν¨μΌμ΄ νλΈ, ν
λΈλ¬ λ±", interactive=True)
with gr.Row():
# μ’μΈ‘ μ»¬λΌ - μ
λ ₯ 컨νΈλ‘€
with gr.Column(scale=1):
image_input = gr.Image(label="μν μ΄λ―Έμ§ μ
λ‘λ", type="pil")
# λ°°κ²½ νμ
ν (μ¬ν, μ€νλμ€, μμ°, μ€λ΄, μΆμ)
gr.Markdown("## λ°°κ²½ μ ν (ν κ°μ§λ§ μ ν)")
with gr.Tabs() as background_tabs:
with gr.TabItem("μ¬ν λ°°κ²½"):
simple_dropdown = gr.Dropdown(
choices=list(SIMPLE_BACKGROUNDS.keys()),
value=list(SIMPLE_BACKGROUNDS.keys())[0] if SIMPLE_BACKGROUNDS else None,
label="μ¬ν λ°°κ²½ μ ν",
interactive=True
)
with gr.TabItem("μ€νλμ€ λ°°κ²½"):
studio_dropdown = gr.Dropdown(
choices=list(STUDIO_BACKGROUNDS.keys()),
value=list(STUDIO_BACKGROUNDS.keys())[0] if STUDIO_BACKGROUNDS else None,
label="μ€νλμ€ λ°°κ²½ μ ν",
interactive=True
)
with gr.TabItem("μμ° νκ²½"):
nature_dropdown = gr.Dropdown(
choices=list(NATURE_BACKGROUNDS.keys()),
value=list(NATURE_BACKGROUNDS.keys())[0] if NATURE_BACKGROUNDS else None,
label="μμ° νκ²½ μ ν",
interactive=True
)
with gr.TabItem("μ€λ΄ νκ²½"):
indoor_dropdown = gr.Dropdown(
choices=list(INDOOR_BACKGROUNDS.keys()),
value=list(INDOOR_BACKGROUNDS.keys())[0] if INDOOR_BACKGROUNDS else None,
label="μ€λ΄ νκ²½ μ ν",
interactive=True
)
with gr.TabItem("μΆμ/νΉμ λ°°κ²½"):
abstract_dropdown = gr.Dropdown(
choices=list(ABSTRACT_BACKGROUNDS.keys()),
value=list(ABSTRACT_BACKGROUNDS.keys())[0] if ABSTRACT_BACKGROUNDS else None,
label="μΆμ/νΉμ λ°°κ²½ μ ν",
interactive=True
)
# μΆκ° μμ²μ¬ν
additional_info = gr.Textbox(
label="μΆκ° μμ²μ¬ν (μ νμ¬ν)",
placeholder="μ: κ³ κΈμ€λ¬μ΄ λλ, λ°μ μ‘°λͺ
λ±",
lines=3,
interactive=True
)
submit_btn = gr.Button("ν둬ννΈ μμ±", variant="primary")
# μ°μΈ‘ μ»¬λΌ - μΆλ ₯ κ²°κ³Ό
with gr.Column(scale=1):
prompt_output = gr.Textbox(label="μμ±λ ν둬ννΈ", lines=10)
image_preview = gr.Image(label="μ
λ‘λλ μ΄λ―Έμ§ (#1)", type="pil")
preview_html = gr.HTML("ν둬ννΈ μμ± μ μ¬κΈ°μ λ―Έλ¦¬λ³΄κΈ°κ° νμλ©λλ€.")
# μ νλ λ°°κ²½ μ 보 κ°μ Έμ€κΈ°
def get_selected_background_info(active_tab, simple, studio, nature, indoor, abstract):
if active_tab == "μ¬ν λ°°κ²½" and simple:
return {
"category": "μ¬ν λ°°κ²½",
"name": simple,
"english": SIMPLE_BACKGROUNDS.get(simple, "white background")
}
elif active_tab == "μ€νλμ€ λ°°κ²½" and studio:
return {
"category": "μ€νλμ€ λ°°κ²½",
"name": studio,
"english": STUDIO_BACKGROUNDS.get(studio, "product photography studio")
}
elif active_tab == "μμ° νκ²½" and nature:
return {
"category": "μμ° νκ²½",
"name": nature,
"english": NATURE_BACKGROUNDS.get(nature, "natural environment")
}
elif active_tab == "μ€λ΄ νκ²½" and indoor:
return {
"category": "μ€λ΄ νκ²½",
"name": indoor,
"english": INDOOR_BACKGROUNDS.get(indoor, "indoor environment")
}
elif active_tab == "μΆμ/νΉμ λ°°κ²½" and abstract:
return {
"category": "μΆμ/νΉμ λ°°κ²½",
"name": abstract,
"english": ABSTRACT_BACKGROUNDS.get(abstract, "abstract background")
}
else:
return {
"category": "κΈ°λ³Έ λ°°κ²½",
"name": "νμ΄νΈ λ°°κ²½",
"english": "white background"
}
# ν둬ννΈ μμ± ν¨μ
def generate_output(image, active_tab, simple, studio, nature, indoor, abstract, product_text, additional_text):
if image is None:
gr.Warning("μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ.")
return "μ΄λ―Έμ§λ₯Ό μ
λ‘λν΄μ£ΌμΈμ.", None, "μ΄λ―Έμ§λ₯Ό μ
λ‘λ ν ν둬ννΈλ₯Ό μμ±ν΄μ£ΌμΈμ."
product_text = product_text.strip() or "μ ν"
# λ°°κ²½ μ 보 κ°μ Έμ€κΈ°
background_info = get_selected_background_info(active_tab, simple, studio, nature, indoor, abstract)
try:
prompt = generate_prompt_with_gemini(product_text, background_info, additional_text)
if not GEMINI_API_KEY:
gr.Warning("Gemini API ν€κ° μ€μ λμ§ μμμ΅λλ€. ν€λ₯Ό λ°κΈλ°μ μ€μ ν΄μ£ΌμΈμ.")
prompt = """
[Gemini API ν€ λλ½]
API ν€ μ€μ λ°©λ²:
1. νκ²½ λ³μ: export GEMINI_API_KEY="your-api-key"
2. μ½λ λ΄ μ§μ μ
λ ₯: GEMINI_API_KEY = "your-api-key"
ν€ λ°κΈ: https://makersuite.google.com/
"""
return prompt, image, "API ν€λ₯Ό μ€μ ν΄μΌ ν©λλ€."
# ν둬ννΈ μμ½ HTML μμ±
preview = f"""
<div style="padding:10px; border:1px solid #ddd; border-radius:8px; margin-top:10px;">
<h3>ν둬ννΈ μμ½</h3>
<p><strong>μ΄ κΈΈμ΄:</strong> {len(prompt)} κΈμ</p>
<p><strong>λ°°κ²½:</strong> {background_info['category']} > {background_info['name']}</p>
<p><strong>μ£Όμ μμ:</strong> {", ".join([kw for kw in ["commercial photography", "product", "square format", "centered", "detailed"] if kw.lower() in prompt.lower()])}</p>
<p><strong>λ―Έλμ λ νλΌλ―Έν°:</strong> {" ".join([param for param in ["--ar 1:1", "--s 750", "--q 2"] if param in prompt])}</p>
</div>
"""
return prompt, image, preview
except Exception as e:
error_msg = f"ν둬ννΈ μμ± μ€ μ€λ₯ λ°μ: {str(e)}"
gr.Error(error_msg)
return error_msg, image, "μ€λ₯κ° λ°μνμ΅λλ€."
# ν둬ννΈ μμ± λ²νΌ ν΄λ¦ μ΄λ²€νΈ
submit_btn.click(
fn=generate_output,
inputs=[
image_input,
background_tabs,
simple_dropdown,
studio_dropdown,
nature_dropdown,
indoor_dropdown,
abstract_dropdown,
product_name,
additional_info
],
outputs=[
prompt_output,
image_preview,
preview_html
]
)
return demo
if __name__ == "__main__":
app = create_app()
app.launch() |