Spaces:
Sleeping
Sleeping
| import os | |
| # Fix pour les erreurs de permission Streamlit sur Hugging Face | |
| if "HOME" not in os.environ or os.environ["HOME"] == "/": | |
| os.environ["HOME"] = "/tmp" | |
| os.makedirs("/tmp/.streamlit", exist_ok=True) | |
| import streamlit as st | |
| import cv2 | |
| import numpy as np | |
| from PIL import Image | |
| st.set_page_config(layout="wide") | |
| st.title("Détection et Isolation de Couleurs sur Image") | |
| st.sidebar.header("Paramètres de l'image et de la couleur") | |
| # 1. Téléchargement de l'image | |
| uploaded_file = st.sidebar.file_uploader("Choisissez une image...", type=["jpg", "jpeg", "png"]) | |
| if uploaded_file is not None: | |
| # --- DÉBUT DU BLOC DE TRAITEMENT LORSQU'UNE IMAGE EST TÉLÉCHARGÉE --- | |
| st.sidebar.success("Fichier chargé avec succès !") # Pour confirmer que le fichier est bien là | |
| # Lire le fichier BINAIRE UNE SEULE FOIS ici | |
| file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8) | |
| st.sidebar.text(f"Taille du fichier en bytes: {len(file_bytes)}") # Vérifier si les bytes sont lus | |
| # Décodage de l'image BGR avec OpenCV | |
| img_bgr = cv2.imdecode(file_bytes, 1) | |
| if img_bgr is None: | |
| st.sidebar.error("Impossible de décoder l'image. Est-ce un format supporté ?") | |
| st.stop() # Arrête l'exécution du script Streamlit pour ce cycle | |
| else: | |
| st.sidebar.success(f"Image décodée. Dimensions: {img_bgr.shape}") | |
| # Convertir BGR en RGB pour l'affichage Streamlit (image originale) | |
| img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) | |
| st.subheader("Image Originale") | |
| st.image(img_rgb, caption="Image Originale", use_column_width=True) | |
| # 2. Choix de la couleur (tout le reste du code de traitement est maintenant ici) | |
| color_choice = st.sidebar.selectbox( | |
| "Choisissez une couleur prédéfinie ou personnalisée :", | |
| ("Bleu", "Vert", "Rouge", "Jaune", "Orange", "Violet", "Personnalisé") | |
| ) | |
| h_lower, s_lower, v_lower = 0, 0, 0 | |
| h_upper, s_upper, v_upper = 179, 255, 255 | |
| if color_choice == "Bleu": | |
| lower_bound = np.array([100, 150, 0]) | |
| upper_bound = np.array([140, 255, 255]) | |
| elif color_choice == "Vert": | |
| lower_bound = np.array([40, 50, 50]) | |
| upper_bound = np.array([80, 255, 255]) | |
| elif color_choice == "Rouge": | |
| # Le rouge est spécial car il chevauche le 0/179 sur le cercle chromatique HSV | |
| # Il faut généralement deux plages pour le rouge pur | |
| st.sidebar.warning("Le rouge peut nécessiter deux plages HSV. Cette démo utilise une plage simple.") | |
| lower_bound = np.array([0, 100, 100]) | |
| upper_bound = np.array([10, 255, 255]) | |
| # Second range for red (optional, for more complete red detection) | |
| # lower_red2 = np.array([160, 100, 100]) | |
| # upper_red2 = np.array([179, 255, 255]) | |
| elif color_choice == "Jaune": | |
| lower_bound = np.array([20, 100, 100]) | |
| upper_bound = np.array([40, 255, 255]) | |
| elif color_choice == "Orange": | |
| lower_bound = np.array([10, 100, 100]) | |
| upper_bound = np.array([25, 255, 255]) | |
| elif color_choice == "Violet": | |
| lower_bound = np.array([130, 50, 50]) | |
| upper_bound = np.array([160, 255, 255]) | |
| elif color_choice == "Personnalisé": | |
| st.sidebar.subheader("Définir la plage HSV personnalisée") | |
| h_lower = st.sidebar.slider("Teinte (H) Min", 0, 179, 0) | |
| h_upper = st.sidebar.slider("Teinte (H) Max", 0, 179, 179) | |
| s_lower = st.sidebar.slider("Saturation (S) Min", 0, 255, 0) | |
| s_upper = st.sidebar.slider("Saturation (S) Max", 0, 255, 255) | |
| v_lower = st.sidebar.slider("Valeur (V) Min", 0, 255, 0) | |
| v_upper = st.sidebar.slider("Valeur (V) Max", 0, 255, 255) | |
| lower_bound = np.array([h_lower, s_lower, v_lower]) | |
| upper_bound = np.array([h_upper, s_upper, v_upper]) | |
| if uploaded_file is not None: | |
| # Convertir l'image BGR en HSV | |
| hsv_image = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV) | |
| # Créer un masque pour la couleur sélectionnée | |
| mask = cv2.inRange(hsv_image, lower_bound, upper_bound) | |
| # Appliquer le masque à l'image originale | |
| # On utilise bitwise_and pour n'afficher que les pixels qui correspondent au masque | |
| isolated_color_bgr = cv2.bitwise_and(img_bgr, img_bgr, mask=mask) | |
| # Convertir le résultat en RGB pour l'affichage Streamlit | |
| isolated_color_rgb = cv2.cvtColor(isolated_color_bgr, cv2.COLOR_BGR2RGB) | |
| st.subheader(f"Couleur isolée : {color_choice}") | |
| st.image(isolated_color_rgb, caption=f"{color_choice} isolé", use_column_width=True) | |
| st.subheader("Masque généré") | |
| st.image(mask, caption="Masque (blanc = couleur détectée)", use_column_width=True) | |
| st.markdown(""" | |
| **Comment ça marche ?** | |
| 1. **Conversion HSV :** L'image originale est convertie de l'espace couleur BGR (utilisé par OpenCV) à HSV (Teinte, Saturation, Valeur). HSV est idéal pour la détection de couleurs car la teinte (H) isole la couleur elle-même, indépendamment de la luminosité ou de l'intensité. | |
| 2. **Définition de la Plage HSV :** Pour chaque couleur, une plage inférieure (`lower_bound`) et une plage supérieure (`upper_bound`) sont définies en termes de valeurs H, S et V. | |
| 3. **Création du Masque :** La fonction `cv2.inRange()` est utilisée pour créer un masque binaire. Tous les pixels de l'image HSV qui tombent dans la plage définie obtiennent une valeur de 255 (blanc), les autres 0 (noir). | |
| 4. **Application du Masque :** La fonction `cv2.bitwise_and()` combine l'image originale avec le masque. Seuls les pixels où le masque est blanc sont conservés de l'image originale ; les autres deviennent noirs. | |
| """) | |
| else: | |
| st.info("Veuillez télécharger une image pour commencer.") |