Spaces:
Paused
Paused
Ali Mohsin
commited on
Commit
Β·
7669ee7
1
Parent(s):
1f07471
Update category mappings and enhance outfit templates for better filtering and accuracy
Browse files- inference.py +112 -43
inference.py
CHANGED
|
@@ -132,7 +132,7 @@ class InferenceService:
|
|
| 132 |
2: "shoes", # shoes, sneakers, boots, footwear
|
| 133 |
3: "jacket", # jacket, blazer, coat, outerwear
|
| 134 |
4: "dress", # dress, gown
|
| 135 |
-
5: "
|
| 136 |
6: "shirt", # sweater, hoodie, pullover (map to shirt)
|
| 137 |
7: "accessory", # watch, ring, necklace, jewelry
|
| 138 |
8: "accessory", # bag, purse, handbag
|
|
@@ -140,7 +140,7 @@ class InferenceService:
|
|
| 140 |
10: "accessory", # belt, accessory
|
| 141 |
11: "kameez", # kameez, kurta, traditional Pakistani shirt
|
| 142 |
12: "shalwar", # shalwar, traditional Pakistani pants
|
| 143 |
-
13: "
|
| 144 |
}
|
| 145 |
|
| 146 |
predicted_category = category_map.get(indices[0].item(), "other")
|
|
@@ -160,20 +160,46 @@ class InferenceService:
|
|
| 160 |
|
| 161 |
filename_lower = filename.lower()
|
| 162 |
|
| 163 |
-
#
|
| 164 |
-
if any(kw in filename_lower for kw in ["
|
| 165 |
-
return "
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
if any(kw in filename_lower for kw in ["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
return "pants"
|
| 170 |
-
|
| 171 |
-
#
|
| 172 |
-
if any(kw in filename_lower for kw in ["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
return "shoes"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
# Accessories
|
| 176 |
-
if any(kw in filename_lower for kw in ["watch", "ring", "necklace", "bracelet", "bag", "hat", "belt", "scarf"]):
|
| 177 |
return "accessory"
|
| 178 |
|
| 179 |
# Default fallback
|
|
@@ -434,80 +460,85 @@ class InferenceService:
|
|
| 434 |
outfit_templates = {
|
| 435 |
"casual": {
|
| 436 |
"style": "relaxed, comfortable, everyday",
|
| 437 |
-
"preferred_categories": ["tshirt", "jean", "sneaker", "hoodie", "sweatpant", "shirt", "pants", "shoes"],
|
|
|
|
| 438 |
"color_palette": ["neutral", "denim", "white", "black", "gray"],
|
| 439 |
"accessory_limit": 2,
|
| 440 |
"weather_modifiers": {
|
| 441 |
-
"hot": {"preferred_categories": ["tank", "
|
| 442 |
-
"cold": {"preferred_categories": ["hoodie", "sweater", "jacket", "
|
| 443 |
-
"rain": {"preferred_categories": ["jacket", "
|
| 444 |
},
|
| 445 |
"occasion_modifiers": {
|
| 446 |
-
"business": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 3},
|
| 447 |
-
"formal": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 4}
|
| 448 |
}
|
| 449 |
},
|
| 450 |
"smart_casual": {
|
| 451 |
"style": "polished but relaxed, business casual",
|
| 452 |
-
"preferred_categories": ["shirt", "chino", "loafer", "blazer", "polo", "pants", "shoes"],
|
|
|
|
| 453 |
"color_palette": ["navy", "white", "khaki", "brown", "gray"],
|
| 454 |
"accessory_limit": 3,
|
| 455 |
"weather_modifiers": {
|
| 456 |
-
"hot": {"preferred_categories": ["polo", "light shirt", "loafer"]},
|
| 457 |
-
"cold": {"preferred_categories": ["blazer", "sweater", "
|
| 458 |
-
"rain": {"preferred_categories": ["blazer", "
|
| 459 |
},
|
| 460 |
"occasion_modifiers": {
|
| 461 |
-
"business": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 4},
|
| 462 |
-
"formal": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 4}
|
| 463 |
}
|
| 464 |
},
|
| 465 |
"formal": {
|
| 466 |
"style": "professional, elegant, sophisticated",
|
| 467 |
-
"preferred_categories": ["blazer", "jacket", "suit jacket", "dress shirt", "dress pant", "oxford", "suit", "shirt", "pants", "shoes"],
|
|
|
|
| 468 |
"color_palette": ["navy", "black", "white", "gray", "charcoal"],
|
| 469 |
"accessory_limit": 4,
|
| 470 |
"requires_outerwear": True, # Flag to indicate formal outfits should include jackets
|
| 471 |
"weather_modifiers": {
|
| 472 |
"hot": {"preferred_categories": ["light shirt", "light pant", "oxford"], "requires_outerwear": False},
|
| 473 |
-
"cold": {"preferred_categories": ["blazer", "suit", "
|
| 474 |
-
"rain": {"preferred_categories": ["blazer", "
|
| 475 |
},
|
| 476 |
"occasion_modifiers": {
|
| 477 |
-
"business": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 4, "requires_outerwear": True},
|
| 478 |
-
"casual": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 3, "requires_outerwear": False}
|
| 479 |
}
|
| 480 |
},
|
| 481 |
"sporty": {
|
| 482 |
"style": "athletic, active, performance",
|
| 483 |
-
"preferred_categories": ["athletic shirt", "jogger", "running shoe", "tank", "legging", "shirt", "pants", "shoes"],
|
|
|
|
| 484 |
"color_palette": ["bright", "neon", "white", "black", "primary colors"],
|
| 485 |
"accessory_limit": 1,
|
| 486 |
"weather_modifiers": {
|
| 487 |
-
"hot": {"preferred_categories": ["tank", "
|
| 488 |
"cold": {"preferred_categories": ["hoodie", "legging", "running shoe"]},
|
| 489 |
"rain": {"preferred_categories": ["jacket", "running shoe", "cap"]}
|
| 490 |
},
|
| 491 |
"occasion_modifiers": {
|
| 492 |
-
"business": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 2},
|
| 493 |
-
"formal": {"preferred_categories": ["shirt", "pants", "shoes"], "accessory_limit": 3}
|
| 494 |
}
|
| 495 |
},
|
| 496 |
"traditional": {
|
| 497 |
"style": "Pakistani traditional, cultural, ethnic",
|
| 498 |
-
"preferred_categories": ["kameez", "kurta", "shalwar", "peshawari", "chappal", "traditional", "ethnic"],
|
|
|
|
| 499 |
"color_palette": ["white", "black", "navy", "maroon", "gold", "green", "traditional colors"],
|
| 500 |
"accessory_limit": 3,
|
| 501 |
"requires_traditional": True, # Flag for traditional outfit combinations
|
| 502 |
"weather_modifiers": {
|
| 503 |
-
"hot": {"preferred_categories": ["light kameez", "cotton shalwar", "peshawari chappal"]},
|
| 504 |
-
"cold": {"preferred_categories": ["warm kameez", "thick shalwar", "traditional boots"]},
|
| 505 |
"rain": {"preferred_categories": ["waterproof kameez", "shalwar", "traditional boots"]}
|
| 506 |
},
|
| 507 |
"occasion_modifiers": {
|
| 508 |
-
"business": {"preferred_categories": ["formal kameez", "shalwar", "peshawari"], "accessory_limit": 2},
|
| 509 |
-
"formal": {"preferred_categories": ["elegant kameez", "shalwar", "peshawari"], "accessory_limit": 3},
|
| 510 |
-
"casual": {"preferred_categories": ["casual kameez", "shalwar", "chappal"], "accessory_limit": 2}
|
| 511 |
}
|
| 512 |
}
|
| 513 |
}
|
|
@@ -545,10 +576,16 @@ class InferenceService:
|
|
| 545 |
if constraints.get("requires_outerwear"):
|
| 546 |
template["requires_outerwear"] = constraints["requires_outerwear"]
|
| 547 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 548 |
# Apply weather modifications
|
| 549 |
if weather != "any" and weather in template.get("weather_modifiers", {}):
|
| 550 |
weather_mod = template["weather_modifiers"][weather]
|
| 551 |
template["preferred_categories"].extend(weather_mod.get("preferred_categories", []))
|
|
|
|
|
|
|
| 552 |
if "accessory_limit" in weather_mod:
|
| 553 |
template["accessory_limit"] = weather_mod["accessory_limit"]
|
| 554 |
|
|
@@ -556,11 +593,14 @@ class InferenceService:
|
|
| 556 |
if occasion in template.get("occasion_modifiers", {}):
|
| 557 |
occasion_mod = template["occasion_modifiers"][occasion]
|
| 558 |
template["preferred_categories"].extend(occasion_mod.get("preferred_categories", []))
|
|
|
|
|
|
|
| 559 |
if "accessory_limit" in occasion_mod:
|
| 560 |
template["accessory_limit"] = occasion_mod["accessory_limit"]
|
| 561 |
|
| 562 |
# Remove duplicates and add context info
|
| 563 |
template["preferred_categories"] = list(set(template["preferred_categories"]))
|
|
|
|
| 564 |
template["context"] = {
|
| 565 |
"occasion": occasion,
|
| 566 |
"weather": weather,
|
|
@@ -572,6 +612,7 @@ class InferenceService:
|
|
| 572 |
|
| 573 |
print(f"π DEBUG: Using template '{template_name}' with context: occasion={occasion}, weather={weather}")
|
| 574 |
print(f"π DEBUG: Template categories: {template['preferred_categories']}")
|
|
|
|
| 575 |
print(f"π DEBUG: Accessory limit: {template['accessory_limit']}")
|
| 576 |
|
| 577 |
# Enhanced category-aware pools with diversity checks
|
|
@@ -765,7 +806,7 @@ class InferenceService:
|
|
| 765 |
def get_category_type(cat: str) -> str:
|
| 766 |
"""Map category to outfit slot type with comprehensive taxonomy"""
|
| 767 |
cat_lower = cat.lower().strip()
|
| 768 |
-
print(f"π DEBUG: Mapping category '{cat}' -> '{cat_lower}'")
|
| 769 |
|
| 770 |
# Direct mapping for CLIP-detected categories
|
| 771 |
if cat_lower == "shirt":
|
|
@@ -784,6 +825,16 @@ class InferenceService:
|
|
| 784 |
return "bottom" # Shalwar is bottom wear
|
| 785 |
elif cat_lower == "peshawari":
|
| 786 |
return "shoe" # Peshawari chappal is footwear
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 787 |
|
| 788 |
# Upper body items (tops, innerwear)
|
| 789 |
upper_keywords = [
|
|
@@ -1135,8 +1186,15 @@ class InferenceService:
|
|
| 1135 |
return False
|
| 1136 |
|
| 1137 |
categories = [get_category_type(cat_str(i)) for i in subset]
|
|
|
|
| 1138 |
category_counts = {}
|
| 1139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1140 |
for cat in categories:
|
| 1141 |
category_counts[cat] = category_counts.get(cat, 0) + 1
|
| 1142 |
|
|
@@ -1159,6 +1217,7 @@ class InferenceService:
|
|
| 1159 |
def calculate_outfit_penalty(subset: List[int], base_score: float) -> float:
|
| 1160 |
"""Calculate sophisticated penalty-adjusted score with advanced fashion reasoning"""
|
| 1161 |
categories = [get_category_type(cat_str(i)) for i in subset]
|
|
|
|
| 1162 |
category_counts = {}
|
| 1163 |
|
| 1164 |
for cat in categories:
|
|
@@ -1177,9 +1236,15 @@ class InferenceService:
|
|
| 1177 |
penalty += -1000.0
|
| 1178 |
|
| 1179 |
# Duplicate core categories: -β penalty (fashion rule violation)
|
|
|
|
| 1180 |
core_categories = {"upper", "bottom", "shoe", "outerwear"}
|
|
|
|
|
|
|
| 1181 |
for cat in core_categories:
|
| 1182 |
-
|
|
|
|
|
|
|
|
|
|
| 1183 |
penalty += -1000.0
|
| 1184 |
|
| 1185 |
# 2. Context-specific critical violations
|
|
@@ -1231,6 +1296,8 @@ class InferenceService:
|
|
| 1231 |
bonus += 0.4 # Complete formal set bonus
|
| 1232 |
if style_score > 0.7:
|
| 1233 |
bonus += 0.3 # High style coherence bonus
|
|
|
|
|
|
|
| 1234 |
|
| 1235 |
# Business outfit bonuses
|
| 1236 |
elif occasion == "business":
|
|
@@ -1250,13 +1317,15 @@ class InferenceService:
|
|
| 1250 |
|
| 1251 |
# 8. Traditional Pakistani outfit bonuses
|
| 1252 |
if outfit_style == "traditional":
|
| 1253 |
-
traditional_items = [cat for cat in
|
| 1254 |
if len(traditional_items) >= 2:
|
| 1255 |
bonus += 0.7 # Strong cultural appropriateness bonus
|
| 1256 |
-
if len(traditional_items)
|
| 1257 |
bonus += 0.4 # Complete traditional set bonus
|
| 1258 |
if style_score > 0.6:
|
| 1259 |
bonus += 0.3 # Traditional style coherence
|
|
|
|
|
|
|
| 1260 |
|
| 1261 |
# 9. Fashion rule compliance bonuses
|
| 1262 |
# Perfect category distribution
|
|
|
|
| 132 |
2: "shoes", # shoes, sneakers, boots, footwear
|
| 133 |
3: "jacket", # jacket, blazer, coat, outerwear
|
| 134 |
4: "dress", # dress, gown
|
| 135 |
+
5: "shorts", # skirt, shorts (Updated from pants to shorts for better filtering)
|
| 136 |
6: "shirt", # sweater, hoodie, pullover (map to shirt)
|
| 137 |
7: "accessory", # watch, ring, necklace, jewelry
|
| 138 |
8: "accessory", # bag, purse, handbag
|
|
|
|
| 140 |
10: "accessory", # belt, accessory
|
| 141 |
11: "kameez", # kameez, kurta, traditional Pakistani shirt
|
| 142 |
12: "shalwar", # shalwar, traditional Pakistani pants
|
| 143 |
+
13: "sandals" # Peshawari chappal, traditional Pakistani sandals (Updated to sandals)
|
| 144 |
}
|
| 145 |
|
| 146 |
predicted_category = category_map.get(indices[0].item(), "other")
|
|
|
|
| 160 |
|
| 161 |
filename_lower = filename.lower()
|
| 162 |
|
| 163 |
+
# Traditional Pakistani Wear
|
| 164 |
+
if any(kw in filename_lower for kw in ["kameez", "kurta", "kurti"]):
|
| 165 |
+
return "kameez"
|
| 166 |
+
if any(kw in filename_lower for kw in ["shalwar", "salwar", "pyjama", "pajama"]):
|
| 167 |
+
return "shalwar"
|
| 168 |
+
if any(kw in filename_lower for kw in ["peshawari", "chappal", "khussa", "kolhapuri"]):
|
| 169 |
+
return "sandals"
|
| 170 |
+
|
| 171 |
+
# Specific Bottoms
|
| 172 |
+
if any(kw in filename_lower for kw in ["short", "shorts", "bermuda"]):
|
| 173 |
+
return "shorts"
|
| 174 |
+
if any(kw in filename_lower for kw in ["jean", "jeans", "denim"]):
|
| 175 |
+
return "jeans"
|
| 176 |
+
if any(kw in filename_lower for kw in ["skirt", "miniskirt"]):
|
| 177 |
+
return "skirt"
|
| 178 |
+
if any(kw in filename_lower for kw in ["pant", "trouser", "slack", "chino", "legging", "jogger"]):
|
| 179 |
return "pants"
|
| 180 |
+
|
| 181 |
+
# Specific Footwear
|
| 182 |
+
if any(kw in filename_lower for kw in ["sandal", "flip flop", "slide", "slipper"]):
|
| 183 |
+
return "sandals"
|
| 184 |
+
if any(kw in filename_lower for kw in ["sneaker", "trainer", "runner", "athletic shoe"]):
|
| 185 |
+
return "sneakers"
|
| 186 |
+
if any(kw in filename_lower for kw in ["boot", "bootie"]):
|
| 187 |
+
return "boots"
|
| 188 |
+
if any(kw in filename_lower for kw in ["shoe", "heel", "loafer", "oxford", "pump", "flat"]):
|
| 189 |
return "shoes"
|
| 190 |
+
|
| 191 |
+
# Specific Tops/Outerwear
|
| 192 |
+
if any(kw in filename_lower for kw in ["waistcoat", "vest"]):
|
| 193 |
+
return "waistcoat"
|
| 194 |
+
if any(kw in filename_lower for kw in ["blazer", "suit jacket", "coat", "jacket"]):
|
| 195 |
+
return "jacket"
|
| 196 |
+
if any(kw in filename_lower for kw in ["hoodie", "sweatshirt"]):
|
| 197 |
+
return "hoodie"
|
| 198 |
+
if any(kw in filename_lower for kw in ["shirt", "top", "blouse", "tank", "tee", "t-shirt", "polo", "sweater", "cardigan"]):
|
| 199 |
+
return "shirt"
|
| 200 |
|
| 201 |
# Accessories
|
| 202 |
+
if any(kw in filename_lower for kw in ["watch", "ring", "necklace", "bracelet", "bag", "hat", "belt", "scarf", "tie", "pocket square"]):
|
| 203 |
return "accessory"
|
| 204 |
|
| 205 |
# Default fallback
|
|
|
|
| 460 |
outfit_templates = {
|
| 461 |
"casual": {
|
| 462 |
"style": "relaxed, comfortable, everyday",
|
| 463 |
+
"preferred_categories": ["tshirt", "jean", "sneaker", "hoodie", "sweatpant", "shirt", "pants", "shoes", "shorts", "jeans", "sneakers"],
|
| 464 |
+
"excluded_categories": ["waistcoat", "suit jacket", "dress pant", "oxford"],
|
| 465 |
"color_palette": ["neutral", "denim", "white", "black", "gray"],
|
| 466 |
"accessory_limit": 2,
|
| 467 |
"weather_modifiers": {
|
| 468 |
+
"hot": {"preferred_categories": ["tank", "shorts", "sandals", "light shirt"], "excluded_categories": ["hoodie", "sweater", "jacket", "boots"]},
|
| 469 |
+
"cold": {"preferred_categories": ["hoodie", "sweater", "jacket", "boots"], "excluded_categories": ["shorts", "sandals", "tank"]},
|
| 470 |
+
"rain": {"preferred_categories": ["jacket", "boots", "waterproof"], "excluded_categories": ["sandals", "suede"]}
|
| 471 |
},
|
| 472 |
"occasion_modifiers": {
|
| 473 |
+
"business": {"preferred_categories": ["shirt", "pants", "shoes", "blazer"], "excluded_categories": ["shorts", "sandals", "tank", "sweatpant", "hoodie", "legging"], "accessory_limit": 3},
|
| 474 |
+
"formal": {"preferred_categories": ["shirt", "pants", "shoes", "blazer"], "excluded_categories": ["shorts", "sandals", "sneakers", "jeans", "tshirt"], "accessory_limit": 4}
|
| 475 |
}
|
| 476 |
},
|
| 477 |
"smart_casual": {
|
| 478 |
"style": "polished but relaxed, business casual",
|
| 479 |
+
"preferred_categories": ["shirt", "chino", "loafer", "blazer", "polo", "pants", "shoes", "jeans", "boots"],
|
| 480 |
+
"excluded_categories": ["shorts", "sandals", "tank", "sweatpant", "hoodie", "athletic"],
|
| 481 |
"color_palette": ["navy", "white", "khaki", "brown", "gray"],
|
| 482 |
"accessory_limit": 3,
|
| 483 |
"weather_modifiers": {
|
| 484 |
+
"hot": {"preferred_categories": ["polo", "light shirt", "loafer"], "excluded_categories": ["boots", "heavy jacket"]},
|
| 485 |
+
"cold": {"preferred_categories": ["blazer", "sweater", "boots"], "excluded_categories": ["loafer"]},
|
| 486 |
+
"rain": {"preferred_categories": ["blazer", "boots", "umbrella"], "excluded_categories": ["suede"]}
|
| 487 |
},
|
| 488 |
"occasion_modifiers": {
|
| 489 |
+
"business": {"preferred_categories": ["shirt", "pants", "shoes", "blazer"], "excluded_categories": ["jeans", "sneakers"], "accessory_limit": 4},
|
| 490 |
+
"formal": {"preferred_categories": ["shirt", "pants", "shoes", "blazer", "suit"], "excluded_categories": ["jeans", "sneakers", "polo"], "accessory_limit": 4}
|
| 491 |
}
|
| 492 |
},
|
| 493 |
"formal": {
|
| 494 |
"style": "professional, elegant, sophisticated",
|
| 495 |
+
"preferred_categories": ["blazer", "jacket", "suit jacket", "dress shirt", "dress pant", "oxford", "suit", "shirt", "pants", "shoes", "waistcoat"],
|
| 496 |
+
"excluded_categories": ["shorts", "sandals", "sneakers", "jeans", "tshirt", "hoodie", "sweatpant", "tank", "legging"],
|
| 497 |
"color_palette": ["navy", "black", "white", "gray", "charcoal"],
|
| 498 |
"accessory_limit": 4,
|
| 499 |
"requires_outerwear": True, # Flag to indicate formal outfits should include jackets
|
| 500 |
"weather_modifiers": {
|
| 501 |
"hot": {"preferred_categories": ["light shirt", "light pant", "oxford"], "requires_outerwear": False},
|
| 502 |
+
"cold": {"preferred_categories": ["blazer", "suit", "boots", "waistcoat"], "requires_outerwear": True},
|
| 503 |
+
"rain": {"preferred_categories": ["blazer", "boots", "umbrella"], "requires_outerwear": True}
|
| 504 |
},
|
| 505 |
"occasion_modifiers": {
|
| 506 |
+
"business": {"preferred_categories": ["shirt", "pants", "shoes", "waistcoat"], "accessory_limit": 4, "requires_outerwear": True},
|
| 507 |
+
"casual": {"preferred_categories": ["shirt", "pants", "shoes", "blazer"], "accessory_limit": 3, "requires_outerwear": False}
|
| 508 |
}
|
| 509 |
},
|
| 510 |
"sporty": {
|
| 511 |
"style": "athletic, active, performance",
|
| 512 |
+
"preferred_categories": ["athletic shirt", "jogger", "running shoe", "tank", "legging", "shirt", "pants", "shoes", "sneakers", "shorts", "hoodie"],
|
| 513 |
+
"excluded_categories": ["blazer", "suit", "dress pant", "oxford", "loafer", "waistcoat", "jeans", "sandals"],
|
| 514 |
"color_palette": ["bright", "neon", "white", "black", "primary colors"],
|
| 515 |
"accessory_limit": 1,
|
| 516 |
"weather_modifiers": {
|
| 517 |
+
"hot": {"preferred_categories": ["tank", "shorts", "running shoe"]},
|
| 518 |
"cold": {"preferred_categories": ["hoodie", "legging", "running shoe"]},
|
| 519 |
"rain": {"preferred_categories": ["jacket", "running shoe", "cap"]}
|
| 520 |
},
|
| 521 |
"occasion_modifiers": {
|
| 522 |
+
"business": {"preferred_categories": ["shirt", "pants", "shoes"], "excluded_categories": ["tank", "shorts", "legging"], "accessory_limit": 2},
|
| 523 |
+
"formal": {"preferred_categories": ["shirt", "pants", "shoes"], "excluded_categories": ["tank", "shorts", "legging", "hoodie"], "accessory_limit": 3}
|
| 524 |
}
|
| 525 |
},
|
| 526 |
"traditional": {
|
| 527 |
"style": "Pakistani traditional, cultural, ethnic",
|
| 528 |
+
"preferred_categories": ["kameez", "kurta", "shalwar", "peshawari", "chappal", "traditional", "ethnic", "waistcoat", "sandals"],
|
| 529 |
+
"excluded_categories": ["shorts", "jeans", "sneakers", "hoodie", "tank", "suit", "tie"],
|
| 530 |
"color_palette": ["white", "black", "navy", "maroon", "gold", "green", "traditional colors"],
|
| 531 |
"accessory_limit": 3,
|
| 532 |
"requires_traditional": True, # Flag for traditional outfit combinations
|
| 533 |
"weather_modifiers": {
|
| 534 |
+
"hot": {"preferred_categories": ["light kameez", "cotton shalwar", "peshawari chappal", "sandals"]},
|
| 535 |
+
"cold": {"preferred_categories": ["warm kameez", "thick shalwar", "traditional boots", "waistcoat", "shawl"]},
|
| 536 |
"rain": {"preferred_categories": ["waterproof kameez", "shalwar", "traditional boots"]}
|
| 537 |
},
|
| 538 |
"occasion_modifiers": {
|
| 539 |
+
"business": {"preferred_categories": ["formal kameez", "shalwar", "peshawari", "waistcoat"], "accessory_limit": 2},
|
| 540 |
+
"formal": {"preferred_categories": ["elegant kameez", "shalwar", "peshawari", "waistcoat"], "accessory_limit": 3},
|
| 541 |
+
"casual": {"preferred_categories": ["casual kameez", "shalwar", "chappal", "sandals"], "accessory_limit": 2}
|
| 542 |
}
|
| 543 |
}
|
| 544 |
}
|
|
|
|
| 576 |
if constraints.get("requires_outerwear"):
|
| 577 |
template["requires_outerwear"] = constraints["requires_outerwear"]
|
| 578 |
|
| 579 |
+
# Initialize excluded categories if not present
|
| 580 |
+
if "excluded_categories" not in template:
|
| 581 |
+
template["excluded_categories"] = []
|
| 582 |
+
|
| 583 |
# Apply weather modifications
|
| 584 |
if weather != "any" and weather in template.get("weather_modifiers", {}):
|
| 585 |
weather_mod = template["weather_modifiers"][weather]
|
| 586 |
template["preferred_categories"].extend(weather_mod.get("preferred_categories", []))
|
| 587 |
+
if "excluded_categories" in weather_mod:
|
| 588 |
+
template["excluded_categories"].extend(weather_mod["excluded_categories"])
|
| 589 |
if "accessory_limit" in weather_mod:
|
| 590 |
template["accessory_limit"] = weather_mod["accessory_limit"]
|
| 591 |
|
|
|
|
| 593 |
if occasion in template.get("occasion_modifiers", {}):
|
| 594 |
occasion_mod = template["occasion_modifiers"][occasion]
|
| 595 |
template["preferred_categories"].extend(occasion_mod.get("preferred_categories", []))
|
| 596 |
+
if "excluded_categories" in occasion_mod:
|
| 597 |
+
template["excluded_categories"].extend(occasion_mod["excluded_categories"])
|
| 598 |
if "accessory_limit" in occasion_mod:
|
| 599 |
template["accessory_limit"] = occasion_mod["accessory_limit"]
|
| 600 |
|
| 601 |
# Remove duplicates and add context info
|
| 602 |
template["preferred_categories"] = list(set(template["preferred_categories"]))
|
| 603 |
+
template["excluded_categories"] = list(set(template["excluded_categories"]))
|
| 604 |
template["context"] = {
|
| 605 |
"occasion": occasion,
|
| 606 |
"weather": weather,
|
|
|
|
| 612 |
|
| 613 |
print(f"π DEBUG: Using template '{template_name}' with context: occasion={occasion}, weather={weather}")
|
| 614 |
print(f"π DEBUG: Template categories: {template['preferred_categories']}")
|
| 615 |
+
print(f"π DEBUG: Excluded categories: {template['excluded_categories']}")
|
| 616 |
print(f"π DEBUG: Accessory limit: {template['accessory_limit']}")
|
| 617 |
|
| 618 |
# Enhanced category-aware pools with diversity checks
|
|
|
|
| 806 |
def get_category_type(cat: str) -> str:
|
| 807 |
"""Map category to outfit slot type with comprehensive taxonomy"""
|
| 808 |
cat_lower = cat.lower().strip()
|
| 809 |
+
# print(f"π DEBUG: Mapping category '{cat}' -> '{cat_lower}'")
|
| 810 |
|
| 811 |
# Direct mapping for CLIP-detected categories
|
| 812 |
if cat_lower == "shirt":
|
|
|
|
| 825 |
return "bottom" # Shalwar is bottom wear
|
| 826 |
elif cat_lower == "peshawari":
|
| 827 |
return "shoe" # Peshawari chappal is footwear
|
| 828 |
+
elif cat_lower == "shorts":
|
| 829 |
+
return "bottom"
|
| 830 |
+
elif cat_lower == "sandals":
|
| 831 |
+
return "shoe"
|
| 832 |
+
elif cat_lower == "sneakers":
|
| 833 |
+
return "shoe"
|
| 834 |
+
elif cat_lower == "jeans":
|
| 835 |
+
return "bottom"
|
| 836 |
+
elif cat_lower == "waistcoat":
|
| 837 |
+
return "outerwear"
|
| 838 |
|
| 839 |
# Upper body items (tops, innerwear)
|
| 840 |
upper_keywords = [
|
|
|
|
| 1186 |
return False
|
| 1187 |
|
| 1188 |
categories = [get_category_type(cat_str(i)) for i in subset]
|
| 1189 |
+
raw_categories = [cat_str(i) for i in subset]
|
| 1190 |
category_counts = {}
|
| 1191 |
|
| 1192 |
+
# Check for excluded categories
|
| 1193 |
+
excluded = template.get("excluded_categories", [])
|
| 1194 |
+
for cat in raw_categories:
|
| 1195 |
+
if any(ex in cat for ex in excluded):
|
| 1196 |
+
return False
|
| 1197 |
+
|
| 1198 |
for cat in categories:
|
| 1199 |
category_counts[cat] = category_counts.get(cat, 0) + 1
|
| 1200 |
|
|
|
|
| 1217 |
def calculate_outfit_penalty(subset: List[int], base_score: float) -> float:
|
| 1218 |
"""Calculate sophisticated penalty-adjusted score with advanced fashion reasoning"""
|
| 1219 |
categories = [get_category_type(cat_str(i)) for i in subset]
|
| 1220 |
+
raw_categories = [cat_str(i) for i in subset]
|
| 1221 |
category_counts = {}
|
| 1222 |
|
| 1223 |
for cat in categories:
|
|
|
|
| 1236 |
penalty += -1000.0
|
| 1237 |
|
| 1238 |
# Duplicate core categories: -β penalty (fashion rule violation)
|
| 1239 |
+
# EXCEPTION: Allow multiple outerwear if one is a waistcoat (3-piece suit)
|
| 1240 |
core_categories = {"upper", "bottom", "shoe", "outerwear"}
|
| 1241 |
+
has_waistcoat = any("waistcoat" in c for c in raw_categories)
|
| 1242 |
+
|
| 1243 |
for cat in core_categories:
|
| 1244 |
+
count = category_counts.get(cat, 0)
|
| 1245 |
+
if cat == "outerwear" and has_waistcoat and count <= 2:
|
| 1246 |
+
continue # Allow waistcoat + jacket
|
| 1247 |
+
if count > 1:
|
| 1248 |
penalty += -1000.0
|
| 1249 |
|
| 1250 |
# 2. Context-specific critical violations
|
|
|
|
| 1296 |
bonus += 0.4 # Complete formal set bonus
|
| 1297 |
if style_score > 0.7:
|
| 1298 |
bonus += 0.3 # High style coherence bonus
|
| 1299 |
+
if has_waistcoat and category_counts.get("outerwear", 0) == 2:
|
| 1300 |
+
bonus += 0.5 # 3-piece suit bonus
|
| 1301 |
|
| 1302 |
# Business outfit bonuses
|
| 1303 |
elif occasion == "business":
|
|
|
|
| 1317 |
|
| 1318 |
# 8. Traditional Pakistani outfit bonuses
|
| 1319 |
if outfit_style == "traditional":
|
| 1320 |
+
traditional_items = [cat for cat in raw_categories if any(traditional in cat for traditional in ["kameez", "kurta", "shalwar", "peshawari", "chappal", "waistcoat"])]
|
| 1321 |
if len(traditional_items) >= 2:
|
| 1322 |
bonus += 0.7 # Strong cultural appropriateness bonus
|
| 1323 |
+
if len(traditional_items) >= 3:
|
| 1324 |
bonus += 0.4 # Complete traditional set bonus
|
| 1325 |
if style_score > 0.6:
|
| 1326 |
bonus += 0.3 # Traditional style coherence
|
| 1327 |
+
if has_waistcoat:
|
| 1328 |
+
bonus += 0.3 # Waistcoat with traditional wear
|
| 1329 |
|
| 1330 |
# 9. Fashion rule compliance bonuses
|
| 1331 |
# Perfect category distribution
|