DavidNgoue commited on
Commit
97cf857
·
verified ·
1 Parent(s): 47b6ea1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +221 -108
app.py CHANGED
@@ -1,121 +1,234 @@
 
 
 
 
 
1
  import streamlit as st
2
- import pandas as pd
3
  import numpy as np
4
- from sklearn.ensemble import RandomForestClassifier
5
- from sklearn.preprocessing import StandardScaler
6
  import time
7
- import matplotlib.pyplot as plt
8
- import seaborn as sns
9
 
10
- # Fonction pour charger un modèle existant (à adapter selon ton besoin)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  def load_model():
12
- # Création d'un modèle simple pour la démonstration.
13
- model = RandomForestClassifier(n_estimators=100, random_state=42)
14
- return model
15
-
16
- # Fonction de pré-traitement des données
17
- def preprocess_data(temperature, humidity, water_level, N, P, K):
18
- data = np.array([[temperature, humidity, water_level, N, P, K]])
19
- scaler = StandardScaler()
20
- scaled_data = scaler.fit_transform(data)
21
- return scaled_data
22
-
23
- # Prédiction avec le modèle
24
- def make_prediction(model, data):
25
- prediction = model.predict(data)
26
- return prediction[0]
27
-
28
- # Interface Streamlit
29
- st.set_page_config(page_title="Prédiction de la pompe à eau", layout="wide")
30
- st.title("Prédiction de l'activation/désactivation de la pompe à eau")
31
- st.write("Remplissez le formulaire ci-dessous pour prédire si la pompe doit être désactivée.")
32
-
33
- # Utilisation de colonnes pour organiser les champs de saisie
34
- col1, col2 = st.columns(2)
 
 
 
 
35
 
36
  with col1:
37
- temperature = st.number_input("Température (°C)", min_value=-50, max_value=50, value=25, step=1)
38
- humidity = st.number_input("Humidité (%)", min_value=0, max_value=100, value=50, step=1)
39
- water_level = st.number_input("Niveau d'eau (%)", min_value=0, max_value=100, value=50, step=1)
40
 
41
  with col2:
42
- N = st.number_input("Concentration en Azote (N)", min_value=0, max_value=500, value=100, step=1)
43
- P = st.number_input("Concentration en Phosphore (P)", min_value=0, max_value=500, value=100, step=1)
44
- K = st.number_input("Concentration en Potassium (K)", min_value=0, max_value=500, value=100, step=1)
45
- fan_actuator_off = st.number_input("Fan Actuator OFF", min_value=0, max_value=1, value=0)
46
- water_plant_pump_on = st.number_input("Water Plant Pump ON", min_value=0, max_value=1, value=1)
47
-
48
- # Ajouter un bouton de prédiction avec animation
49
- if st.button('Faire la prédiction', use_container_width=True):
50
- with st.spinner('Traitement en cours...'):
51
- time.sleep(2)
52
-
 
 
 
53
  try:
54
- # Prétraitement des données
55
- data = preprocess_data(temperature, humidity, water_level, N, P, K)
56
-
57
- # Charger le modèle (ici un modèle fictif pour la démo)
58
- model = load_model()
59
-
60
- # Entraîner le modèle avec des données fictives
61
- X_train = np.random.rand(100, 6) # 100 exemples de données aléatoires
62
- y_train = np.random.choice([0, 1], 100) # Cible binaire
63
- model.fit(X_train, y_train)
64
-
65
- # Faire la prédiction
66
- prediction = make_prediction(model, data)
67
-
68
- # Affichage de la prédiction
69
- if prediction == 1:
70
- st.success("La pompe **doit être désactivée**.")
71
- else:
72
- st.warning("La pompe **doit être activée**.")
73
-
74
- # Animation des ballons après la prédiction
75
- st.balloons()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  except Exception as e:
78
- st.error(f"Erreur pendant la prédiction : {e}")
79
-
80
- # Section "Exemple de données"
81
- st.markdown("""
82
- ### Exemple de données
83
- - **Température** : 25°C
84
- - **Humidité** : 50%
85
- - **Niveau d'eau** : 50%
86
- - **Azote (N)** : 100 mg/L
87
- - **Phosphore (P)** : 100 mg/L
88
- - **Potassium (K)** : 100 mg/L
89
- - **Fan Actuator OFF** : 0
90
- - **Water Plant Pump ON** : 1
91
- """)
92
-
93
- # Ajouter un peu de style pour rendre l'interface plus jolie
94
- st.markdown("""
95
- <style>
96
- .css-1aumxhk {
97
- text-align: center;
98
- color: #2e7d32;
99
- font-size: 22px;
100
- font-weight: bold;
101
- }
102
- .stButton>button {
103
- background-color: #43a047;
104
- color: white;
105
- font-size: 18px;
106
- padding: 15px 30px;
107
- border-radius: 8px;
108
- }
109
- .stButton>button:hover {
110
- background-color: #388e3c;
111
- }
112
- </style>
113
- """, unsafe_allow_html=True)
114
 
