File size: 5,838 Bytes
03264f9
 
 
 
 
 
 
 
6031c78
a08355b
 
 
 
35e53c0
a08355b
 
 
 
 
 
 
 
 
 
b7e362f
 
 
 
a08355b
b7e362f
 
 
a08355b
 
b7e362f
 
 
 
 
 
 
a08355b
 
a03680b
a08355b
 
 
b7e362f
a08355b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6031c78
a08355b
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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.")