Spaces:
Runtime error
Runtime error
Update app/services/image_service.py
Browse files- app/services/image_service.py +38 -28
app/services/image_service.py
CHANGED
|
@@ -12,27 +12,28 @@ from app.core.clients import llm, prompt_template, genai_client, flux_client, ge
|
|
| 12 |
|
| 13 |
logger = logging.getLogger(__name__)
|
| 14 |
|
| 15 |
-
# --- Virtual Try-On Instruction Template ---
|
| 16 |
VIRTUAL_TRY_ON_PROMPT = """
|
| 17 |
-
You are an expert image-editing agent. Perform a high-fidelity virtual try-on using
|
| 18 |
|
| 19 |
- Input 1 (dress reference): the exact garment image to be transferred.
|
| 20 |
- Input 2 (person): the target person who must wear the garment.
|
|
|
|
| 21 |
|
| 22 |
Positive instructions (Do):
|
| 23 |
-
1. Produce exactly one photorealistic output image showing the person wearing the dress from Input 1.
|
| 24 |
2. Preserve the person's face, facial features, expression, hair, gender, skin tone, and body proportions — do NOT change identity.
|
| 25 |
-
3. Reproduce the dress design, color, pattern, fabric texture, and major details (buttons, seams, prints) faithfully
|
| 26 |
-
4.
|
| 27 |
-
5.
|
| 28 |
6. Also return a short text JSON summary with the form: {"success": true|false, "notes": "explain any limitations or changes"}.
|
| 29 |
|
| 30 |
Negative instructions (Do NOT):
|
| 31 |
1. Do NOT modify the person's face, gender, or identifying features.
|
| 32 |
-
2. Do NOT change the dress color, pattern, or main texture.
|
| 33 |
3. Do NOT add extra clothing items, logos, watermarks, offensive symbols, or unrelated props.
|
| 34 |
4. Do NOT produce empty responses, placeholders, or images containing text overlays.
|
| 35 |
-
5. Do NOT blur, heavily distort, or crop important parts of the person or
|
| 36 |
|
| 37 |
Output requirements:
|
| 38 |
- Return a single photorealistic image (same orientation as the person image) and a short text JSON summary.
|
|
@@ -153,23 +154,43 @@ def update_image_with_text(text_instruction: str, image_bytes: bytes) -> tuple[O
|
|
| 153 |
|
| 154 |
|
| 155 |
# ===============================================================
|
| 156 |
-
# 🔹 VIRTUAL TRY-ON (DRESS + PERSON)
|
| 157 |
# ===============================================================
|
| 158 |
-
def virtual_try_on(
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
logger.info("Opening images for virtual try-on...")
|
| 161 |
|
| 162 |
try:
|
| 163 |
dress_image = Image.open(BytesIO(dress_image_bytes))
|
| 164 |
person_image = Image.open(BytesIO(person_image_bytes))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
except Exception:
|
| 166 |
raise ValueError("Invalid image data provided.")
|
| 167 |
|
| 168 |
try:
|
| 169 |
config = types.GenerateContentConfig(response_modalities=["Text", "Image"])
|
|
|
|
|
|
|
| 170 |
response = genai_client1.models.generate_content(
|
| 171 |
-
model="gemini-2.
|
| 172 |
-
contents=
|
| 173 |
config=config
|
| 174 |
)
|
| 175 |
|
|
@@ -190,23 +211,12 @@ def virtual_try_on(dress_image_bytes: bytes, person_image_bytes: bytes) -> tuple
|
|
| 190 |
return result_summary, result_image_bytes
|
| 191 |
|
| 192 |
except Exception as e:
|
| 193 |
-
logger.warning(f"Gemini try-on failed: {e}
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
# prompt = "Photorealistic virtual try-on of a person wearing the given dress."
|
| 197 |
-
# image = flux_client.text_to_image(
|
| 198 |
-
# prompt,
|
| 199 |
-
# model="black-forest-labs/FLUX.1-dev"
|
| 200 |
-
# )
|
| 201 |
-
# buf = BytesIO()
|
| 202 |
-
# image.save(buf, format="PNG")
|
| 203 |
-
# buf.seek(0)
|
| 204 |
-
# return {"success": True, "notes": "Generated using Flux fallback."}, buf
|
| 205 |
-
# except Exception as flux_error:
|
| 206 |
-
# logger.error(f"Flux fallback failed: {flux_error}", exc_info=True)
|
| 207 |
-
# raise
|
| 208 |
|
| 209 |
|
|
|
|
| 210 |
# ===============================================================
|
| 211 |
# 🔹 SHOE IMAGE GENERATION
|
| 212 |
# ===============================================================
|
|
|
|
| 12 |
|
| 13 |
logger = logging.getLogger(__name__)
|
| 14 |
|
| 15 |
+
# --- Virtual Try-On Instruction Template (Updated for 3 Inputs) ---
|
| 16 |
VIRTUAL_TRY_ON_PROMPT = """
|
| 17 |
+
You are an expert image-editing agent. Perform a high-fidelity virtual try-on using three inputs:
|
| 18 |
|
| 19 |
- Input 1 (dress reference): the exact garment image to be transferred.
|
| 20 |
- Input 2 (person): the target person who must wear the garment.
|
| 21 |
+
- Input 3 (shoes reference): the footwear to be worn.
|
| 22 |
|
| 23 |
Positive instructions (Do):
|
| 24 |
+
1. Produce exactly one photorealistic output image showing the person from Input 2 wearing BOTH the dress from Input 1 and the shoes from Input 3.
|
| 25 |
2. Preserve the person's face, facial features, expression, hair, gender, skin tone, and body proportions — do NOT change identity.
|
| 26 |
+
3. Reproduce the dress design, color, pattern, fabric texture, and major details (buttons, seams, prints) faithfully.
|
| 27 |
+
4. Reproduce the shoes faithfully and ensure they fit the person's stance naturally (grounding, shadows).
|
| 28 |
+
5. Match lighting, shadows, perspective, and scale so all items appear naturally worn by the person in the original scene.
|
| 29 |
6. Also return a short text JSON summary with the form: {"success": true|false, "notes": "explain any limitations or changes"}.
|
| 30 |
|
| 31 |
Negative instructions (Do NOT):
|
| 32 |
1. Do NOT modify the person's face, gender, or identifying features.
|
| 33 |
+
2. Do NOT change the dress/shoe color, pattern, or main texture.
|
| 34 |
3. Do NOT add extra clothing items, logos, watermarks, offensive symbols, or unrelated props.
|
| 35 |
4. Do NOT produce empty responses, placeholders, or images containing text overlays.
|
| 36 |
+
5. Do NOT blur, heavily distort, or crop important parts of the person, dress, or shoes.
|
| 37 |
|
| 38 |
Output requirements:
|
| 39 |
- Return a single photorealistic image (same orientation as the person image) and a short text JSON summary.
|
|
|
|
| 154 |
|
| 155 |
|
| 156 |
# ===============================================================
|
| 157 |
+
# 🔹 VIRTUAL TRY-ON (DRESS + PERSON + SHOES)
|
| 158 |
# ===============================================================
|
| 159 |
+
def virtual_try_on(
|
| 160 |
+
dress_image_bytes: bytes,
|
| 161 |
+
person_image_bytes: bytes,
|
| 162 |
+
shoes_image_bytes: Optional[bytes] = None
|
| 163 |
+
) -> tuple[Dict[str, Any], Optional[BytesIO]]:
|
| 164 |
+
"""Perform virtual try-on with Gemini (Supports optional shoes)."""
|
| 165 |
logger.info("Opening images for virtual try-on...")
|
| 166 |
|
| 167 |
try:
|
| 168 |
dress_image = Image.open(BytesIO(dress_image_bytes))
|
| 169 |
person_image = Image.open(BytesIO(person_image_bytes))
|
| 170 |
+
|
| 171 |
+
# Prepare content list with mandatory items
|
| 172 |
+
contents = [VIRTUAL_TRY_ON_PROMPT, dress_image, person_image]
|
| 173 |
+
|
| 174 |
+
# Handle optional shoes
|
| 175 |
+
if shoes_image_bytes:
|
| 176 |
+
shoes_image = Image.open(BytesIO(shoes_image_bytes))
|
| 177 |
+
contents.append(shoes_image) # Appends as Input 3
|
| 178 |
+
else:
|
| 179 |
+
# If no shoes provided, you might want to append a text note
|
| 180 |
+
# telling the model to ignore Input 3 instructions,
|
| 181 |
+
# or simply rely on the model's flexibility.
|
| 182 |
+
pass
|
| 183 |
+
|
| 184 |
except Exception:
|
| 185 |
raise ValueError("Invalid image data provided.")
|
| 186 |
|
| 187 |
try:
|
| 188 |
config = types.GenerateContentConfig(response_modalities=["Text", "Image"])
|
| 189 |
+
|
| 190 |
+
# Make the API call with all collected contents
|
| 191 |
response = genai_client1.models.generate_content(
|
| 192 |
+
model="gemini-2.0-flash-exp", # Ensure this model supports image gen
|
| 193 |
+
contents=contents,
|
| 194 |
config=config
|
| 195 |
)
|
| 196 |
|
|
|
|
| 211 |
return result_summary, result_image_bytes
|
| 212 |
|
| 213 |
except Exception as e:
|
| 214 |
+
logger.warning(f"Gemini try-on failed: {e}")
|
| 215 |
+
# Re-raise or handle fallback logic here
|
| 216 |
+
raise HTTPException(status_code=500, detail=f"Model generation failed: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
| 218 |
|
| 219 |
+
|
| 220 |
# ===============================================================
|
| 221 |
# 🔹 SHOE IMAGE GENERATION
|
| 222 |
# ===============================================================
|