115
- # Explication de l'objectif du projet
116
- st.markdown("""
117
- ### Objectif du Projet
118
- L'objectif de ce projet est de prédire l'état de la pompe à eau dans un système automatisé de gestion de l'irrigation.
119
- En utilisant des informations telles que la température, l'humidité, le niveau d'eau, et d'autres paramètres environnementaux et opérationnels,
120
- nous pouvons déterminer si la pompe doit être activée ou désactivée pour optimiser l'usage des ressources.
121
- """)
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ from torchvision import transforms
5
+ import cv2
6
  import streamlit as st
7
+ from PIL import Image
8
  import numpy as np
 
 
9
  import time
 
 
10
 
11
+ # Définition du modèle CNN
12
+ class EmotionCNN(nn.Module):
13
+ def __init__(self):
14
+ super(EmotionCNN, self).__init__()
15
+ self.conv_layers = nn.Sequential(
16
+ # Premier bloc
17
+ nn.Conv2d(1, 32, 3, padding=1),
18
+ nn.BatchNorm2d(32),
19
+ nn.ReLU(),
20
+ nn.Conv2d(32, 32, 3, padding=1),
21
+ nn.BatchNorm2d(32),
22
+ nn.ReLU(),
23
+ nn.MaxPool2d(2),
24
+ nn.Dropout2d(0.25),
25
+
26
+ # Deuxième bloc
27
+ nn.Conv2d(32, 64, 3, padding=1),
28
+ nn.BatchNorm2d(64),
29
+ nn.ReLU(),
30
+ nn.Conv2d(64, 64, 3, padding=1),
31
+ nn.BatchNorm2d(64),
32
+ nn.ReLU(),
33
+ nn.MaxPool2d(2),
34
+ nn.Dropout2d(0.25),
35
+
36
+ # Troisième bloc
37
+ nn.Conv2d(64, 128, 3, padding=1),
38
+ nn.BatchNorm2d(128),
39
+ nn.ReLU(),
40
+ nn.Conv2d(128, 128, 3, padding=1),
41
+ nn.BatchNorm2d(128),
42
+ nn.ReLU(),
43
+ nn.MaxPool2d(2),
44
+ nn.Dropout2d(0.25)
45
+ )
46
+
47
+ self.fc_layers = nn.Sequential(
48
+ nn.Linear(128 * 6 * 6, 512),
49
+ nn.ReLU(),
50
+ nn.Dropout(0.5),
51
+ nn.Linear(512, 256),
52
+ nn.ReLU(),
53
+ nn.Dropout(0.5),
54
+ nn.Linear(256, 8)
55
+ )
56
+
57
+ def forward(self, x):
58
+ x = self.conv_layers(x)
59
+ x = x.view(x.size(0), -1)
60
+ x = self.fc_layers(x)
61
+ return x
62
+
63
+ # Dictionnaire des émotions et leurs messages associés
64
+ emotion_dict = {
65
+ 0: {"name": "Colère", "message": "Respirez profondément et prenez un moment pour vous calmer."},
66
+ 1: {"name": "Mépris", "message": "Essayez de voir les choses d'un autre point de vue."},
67
+ 2: {"name": "Dégoût", "message": "Concentrez-vous sur les aspects positifs de la situation."},
68
+ 3: {"name": "Peur", "message": "Vous êtes en sécurité, prenez votre temps pour vous apaiser."},
69
+ 4: {"name": "Bonheur", "message": "Votre sourire illumine la pièce ! Continuez ainsi !"},
70
+ 5: {"name": "Neutre", "message": "Vous semblez calme et posé."},
71
+ 6: {"name": "Tristesse", "message": "Chaque jour est une nouvelle opportunité. Gardez espoir !"},
72
+ 7: {"name": "Surprise", "message": "La vie est pleine de surprises positives !"}
73
+ }
74
+
75
+ # Configuration de la page Streamlit
76
+ st.set_page_config(page_title="Détecteur d'Émotions", layout="wide")
77
+
78
+ # Styles CSS personnalisés
79
+ st.markdown("""
80
+ <style>
81
+ .main {
82
+ background-color: #f5f5f5;
83
+ }
84
+ .stButton>button {
85
+ background-color: #4CAF50;
86
+ color: white;
87
+ padding: 15px 32px;
88
+ text-align: center;
89
+ text-decoration: none;
90
+ display: inline-block;
91
+ font-size: 16px;
92
+ margin: 4px 2px;
93
+ cursor: pointer;
94
+ border-radius: 12px;
95
+ border: none;
96
+ transition-duration: 0.4s;
97
+ }
98
+ .stButton>button:hover {
99
+ background-color: #45a049;
100
+ }
101
+ .emotion-box {
102
+ padding: 20px;
103
+ border-radius: 10px;
104
+ background-color: white;
105
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
106
+ margin: 10px 0;
107
+ }
108
+ .emotion-title {
109
+ color: #333;
110
+ font-size: 24px;
111
+ font-weight: bold;
112
+ margin-bottom: 10px;
113
+ }
114
+ .emotion-message {
115
+ color: #666;
116
+ font-size: 18px;
117
+ line-height: 1.5;
118
+ }
119
+ </style>
120
+ """, unsafe_allow_html=True)
121
+
122
+ # Titre de l'application
123
+ st.title("🎭 Détecteur d'Émotions en Temps Réel")
124
+
125
+ # Initialisation du modèle
126
+ @st.cache_resource
127
  def load_model():
