diff --git a/app.py b/app.py index 49085b4ed2988cb655195f491ec0c32929e62d58..03a0e40f4cadc29279bfad0cf58e7211f11e7adb 100644 --- a/app.py +++ b/app.py @@ -9,6 +9,7 @@ Built for the Build Small Hackathon (HuggingFace x Gradio, June 2026). import io import logging import os +import shutil from pathlib import Path from dotenv import load_dotenv @@ -166,6 +167,32 @@ def update_detection_backend(backend_name: str): return f"Backend actualizado: **{backend_name}**" +# --------------------------------------------------------------------------- +# Sample wardrobe handler +# --------------------------------------------------------------------------- + +SAMPLES_DIR = Path(__file__).resolve().parent / "data" / "samples" +DATA_DIR = Path(__file__).resolve().parent / "data" + + +def load_sample_wardrobe(): + """Load the pre-processed sample wardrobe into the active catalog.""" + if not SAMPLES_DIR.exists() or not (SAMPLES_DIR / "catalog.json").exists(): + return "Datos de ejemplo no disponibles. Ejecuta scripts/build_sample_wardrobe.py primero." + + shutil.copy(SAMPLES_DIR / "catalog.json", DATA_DIR / "catalog.json") + + dest = DATA_DIR / "garments" + dest.mkdir(parents=True, exist_ok=True) + src_garments = SAMPLES_DIR / "garments" + if src_garments.exists(): + for img in src_garments.glob("*.jpg"): + shutil.copy(img, dest / img.name) + + catalog = load_catalog() + return f"Cargadas **{len(catalog)}** prendas de ejemplo. Ve a 'Mi Armario' para explorarlas." + + # --------------------------------------------------------------------------- # Wardrobe tab handlers # --------------------------------------------------------------------------- @@ -434,6 +461,19 @@ with gr.Blocks(title="Wardrobe AI") as demo: interactive=False, ) + gr.Markdown("---") + with gr.Row(): + sample_btn = gr.Button( + "Cargar armario de ejemplo (50 prendas)", + variant="secondary", size="sm", + ) + sample_status = gr.Markdown() + + sample_btn.click( + load_sample_wardrobe, + outputs=[sample_status], + ) + with gr.Accordion("⚙️ Ajustes de detección", open=False): available_backends = list_available() if not available_backends: diff --git a/data/samples/catalog.json b/data/samples/catalog.json new file mode 100644 index 0000000000000000000000000000000000000000..439f955e6bb44b3017d0c7f735ad8ecca49d984a --- /dev/null +++ b/data/samples/catalog.json @@ -0,0 +1,552 @@ +[ + { + "type": "crop top", + "color": "black", + "material": "polyester", + "pattern": "striped", + "season": "summer", + "formality": "casual", + "description": "A black crop top with white stripes and a built-in corset-style bodice, offering a sporty and casual style.", + "id": "garment_001", + "image_ref": "garment_001.jpg" + }, + { + "type": "crop top", + "color": "black", + "material": "unknown", + "pattern": "solid", + "season": "summer", + "formality": "casual", + "description": "A black crop top with a structured, fitted silhouette and white detailing along the neckline. It features a graphic print and is paired with bright neon green shorts and chunky black boots.", + "id": "garment_002", + "image_ref": "garment_002.jpg" + }, + { + "type": "shorts", + "color": "lime green", + "material": "unknown", + "pattern": "solid", + "season": "summer", + "formality": "casual", + "description": "High-waisted, bright lime green shorts with a structured fit and pleats. They feature a black belt with a plastic buckle and are suitable for warm weather and casual outfits.", + "id": "garment_003", + "image_ref": "garment_003.jpg" + }, + { + "type": "skirt", + "color": "blue", + "material": "denim", + "pattern": "solid", + "season": "spring", + "formality": "smart-casual", + "description": "A long, asymmetric denim skirt with a high-waisted fit and a ruffled hem. The skirt features a distressed and frayed edge, giving it a casual yet stylish appearance.", + "id": "garment_004", + "image_ref": "garment_004.jpg" + }, + { + "type": "boots", + "color": "blue", + "material": "suede", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "Tall, pointed-toe suede boots with gold laces and a chunky heel. These boots have a sleek and sophisticated design, suitable for dressing up an outfit.", + "id": "garment_005", + "image_ref": "garment_005.jpg" + }, + { + "type": "dress", + "color": "blue", + "material": "satin", + "pattern": "solid", + "season": "spring", + "formality": "smart-casual", + "description": "A light blue satin dress with a fitted bodice, puffed sleeves, and a wrap-style closure. The dress features a ruffled hem and is suitable for a semi-formal occasion.", + "id": "garment_006", + "image_ref": "garment_006.jpg" + }, + { + "type": "dress", + "color": "blue", + "material": "satin", + "pattern": "solid", + "season": "spring", + "formality": "smart-casual", + "description": "A light blue satin dress with a fitted bodice, puffed sleeves, and a ruffled skirt. It features a double-button closure and a sophisticated, elegant style suitable for a dressy occasion.", + "id": "garment_007", + "image_ref": "garment_007.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "lace", + "pattern": "floral", + "season": "autumn", + "formality": "smart-casual", + "description": "This black lace dress features a floral pattern with gold accents and a flattering fit. The dress has a high neckline and ruffled sleeves, making it suitable for a dressy yet comfortable occasion.", + "id": "garment_008", + "image_ref": "garment_008.jpg" + }, + { + "type": "shirt", + "color": "black", + "material": "satin", + "pattern": "striped", + "season": "summer", + "formality": "smart-casual", + "description": "A cropped satin shirt with a bold zebra print, featuring a tie-front closure and long sleeves. This stylish top is perfect for a warm weather outfit.", + "id": "garment_009", + "image_ref": "garment_009.jpg" + }, + { + "type": "jacket", + "color": "silver", + "material": "leather", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "A cropped silver leather biker jacket with a belted waist and a classic motorcycle style. It features a shiny finish and a slim fit, suitable for layering in cooler weather.", + "id": "garment_010", + "image_ref": "garment_010.jpg" + }, + { + "type": "pants", + "color": "blue", + "material": "denim", + "pattern": "striped", + "season": "spring", + "formality": "smart-casual", + "description": "High-waisted denim pants with black panels on the sides and legs, creating a modern and asymmetrical design. The fit is tailored and suitable for a stylish, casual yet put-together look.", + "id": "garment_011", + "image_ref": "garment_011.jpg" + }, + { + "type": "boots", + "color": "black", + "material": "unknown", + "pattern": "solid", + "season": "all", + "formality": "smart-casual", + "description": "These black ankle boots feature a pointed toe and a chunky block heel, offering a sleek and modern style suitable for a variety of outfits.", + "id": "garment_012", + "image_ref": "garment_012.jpg" + }, + { + "type": "blazer", + "color": "beige", + "material": "linen", + "pattern": "striped", + "season": "spring", + "formality": "smart-casual", + "description": "A light beige blazer with a double-breasted design and subtle vertical stripes, featuring gold-tone buttons and a relaxed fit suitable for smart-casual occasions.", + "id": "garment_013", + "image_ref": "garment_013.jpg" + }, + { + "type": "top", + "color": "black", + "material": "satin", + "pattern": "solid", + "season": "summer", + "formality": "casual", + "description": "A black satin crop top with delicate lace trim along the neckline and straps, offering a sleek and minimalist style suitable for warm weather.", + "id": "garment_014", + "image_ref": "garment_014.jpg" + }, + { + "type": "jeans", + "color": "blue", + "material": "denim", + "pattern": "solid", + "season": "spring", + "formality": "casual", + "description": "Wide-leg, light blue denim jeans with embroidered details and a relaxed fit, perfect for a casual summer outfit.", + "id": "garment_015", + "image_ref": "garment_015.jpg" + }, + { + "type": "boots", + "color": "black", + "material": "leather", + "pattern": "solid", + "season": "all", + "formality": "casual", + "description": "Classic black leather Chelsea boots with a chunky platform sole and laces. These boots have a rugged, casual style suitable for everyday wear.", + "id": "garment_016", + "image_ref": "garment_016.jpg" + }, + { + "type": "cardigan", + "color": "green", + "material": "knit", + "pattern": "plaid", + "season": "autumn", + "formality": "casual", + "description": "A cozy, oversized plaid cardigan in a muted green color with a v-neck and button closures. It has pockets and a relaxed fit, perfect for layering during the fall.", + "id": "garment_017", + "image_ref": "garment_017.jpg" + }, + { + "type": "pants", + "color": "black", + "material": "leather", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "High-waisted black leather pants with a zip front and asymmetrical cut, creating a modern and edgy style suitable for a smart-casual look.", + "id": "garment_018", + "image_ref": "garment_018.jpg" + }, + { + "type": "coat", + "color": "black", + "material": "woven", + "pattern": "striped", + "season": "autumn", + "formality": "smart-casual", + "description": "Oversized double-breasted coat in black and white stripes with a wide belt and decorative buckle. The coat has a relaxed fit and a structured silhouette, suitable for layering in cooler weather.", + "id": "garment_019", + "image_ref": "garment_019.jpg" + }, + { + "type": "blazer", + "color": "black", + "material": "woven", + "pattern": "striped", + "season": "autumn", + "formality": "smart-casual", + "description": "A black and white striped blazer with a double-breasted design and a belted waist, creating a tailored yet stylish silhouette.", + "id": "garment_020", + "image_ref": "garment_020.jpg" + }, + { + "type": "shirt", + "color": "light blue", + "material": "knit", + "pattern": "solid", + "season": "summer", + "formality": "casual", + "description": "A light blue, short-sleeved polo shirt with a v-neck and a slim fit, perfect for warm weather and casual occasions.", + "id": "garment_021", + "image_ref": "garment_021.jpg" + }, + { + "type": "skirt", + "color": "orange", + "material": "leather", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "A high-waisted, A-line leather skirt in a vibrant orange color. It has a sleek and polished appearance suitable for a smart-casual outfit.", + "id": "garment_022", + "image_ref": "garment_022.jpg" + }, + { + "type": "shoes", + "color": "orange", + "material": "suede", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "Elegant pointed-toe high heels in a vibrant orange suede, featuring a stiletto heel and a red sole. These shoes are a sophisticated choice for a dressy occasion.", + "id": "garment_023", + "image_ref": "garment_023.jpg" + }, + { + "type": "top", + "color": "beige", + "material": "woven", + "pattern": "floral", + "season": "spring", + "formality": "smart-casual", + "description": "This beige top features a floral pattern and puffed sleeves, creating a romantic and slightly formal look. The square neckline and woven fabric suggest a lightweight and elegant design.", + "id": "garment_024", + "image_ref": "garment_024.jpg" + }, + { + "type": "top", + "color": "beige", + "material": "silk", + "pattern": "floral", + "season": "spring", + "formality": "smart-casual", + "description": "This flowy, square-neck top features puffed sleeves and a delicate floral pattern in beige and orange tones. It has a relaxed fit and would be suitable for warmer weather occasions.", + "id": "garment_025", + "image_ref": "garment_025.jpg" + }, + { + "type": "pants", + "color": "black", + "material": "unknown", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "Wide-leg black trousers with a high waist and a tailored fit, suitable for a sophisticated evening look.", + "id": "garment_026", + "image_ref": "garment_026.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "unknown", + "pattern": "solid", + "season": "autumn", + "formality": "formal", + "description": "A sleek, long-sleeved off-the-shoulder dress in black with a fitted silhouette and button closure. It features long gloves and is suitable for evening events or formal occasions.", + "id": "garment_027", + "image_ref": "garment_027.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "sequin", + "pattern": "sequined", + "season": "winter", + "formality": "formal", + "description": "A sleek, black sequin strapless mini dress with a shimmering effect, perfect for a glamorous evening event. The dress is paired with tall lace-up boots and a sparkly clutch.", + "id": "garment_028", + "image_ref": "garment_028.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "lace", + "pattern": "floral", + "season": "autumn", + "formality": "smart-casual", + "description": "This black lace dress features a high neckline, ruffled sleeves, and a fitted silhouette. It's a delicate and elegant piece suitable for a semi-formal occasion.", + "id": "garment_029", + "image_ref": "garment_029.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "lace", + "pattern": "floral", + "season": "autumn", + "formality": "smart-casual", + "description": "A black lace dress with a high neckline and ruffled sleeves, featuring a floral pattern and a fitted silhouette. It is paired with heels and jewelry for a sophisticated and elegant look.", + "id": "garment_030", + "image_ref": "garment_030.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "velvet", + "pattern": "solid", + "season": "winter", + "formality": "formal", + "description": "A fitted black velvet dress with dramatic puffed sleeves and a high neckline adorned with emerald green stones. It features a statement necklace and is suitable for a glamorous evening event.", + "id": "garment_031", + "image_ref": "garment_031.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "velvet", + "pattern": "solid", + "season": "winter", + "formality": "formal", + "description": "A fitted, short velvet dress with long sleeves adorned with emerald green embellishments. It is a luxurious and elegant piece suitable for formal occasions.", + "id": "garment_032", + "image_ref": "garment_032.jpg" + }, + { + "type": "blazer", + "color": "black", + "material": "polyester", + "pattern": "solid", + "season": "all", + "formality": "smart-casual", + "description": "A cropped black blazer with a tie-front closure, featuring a tailored fit and a sleek, modern style.", + "id": "garment_033", + "image_ref": "garment_033.jpg" + }, + { + "type": "bag", + "color": "black", + "material": "leather", + "pattern": "solid", + "season": "all", + "formality": "smart-casual", + "description": "A structured black leather handbag with a gold heart-shaped embellishment on the front. It features a detachable shoulder strap and a classic, sophisticated design.", + "id": "garment_034", + "image_ref": "garment_034.jpg" + }, + { + "type": "skirt", + "color": "red", + "material": "denim", + "pattern": "solid", + "season": "spring", + "formality": "casual", + "description": "A short, fitted denim skirt in a vibrant red color with a button-down front and a classic style. It appears to be a casual garment suitable for warmer weather.", + "id": "garment_035", + "image_ref": "garment_035.jpg" + }, + { + "type": "top", + "color": "black", + "material": "velvet", + "pattern": "floral", + "season": "autumn", + "formality": "smart-casual", + "description": "This black velvet top features a high neckline and embellished floral embroidery with red, white, and gold accents. It has a fitted silhouette and a halter neck design, suitable for a stylish and slightly dressy occasion.", + "id": "garment_036", + "image_ref": "garment_036.jpg" + }, + { + "type": "bag", + "color": "red", + "material": "leather", + "pattern": "solid", + "season": "all", + "formality": "smart-casual", + "description": "A vibrant red, structured handbag with a curved silhouette and a detachable tassel strap. The bag features a gold logo detail and a sleek, modern design suitable for a variety of occasions.", + "id": "garment_037", + "image_ref": "garment_037.jpg" + }, + { + "type": "dress", + "color": "black", + "material": "satin", + "pattern": "floral", + "season": "autumn", + "formality": "smart-casual", + "description": "A fitted black satin dress with a vibrant floral pattern of red and green, featuring a wrap-style bodice and a flattering silhouette.", + "id": "garment_038", + "image_ref": "garment_038.jpg" + }, + { + "type": "boots", + "color": "black", + "material": "unknown", + "pattern": "solid", + "season": "autumn", + "formality": "smart-casual", + "description": "Tall, pointed-toe stiletto boots in black with a sleek, fitted design. These boots are suitable for a sophisticated and stylish look, perfect for cooler weather.", + "id": "garment_039", + "image_ref": "garment_039.jpg" + }, + { + "type": "shirt", + "color": "red", + "material": "silk", + "pattern": "floral", + "season": "autumn", + "formality": "smart-casual", + "description": "A short-sleeved shirt with a V-neck and a floral pattern of red and black, featuring a structured fit and a ruffled skirt. It appears to be a stylish and slightly formal piece suitable for autumn wear.", + "id": "garment_040", + "image_ref": "garment_040.jpg" + }, + { + "type": "blouse", + "color": "red", + "material": "silk", + "pattern": "floral", + "season": "spring", + "formality": "smart-casual", + "description": "A red and black silk blouse with a floral pattern and a gathered neckline, featuring short sleeves and a button-down closure. It appears to be a stylish and sophisticated piece suitable for warmer weather.", + "id": "garment_041", + "image_ref": "garment_041.jpg" + }, + { + "type": "pants", + "color": "white", + "material": "unknown", + "pattern": "solid", + "season": "summer", + "formality": "smart-casual", + "description": "Wide-leg, high-waisted white pants with a relaxed fit, perfect for a stylish summer outfit.", + "id": "garment_042", + "image_ref": "garment_042.jpg" + }, + { + "type": "blazer", + "color": "white", + "material": "unknown", + "pattern": "solid", + "season": "all", + "formality": "smart-casual", + "description": "A cropped white blazer with a tailored fit and a notched lapel, suitable for a smart-casual look.", + "id": "garment_043", + "image_ref": "garment_043.jpg" + }, + { + "type": "pants", + "color": "pink", + "material": "unknown", + "pattern": "solid", + "season": "spring", + "formality": "smart-casual", + "description": "Wide-leg, pleated pink pants with a fitted waistband, offering a modern and stylish silhouette suitable for warmer weather and dressed-up occasions.", + "id": "garment_044", + "image_ref": "garment_044.jpg" + }, + { + "type": "shirt", + "color": "white", + "material": "cotton", + "pattern": "striped", + "season": "spring", + "formality": "smart-casual", + "description": "A crisp white button-down shirt with a fitted silhouette and a subtle striped pattern. It features a collar, button-down closure, and a decorative belt at the waist.", + "id": "garment_045", + "image_ref": "garment_045.jpg" + }, + { + "type": "dress", + "color": "white", + "material": "lace", + "pattern": "floral", + "season": "spring", + "formality": "smart-casual", + "description": "This white lace dress features a fitted bodice and a flared skirt with a delicate floral pattern. It has spaghetti straps and a decorative embellishment, suitable for a semi-formal occasion.", + "id": "garment_046", + "image_ref": "garment_046.jpg" + }, + { + "type": "dress", + "color": "white", + "material": "lace", + "pattern": "floral", + "season": "spring", + "formality": "smart-casual", + "description": "A delicate white lace dress with a floral pattern and a fitted bodice, perfect for a light and airy spring occasion. The dress features spaghetti straps and a flared skirt.", + "id": "garment_047", + "image_ref": "garment_047.jpg" + }, + { + "type": "crop top", + "color": "purple", + "material": "sequin", + "pattern": "solid", + "season": "spring", + "formality": "smart-casual", + "description": "A sparkly purple sequin crop top with a halter neckline and thin straps, offering a glamorous and stylish look for warmer weather.", + "id": "garment_048", + "image_ref": "garment_048.jpg" + }, + { + "type": "bag", + "color": "purple", + "material": "suede", + "pattern": "quilted", + "season": "all", + "formality": "smart-casual", + "description": "A quilted purple suede shoulder bag with a classic Chanel logo closure and a comfortable handle. It has a structured design suitable for both casual and slightly more formal occasions.", + "id": "garment_049", + "image_ref": "garment_049.jpg" + }, + { + "type": "dress", + "color": "light blue", + "material": "unknown", + "pattern": "floral", + "season": "spring", + "formality": "smart-casual", + "description": "A light blue, off-the-shoulder dress with a floral pattern and a wrap-style design, creating a flattering and elegant silhouette suitable for a semi-formal occasion.", + "id": "garment_050", + "image_ref": "garment_050.jpg" + } +] \ No newline at end of file diff --git a/data/samples/garments/garment_001.jpg b/data/samples/garments/garment_001.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b22bdce18806ffb76f4ab7317ddfa64e199837a6 Binary files /dev/null and b/data/samples/garments/garment_001.jpg differ diff --git a/data/samples/garments/garment_002.jpg b/data/samples/garments/garment_002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..11e1addbf06dcf6c8146d6e59f12970b0ef860fa Binary files /dev/null and b/data/samples/garments/garment_002.jpg differ diff --git a/data/samples/garments/garment_003.jpg b/data/samples/garments/garment_003.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cbb29025844d076d0875ebfbeca56fb8791b5e14 Binary files /dev/null and b/data/samples/garments/garment_003.jpg differ diff --git a/data/samples/garments/garment_004.jpg b/data/samples/garments/garment_004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f24392df14020b9fbdc9021d562ea54b13653fa3 Binary files /dev/null and b/data/samples/garments/garment_004.jpg differ diff --git a/data/samples/garments/garment_005.jpg b/data/samples/garments/garment_005.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f6367aedf8d51810848a6cf5301fed89bcb1b856 Binary files /dev/null and b/data/samples/garments/garment_005.jpg differ diff --git a/data/samples/garments/garment_006.jpg b/data/samples/garments/garment_006.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cb7a7f6ba0e44fc3bb447400b421cfafd0447d48 Binary files /dev/null and b/data/samples/garments/garment_006.jpg differ diff --git a/data/samples/garments/garment_007.jpg b/data/samples/garments/garment_007.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7945dafc14ede24019672958f61d8c4a3eb0f5a7 Binary files /dev/null and b/data/samples/garments/garment_007.jpg differ diff --git a/data/samples/garments/garment_008.jpg b/data/samples/garments/garment_008.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d4246bd4786acf21080ce2a64c93e7ca7e7a88d4 Binary files /dev/null and b/data/samples/garments/garment_008.jpg differ diff --git a/data/samples/garments/garment_009.jpg b/data/samples/garments/garment_009.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ffbc6061e3f2f8a34d88731857134bab883a7cae Binary files /dev/null and b/data/samples/garments/garment_009.jpg differ diff --git a/data/samples/garments/garment_010.jpg b/data/samples/garments/garment_010.jpg new file mode 100644 index 0000000000000000000000000000000000000000..adc9158969d7f2866548c6fe3935d3a0f9014811 Binary files /dev/null and b/data/samples/garments/garment_010.jpg differ diff --git a/data/samples/garments/garment_011.jpg b/data/samples/garments/garment_011.jpg new file mode 100644 index 0000000000000000000000000000000000000000..754f22329b737d6a352c8866f730f0f5d12d3b03 Binary files /dev/null and b/data/samples/garments/garment_011.jpg differ diff --git a/data/samples/garments/garment_012.jpg b/data/samples/garments/garment_012.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e3d77a65d314a536790a3f1b4d2190e9916f8f9 Binary files /dev/null and b/data/samples/garments/garment_012.jpg differ diff --git a/data/samples/garments/garment_013.jpg b/data/samples/garments/garment_013.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4cc0f1074cff91065f2130c968d93101d33dab69 Binary files /dev/null and b/data/samples/garments/garment_013.jpg differ diff --git a/data/samples/garments/garment_014.jpg b/data/samples/garments/garment_014.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b9c5c8ab2e609e475bb65783a4d47eacadd4a664 Binary files /dev/null and b/data/samples/garments/garment_014.jpg differ diff --git a/data/samples/garments/garment_015.jpg b/data/samples/garments/garment_015.jpg new file mode 100644 index 0000000000000000000000000000000000000000..125155558184404abfccb2a972a180d9b4ed0546 Binary files /dev/null and b/data/samples/garments/garment_015.jpg differ diff --git a/data/samples/garments/garment_016.jpg b/data/samples/garments/garment_016.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b60d7271292932a14abaa2b6a3412b454a205019 Binary files /dev/null and b/data/samples/garments/garment_016.jpg differ diff --git a/data/samples/garments/garment_017.jpg b/data/samples/garments/garment_017.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b25020c9c917df4b0bca7f133a88c7b697358542 Binary files /dev/null and b/data/samples/garments/garment_017.jpg differ diff --git a/data/samples/garments/garment_018.jpg b/data/samples/garments/garment_018.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cd2a57a053c8f0ad929e59147ce0f17bba831b09 Binary files /dev/null and b/data/samples/garments/garment_018.jpg differ diff --git a/data/samples/garments/garment_019.jpg b/data/samples/garments/garment_019.jpg new file mode 100644 index 0000000000000000000000000000000000000000..785c640a3a4f21e073674a65526781e26fb7bdef Binary files /dev/null and b/data/samples/garments/garment_019.jpg differ diff --git a/data/samples/garments/garment_020.jpg b/data/samples/garments/garment_020.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b85d9310bcb866276d9955129655a8acd7cbe69d Binary files /dev/null and b/data/samples/garments/garment_020.jpg differ diff --git a/data/samples/garments/garment_021.jpg b/data/samples/garments/garment_021.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34e9eccefcf418bd12b3485c98b9d6392cdf5fa8 Binary files /dev/null and b/data/samples/garments/garment_021.jpg differ diff --git a/data/samples/garments/garment_022.jpg b/data/samples/garments/garment_022.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7bbe78bc8226c9b7c8839de18ded48f171a4a7fe Binary files /dev/null and b/data/samples/garments/garment_022.jpg differ diff --git a/data/samples/garments/garment_023.jpg b/data/samples/garments/garment_023.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8c475e0ec545c9a859cc614f5811ae32abf8059 Binary files /dev/null and b/data/samples/garments/garment_023.jpg differ diff --git a/data/samples/garments/garment_024.jpg b/data/samples/garments/garment_024.jpg new file mode 100644 index 0000000000000000000000000000000000000000..84070a0c5799a039015229c0766dcc0db55f84a3 Binary files /dev/null and b/data/samples/garments/garment_024.jpg differ diff --git a/data/samples/garments/garment_025.jpg b/data/samples/garments/garment_025.jpg new file mode 100644 index 0000000000000000000000000000000000000000..880539fc8872d0db15fe101ef9b8b2323b96710f Binary files /dev/null and b/data/samples/garments/garment_025.jpg differ diff --git a/data/samples/garments/garment_026.jpg b/data/samples/garments/garment_026.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e9e4645f490b75a6d7220d9f0e6fa6a1e35d9d00 Binary files /dev/null and b/data/samples/garments/garment_026.jpg differ diff --git a/data/samples/garments/garment_027.jpg b/data/samples/garments/garment_027.jpg new file mode 100644 index 0000000000000000000000000000000000000000..27e5773c103416cc5a9e0e181fe06823155f3ce2 Binary files /dev/null and b/data/samples/garments/garment_027.jpg differ diff --git a/data/samples/garments/garment_028.jpg b/data/samples/garments/garment_028.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0916da2a81136b25cc37186f31e840a946b6416d Binary files /dev/null and b/data/samples/garments/garment_028.jpg differ diff --git a/data/samples/garments/garment_029.jpg b/data/samples/garments/garment_029.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f53e9a742d7941cf98713f68cb72584c017f347b Binary files /dev/null and b/data/samples/garments/garment_029.jpg differ diff --git a/data/samples/garments/garment_030.jpg b/data/samples/garments/garment_030.jpg new file mode 100644 index 0000000000000000000000000000000000000000..43bfb24a7870bb38add9cc2a32dfa1be5cbb8ee0 Binary files /dev/null and b/data/samples/garments/garment_030.jpg differ diff --git a/data/samples/garments/garment_031.jpg b/data/samples/garments/garment_031.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a7103bda2c43bdc0308eca4155279dd5186b9c5e Binary files /dev/null and b/data/samples/garments/garment_031.jpg differ diff --git a/data/samples/garments/garment_032.jpg b/data/samples/garments/garment_032.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eac643b24be155e1bf9eaba257f7bbba8814f79c Binary files /dev/null and b/data/samples/garments/garment_032.jpg differ diff --git a/data/samples/garments/garment_033.jpg b/data/samples/garments/garment_033.jpg new file mode 100644 index 0000000000000000000000000000000000000000..532e8bc0f758313d01bdea8b3d777584112b2cca Binary files /dev/null and b/data/samples/garments/garment_033.jpg differ diff --git a/data/samples/garments/garment_034.jpg b/data/samples/garments/garment_034.jpg new file mode 100644 index 0000000000000000000000000000000000000000..be32eaeadfc4e106159ea364b8c7ea56822e5b67 Binary files /dev/null and b/data/samples/garments/garment_034.jpg differ diff --git a/data/samples/garments/garment_035.jpg b/data/samples/garments/garment_035.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2472a0a8e4055512954c1385e335765de068fbc3 Binary files /dev/null and b/data/samples/garments/garment_035.jpg differ diff --git a/data/samples/garments/garment_036.jpg b/data/samples/garments/garment_036.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4809ff097738e80d017fe7d19dba6af37eab1768 Binary files /dev/null and b/data/samples/garments/garment_036.jpg differ diff --git a/data/samples/garments/garment_037.jpg b/data/samples/garments/garment_037.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e5b5fe511c74a2790e814cd6f321318dfe169a6e Binary files /dev/null and b/data/samples/garments/garment_037.jpg differ diff --git a/data/samples/garments/garment_038.jpg b/data/samples/garments/garment_038.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7cd9416cd0c7bdb479edf8175389fc1556dc643d Binary files /dev/null and b/data/samples/garments/garment_038.jpg differ diff --git a/data/samples/garments/garment_039.jpg b/data/samples/garments/garment_039.jpg new file mode 100644 index 0000000000000000000000000000000000000000..28d5642095398dbc30d608b68ce6196c1406bb7e Binary files /dev/null and b/data/samples/garments/garment_039.jpg differ diff --git a/data/samples/garments/garment_040.jpg b/data/samples/garments/garment_040.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1edde30d7dc074b32cce509ed5cb9eafd9dc68f9 Binary files /dev/null and b/data/samples/garments/garment_040.jpg differ diff --git a/data/samples/garments/garment_041.jpg b/data/samples/garments/garment_041.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8259ae7f397540566a06e9c829b3c15b6dbb545b Binary files /dev/null and b/data/samples/garments/garment_041.jpg differ diff --git a/data/samples/garments/garment_042.jpg b/data/samples/garments/garment_042.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ea07605c0000a0b75dfb592baca1983a349a5ec6 Binary files /dev/null and b/data/samples/garments/garment_042.jpg differ diff --git a/data/samples/garments/garment_043.jpg b/data/samples/garments/garment_043.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7192d92615e12b3aedf89ed5937b5f6708f9829e Binary files /dev/null and b/data/samples/garments/garment_043.jpg differ diff --git a/data/samples/garments/garment_044.jpg b/data/samples/garments/garment_044.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6d468c03d153ed9a31791b39ea72a167ba92d775 Binary files /dev/null and b/data/samples/garments/garment_044.jpg differ diff --git a/data/samples/garments/garment_045.jpg b/data/samples/garments/garment_045.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e291447e98ac1362152d541d80676fac79b90199 Binary files /dev/null and b/data/samples/garments/garment_045.jpg differ diff --git a/data/samples/garments/garment_046.jpg b/data/samples/garments/garment_046.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f2e5245bd761b099c2e7539e53e933949cb25995 Binary files /dev/null and b/data/samples/garments/garment_046.jpg differ diff --git a/data/samples/garments/garment_047.jpg b/data/samples/garments/garment_047.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a69e0985a6cb7f08741741a9eb0cab6d0f70e7fa Binary files /dev/null and b/data/samples/garments/garment_047.jpg differ diff --git a/data/samples/garments/garment_048.jpg b/data/samples/garments/garment_048.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2f17c419b2b9d7155befb7350e27dd4dbabaecde Binary files /dev/null and b/data/samples/garments/garment_048.jpg differ diff --git a/data/samples/garments/garment_049.jpg b/data/samples/garments/garment_049.jpg new file mode 100644 index 0000000000000000000000000000000000000000..de7505aab4358f03fa01a4566a693baf5b3052e7 Binary files /dev/null and b/data/samples/garments/garment_049.jpg differ diff --git a/data/samples/garments/garment_050.jpg b/data/samples/garments/garment_050.jpg new file mode 100644 index 0000000000000000000000000000000000000000..70d2f8383a71afbb6181b5ba4fedaf43f9821878 Binary files /dev/null and b/data/samples/garments/garment_050.jpg differ diff --git a/scripts/build_sample_wardrobe.py b/scripts/build_sample_wardrobe.py new file mode 100644 index 0000000000000000000000000000000000000000..5b8832722c55a49730465e2030272e5f15fd4dff --- /dev/null +++ b/scripts/build_sample_wardrobe.py @@ -0,0 +1,194 @@ +"""Build a pre-processed sample wardrobe from Fashion-1K dataset. + +Downloads flat lay images from Codatta/Fashion-1K (HuggingFace), +runs the full detection + VLM pipeline, and saves the results to +data/samples/ for instant loading in the demo. + +Usage: + cd packages/wardrobe-us + .venv/bin/python scripts/build_sample_wardrobe.py + +Requires: datasets>=2.18.0 (pip install datasets) +""" + +import io +import json +import logging +import sys +import tempfile +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) + +from PIL import Image + +from src.detector import detect_and_crop +from src.vision import _extract_single_garment + +logging.basicConfig(level=logging.INFO, format="%(name)s | %(message)s") +logger = logging.getLogger("build_sample") + +SAMPLES_DIR = Path(__file__).resolve().parent.parent / "data" / "samples" +GARMENTS_DIR = SAMPLES_DIR / "garments" +CATALOG_PATH = SAMPLES_DIR / "catalog.json" + +TARGET_GARMENTS = 50 +MAX_IMAGES_TO_PROCESS = 40 + +# Indices hand-picked from Fashion-1K for variety (tops, bottoms, dresses, +# outerwear, shoes, accessories). If these don't yield enough garments, +# the script will continue with sequential images. +CURATED_INDICES = [ + 0, 5, 12, 18, 25, 33, 41, 50, 58, 67, + 75, 83, 91, 100, 110, 120, 130, 140, 150, 160, + 170, 180, 190, 200, 220, 240, 260, 280, 300, 320, + 350, 380, 400, 430, 460, 500, 550, 600, 650, 700, +] + + +def save_crop(garment_id: str, crop_bytes: bytes) -> str: + """Save a crop to the samples garments directory.""" + GARMENTS_DIR.mkdir(parents=True, exist_ok=True) + filename = f"{garment_id}.jpg" + path = GARMENTS_DIR / filename + path.write_bytes(crop_bytes) + return filename + + +def process_image(image: Image.Image, image_idx: int, catalog: list, garment_counter: int) -> int: + """Process a single source image through detection + VLM. + + Returns the updated garment counter. + """ + with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: + image.save(tmp, format="JPEG", quality=90) + tmp_path = tmp.name + + try: + crops = detect_and_crop(tmp_path) + except Exception as e: + logger.warning("Detection failed for image %d: %s", image_idx, e) + return garment_counter + + if not crops: + logger.info("Image %d: no garments detected, skipping", image_idx) + return garment_counter + + logger.info("Image %d: %d crops detected", image_idx, len(crops)) + + for crop_bytes in crops: + if garment_counter >= TARGET_GARMENTS: + break + + garment = _extract_single_garment(crop_bytes) + if not garment: + logger.debug(" Crop failed VLM extraction, skipping") + continue + + garment_counter += 1 + garment_id = f"garment_{garment_counter:03d}" + garment["id"] = garment_id + + image_ref = save_crop(garment_id, crop_bytes) + garment["image_ref"] = image_ref + + catalog.append(garment) + logger.info( + " [%d/%d] %s: %s %s (%s)", + garment_counter, TARGET_GARMENTS, + garment_id, garment.get("color", "?"), garment.get("type", "?"), + garment.get("pattern", "?"), + ) + + Path(tmp_path).unlink(missing_ok=True) + return garment_counter + + +def main(): + logger.info("=== Building Sample Wardrobe ===") + logger.info("Target: %d garments from Fashion-1K", TARGET_GARMENTS) + + try: + from datasets import load_dataset + except ImportError: + logger.error("'datasets' package not installed. Run: pip install datasets") + sys.exit(1) + + logger.info("Loading Codatta/Fashion-1K dataset...") + ds = load_dataset("Codatta/Fashion-1K", split="train") + logger.info("Dataset loaded: %d images", len(ds)) + + SAMPLES_DIR.mkdir(parents=True, exist_ok=True) + GARMENTS_DIR.mkdir(parents=True, exist_ok=True) + + catalog: list[dict] = [] + garment_counter = 0 + images_processed = 0 + + # Process curated indices first + for idx in CURATED_INDICES: + if garment_counter >= TARGET_GARMENTS: + break + if idx >= len(ds): + continue + + images_processed += 1 + if images_processed > MAX_IMAGES_TO_PROCESS: + break + + sample = ds[idx] + image = sample["image"] + if not isinstance(image, Image.Image): + continue + + if image.mode != "RGB": + image = image.convert("RGB") + + logger.info("--- Processing image %d (dataset idx %d) ---", images_processed, idx) + garment_counter = process_image(image, idx, catalog, garment_counter) + + # If we haven't reached target, try sequential + if garment_counter < TARGET_GARMENTS: + processed_indices = set(CURATED_INDICES) + for idx in range(len(ds)): + if garment_counter >= TARGET_GARMENTS: + break + if idx in processed_indices: + continue + if images_processed >= MAX_IMAGES_TO_PROCESS: + break + + images_processed += 1 + sample = ds[idx] + image = sample["image"] + if not isinstance(image, Image.Image): + continue + if image.mode != "RGB": + image = image.convert("RGB") + + logger.info("--- Processing image %d (dataset idx %d) ---", images_processed, idx) + garment_counter = process_image(image, idx, catalog, garment_counter) + + # Save catalog + with open(CATALOG_PATH, "w", encoding="utf-8") as f: + json.dump(catalog, f, indent=2, ensure_ascii=False) + + logger.info("=== Done ===") + logger.info("Total garments: %d", len(catalog)) + logger.info("Images processed: %d", images_processed) + logger.info("Catalog saved: %s", CATALOG_PATH) + logger.info("Garment images: %s", GARMENTS_DIR) + + # Print summary by type + types: dict[str, int] = {} + for g in catalog: + t = g.get("type", "unknown") + types[t] = types.get(t, 0) + 1 + + logger.info("Distribution by type:") + for t, count in sorted(types.items(), key=lambda x: -x[1]): + logger.info(" %s: %d", t, count) + + +if __name__ == "__main__": + main()