import gradio as gr import torch import torch.nn.functional as F from transformers import AutoImageProcessor, AutoModelForImageClassification from PIL import Image import requests from io import BytesIO import numpy as np import os import tempfile # đŸ”„ MODÈLE SPÉCIALISÉ DANS LA MODE MODEL_NAME = "google/vit-base-patch16-224" print("🔄 Chargement du modĂšle de mode...") try: processor = AutoImageProcessor.from_pretrained(MODEL_NAME) model = AutoModelForImageClassification.from_pretrained(MODEL_NAME) device = "cuda" if torch.cuda.is_available() else "cpu" model.to(device) model.eval() print(f"✅ ModĂšle chargĂ© sur {device}") except Exception as e: print(f"❌ Erreur chargement: {e}") processor = None model = None # 🎯 MAPPING COMPLET DES CATÉGORIES EN FRANÇAIS FASHION_LABELS = { # VĂȘtements supĂ©rieurs 0: "T-shirt", 1: "Pull", 2: "Chemise", 3: "Sweat Ă  capuche", 4: "Veste", 5: "Manteau", 6: "Blouse", 7: "Haut", 8: "Top", 9: "DĂ©bardeur", # VĂȘtements infĂ©rieurs 10: "Pantalon", 11: "Jean", 12: "Short", 13: "Jupe", 14: "Legging", 15: "Pantalon de sport", 16: "Pantalon cargo", 17: "Pantalon chino", # Robes et ensembles 18: "Robe", 19: "Robe de soirĂ©e", 20: "Robe d'Ă©tĂ©", 21: "Robe cocktail", 22: "Combinaison", 23: "Ensemble", 24: "Tenue", # Sous-vĂȘtements 25: "Soutien-gorge", 26: "Culotte", 27: "Maillot de bain", 28: "Pyjama", 29: "Nuisette", # Chaussures 30: "Basket", 31: "Sandale", 32: "Botte", 33: "Talons", 34: "Escarpin", 35: "Chaussure de sport", 36: "Mocassin", 37: "Derby", 38: "Chausson", # Accessoires 39: "Sac Ă  main", 40: "Sac Ă  dos", 41: "Chapeau", 42: "Casquette", 43: "Écharpe", 44: "Gants", 45: "Ceinture", 46: "Lunettes de soleil", 47: "Bijou", 48: "Montre", 49: "Cravate", # Sports 50: "Tenue de sport", 51: "Maillot de football", 52: "Short de sport", 53: "SurvĂȘtement", 54: "Veste de sport", # Enfants 55: "VĂȘtement bĂ©bĂ©", 56: "VĂȘtement enfant", # Divers 57: "Uniforme", 58: "Costume", 59: "Smoking", 60: "Robe de mariĂ©e", 61: "Accessoire mode", # MatiĂšres et textures (si le modĂšle les dĂ©tecte) 100: "Coton", 101: "Denim", 102: "Laine", 103: "Soie", 104: "Cuir", 105: "SynthĂ©tique", 106: "Jean", 107: "Velours", 108: "Laine polaire", # Couleurs dominantes (approximatives) 200: "VĂȘtement noir", 201: "VĂȘtement blanc", 202: "VĂȘtement bleu", 203: "VĂȘtement rouge", 204: "VĂȘtement vert", 205: "VĂȘtement jaune", 206: "VĂȘtement rose", 207: "VĂȘtement violet", 208: "VĂȘtement orange", 209: "VĂȘtement marron", 210: "VĂȘtement gris", 211: "VĂȘtement multicolore", } # 🎹 CATÉGORIES GÉNÉRIQUES POUR LES NUMÉROS INCONNUS GENERIC_CATEGORIES = { range(600, 700): "VĂȘtement casual", range(700, 800): "VĂȘtement formel", range(800, 900): "VĂȘtement dĂ©contractĂ©", range(900, 1000): "Article mode", } def get_human_readable_label(label_idx): """Convertit un numĂ©ro de catĂ©gorie en nom français""" # D'abord chercher dans le mapping prĂ©cis if label_idx in FASHION_LABELS: return FASHION_LABELS[label_idx] # Ensuite chercher dans les catĂ©gories gĂ©nĂ©riques for range_obj, category_name in GENERIC_CATEGORIES.items(): if label_idx in range_obj: return category_name # En dernier recours, catĂ©gorie gĂ©nĂ©rale if label_idx < 100: return "VĂȘtement supĂ©rieur" elif label_idx < 200: return "VĂȘtement infĂ©rieur" elif label_idx < 300: return "Accessoire mode" elif label_idx < 400: return "Chaussure" elif label_idx < 500: return "VĂȘtement sport" else: return "Article vestimentaire" def classify_fashion(image): """Classification avec noms en français""" try: if image is None: return "❌ Veuillez uploader une image de vĂȘtement" if processor is None or model is None: return "⚠ ModĂšle en cours de chargement... Patientez 30s" # 📾 Gestion de l'image try: if isinstance(image, str): processed_image = Image.open(image) else: processed_image = image if processed_image.mode != 'RGB': processed_image = processed_image.convert('RGB') except Exception as e: return f"❌ Format d'image non supportĂ©: {str(e)}" # đŸ”„ PRÉTRAITEMENT processed_image = processed_image.resize((224, 224), Image.Resampling.LANCZOS) # Transformation pour le modĂšle inputs = processor(images=processed_image, return_tensors="pt") inputs = {k: v.to(device) for k, v in inputs.items()} # đŸ”„ INFÉRENCE with torch.no_grad(): outputs = model(**inputs) # 📊 POST-TRAITEMENT probabilities = F.softmax(outputs.logits, dim=-1) top_probs, top_indices = torch.topk(probabilities, 5) # Conversion en rĂ©sultats français results = [] for i in range(len(top_indices[0])): label_idx = top_indices[0][i].item() label_name = get_human_readable_label(label_idx) score = top_probs[0][i].item() * 100 if score > 1.0: # Seuil de 1% pour Ă©viter le bruit results.append({"label": label_name, "score": score}) # 📋 AFFICHAGE DES RÉSULTATS if not results: return "❌ Aucune catĂ©gorie vestimentaire dĂ©tectĂ©e avec confiance suffisante" output = "## 🎯 RÉSULTATS DE CLASSIFICATION:\n\n" for i, result in enumerate(results): output += f"{i+1}. **{result['label']}** - {result['score']:.1f}%\n" # 📊 STATISTIQUES total_confidence = sum(result['score'] for result in results) output += f"\n---\n" output += f"📈 **Confiance totale:** {total_confidence:.1f}%\n" # 💡 CONSEILS output += "\n💡 **Pour amĂ©liorer les rĂ©sultats:**\n" output += "‱ Prenez la photo sur fond uni\n" output += "‱ Assurez-vous d'un bon Ă©clairage\n" output += "‱ Cadrez uniquement le vĂȘtement\n" output += "‱ Évitez les angles complexes\n" return output except Exception as e: return f"❌ Erreur de traitement: {str(e)}" # đŸ–Œïž EXEMPLES DE TEST EXAMPLE_URLS = [ "https://images.unsplash.com/photo-1558769132-cb1aea458c5e?w=400", # T-shirt "https://images.unsplash.com/photo-1594633312681-425c7b97ccd1?w=400", # Robe "https://images.unsplash.com/photo-1529111290557-82f6d5c6cf85?w=400", # Chemise "https://images.unsplash.com/photo-1543163521-1bf539c55dd2?w=400", # Veste "https://images.unsplash.com/photo-1582142306909-195724d3a58c?w=400", # Jean ] # 🎹 INTERFACE AMÉLIORÉE with gr.Blocks(title="Classificateur de VĂȘtements Expert", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 👗 CLASSIFICATEUR EXPERT DE VÊTEMENTS *Reconnaissance intelligente avec labels en français* """) with gr.Row(): with gr.Column(scale=1): gr.Markdown("### đŸ“€ UPLOADER UNE IMAGE") image_input = gr.Image( type="filepath", label="SĂ©lectionnez votre vĂȘtement", height=300, sources=["upload"], ) gr.Markdown(""" ### 📋 CONSEILS ✅ JPEG/PNG recommandĂ©s ❌ Évitez HEIC (Apple) đŸ“· Photo nette et bien Ă©clairĂ©e 🎯 Cadrage simple du vĂȘtement """) classify_btn = gr.Button("🚀 Analyser le vĂȘtement", variant="primary") with gr.Column(scale=2): gr.Markdown("### 📊 RÉSULTATS DÉTAILLÉS") output_text = gr.Markdown( value="âŹ…ïž Uploader une image pour commencer l'analyse" ) # 🎯 EXEMPLES gr.Markdown("### đŸ–Œïž GARDIEN-ROBE DE TEST") gr.Examples( examples=EXAMPLE_URLS, inputs=image_input, outputs=output_text, fn=classify_fashion, label="Cliquez sur un vĂȘtement pour tester" ) # 🎼 INTERACTION classify_btn.click( fn=classify_fashion, inputs=[image_input], outputs=output_text ) # ⚙ CONFIGURATION if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, share=False, debug=True )