128
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
129
+ model = EmotionCNN().to(device)
130
+ model.load_state_dict(torch.load("cnn_emotion_model.pth", map_location=device))
131
+ model.eval()
132
+ return model, device
133
+
134
+ # Chargement du modèle
135
+ model, device = load_model()
136
+
137
+ # Transformations pour l'image
138
+ transform = transforms.Compose([
139
+ transforms.Grayscale(num_output_channels=1),
140
+ transforms.Resize((48, 48)),
141
+ transforms.ToTensor(),
142
+ transforms.Normalize(mean=[0.5], std=[0.5])
143
+ ])
144
+
145
+ # Chargement du classificateur Haar pour la détection de visage
146
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
147
+
148
+ def detect_faces(frame):
149
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
150
+ faces = face_cascade.detectMultiScale(gray, 1.1, 4)
151
+ return faces
152
+
153
+ # Configuration de la webcam
154
+ col1, col2 = st.columns([2, 1])
155
 
156
  with col1:
157
+ st.markdown("### 📹 Flux Vidéo")
158
+ frame_placeholder = st.empty()
 
159
 
160
  with col2:
161
+ st.markdown("### 😊 Émotion Détectée")
162
+ emotion_placeholder = st.empty()
163
+ message_placeholder = st.empty()
164
+
165
+ # Bouton pour démarrer/arrêter la détection
166
+ start_button = st.button("Démarrer la Détection")
167
+
168
+ if start_button:
169
+ cap = cv2.VideoCapture(0)
170
+
171
+ if not cap.isOpened():
172
+ st.error("❌ Impossible d'accéder à la webcam. Veuillez vérifier vos permissions.")
173
+ st.stop()
174
+
175
  try:
176
+ while True:
177
+ ret, frame = cap.read()
178
+ if not ret:
179
+ st.error("❌ Erreur lors de la capture vidéo.")
180
+ break
181
+
182
+ # Détection des visages
183
+ faces = detect_faces(frame)
184
+
185
+ # Traitement de chaque visage détecté
186
+ for (x, y, w, h) in faces:
187
+ # Dessiner la bounding box
188
+ cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
189
+
190
+ # Extraire et prétraiter le visage
191
+ face_img = frame[y:y+h, x:x+w]
192
+ pil_img = Image.fromarray(cv2.cvtColor(face_img, cv2.COLOR_BGR2RGB))
193
+
194
+ # Prédiction de l'émotion
195
+ img_tensor = transform(pil_img).unsqueeze(0).to(device)
196
+ with torch.no_grad():
197
+ output = model(img_tensor)
198
+ _, predicted = torch.max(output, 1)
199
+ emotion_idx = predicted.item()
200
+
201
+ # Afficher l'émotion sur l'image
202
+ emotion_name = emotion_dict[emotion_idx]["name"]
203
+ cv2.putText(frame, emotion_name, (x, y-10),
204
+ cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
205
+
206
+ # Mettre à jour l'affichage de l'émotion et du message
207
+ with emotion_placeholder:
208
+ st.markdown(f"""
209
+ <div class="emotion-box">
210
+ <div class="emotion-title">{emotion_name}</div>
211
+ </div>
212
+ """, unsafe_allow_html=True)
213
+
214
+ with message_placeholder:
215
+ st.markdown(f"""
216
+ <div class="emotion-box">
217
+ <div class="emotion-message">{emotion_dict[emotion_idx]["message"]}</div>
218
+ </div>
219
+ """, unsafe_allow_html=True)
220
+
221
+ # Afficher le flux vidéo
222
+ frame_placeholder.image(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
223
+
224
+ # Petite pause pour éviter une surcharge
225
+ time.sleep(0.1)
226
 
227
  except Exception as e:
228
+ st.error(f"Une erreur s'est produite : {str(e)}")
229
+
230
+ finally:
231
+ cap.release()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
 
233
+ else:
234
+ st.info("👆 Cliquez sur le bouton pour démarrer la détection d'émotions.")