Spaces:
Sleeping
Sleeping
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.") |