rkonan commited on
Commit
affa9e0
·
1 Parent(s): ab5bac6

amerlioration ihm

Browse files
Files changed (3) hide show
  1. .streamlit/config.toml +8 -1
  2. app/main.py +24 -5
  3. app/utils.py +34 -0
.streamlit/config.toml CHANGED
@@ -6,4 +6,11 @@ headless = true
6
  fileWatcherType = "watchdog"
7
 
8
  [browser]
9
- gatherUsageStats = false
 
 
 
 
 
 
 
 
6
  fileWatcherType = "watchdog"
7
 
8
  [browser]
9
+ gatherUsageStats = false
10
+
11
+ [theme]
12
+ base="dark"
13
+ primaryColor="#4CAF50"
14
+ backgroundColor="#0E1117"
15
+ secondaryBackgroundColor="#262730"
16
+ textColor="#FAFAFA"
app/main.py CHANGED
@@ -10,7 +10,7 @@ import logging
10
 
11
 
12
  confidence_threshold=0.4
13
- entropy_threshold=1.5
14
 
15
  logging.basicConfig(
16
  level=logging.DEBUG, # ou logging.DEBUG
@@ -356,10 +356,29 @@ if page == pages[4]:
356
  st.image(res['image_obj'], caption=f"Image : {res['file_name']}", use_container_width=True)
357
  st.markdown("### 🔍 Résultat de la prédiction")
358
  st.write(f"📁 Nom du fichier : `{res['file_name']}`")
359
- st.write(f"🏷️ Vraie classe (extrait nom) : `{res['true_class']}`")
360
- st.write(f"✅ Classe prédite : `{res['pred_class_name']}`")
361
- st.write(f"📊 Confiance : **{res['confidence']*100:.2f}%**")
362
- st.write(f"📈 Entropie : **{res['entropy']:.3f}**")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  if is_online:
364
  if "rapide" in mode_api:
365
  st.info(f"🧠 **{mode_api}** — 1 modèle utilisé : `{res['models_names'][0]}`")
 
10
 
11
 
12
  confidence_threshold=0.4
13
+ entropy_threshold=2
14
 
15
  logging.basicConfig(
16
  level=logging.DEBUG, # ou logging.DEBUG
 
356
  st.image(res['image_obj'], caption=f"Image : {res['file_name']}", use_container_width=True)
357
  st.markdown("### 🔍 Résultat de la prédiction")
358
  st.write(f"📁 Nom du fichier : `{res['file_name']}`")
359
+
360
+ predicted_classes = res['models_predictions']
361
+ unique_classes = set(predicted_classes)
362
+ if len(unique_classes) == 1 or not is_online:
363
+ pred_plant, pred_disease = res['pred_class_name'].split('_', 1)
364
+ st.success(f"🌱 **Plante predite :** `{pred_plant}`")
365
+ st.success(f"🩺 **Maladie predite :** `{pred_disease}`")
366
+ if len(predicted_classes)>1:
367
+ st.info("Prédiction fiable. Les modèles sont unanimes.")
368
+
369
+ true_plant, true_disease = extract_class_from_filename(res['file_name'])
370
+ if true_plant is not None and true_disease is not None:
371
+ with st.expander("🔍 **Vérité terrain :**"):
372
+ st.write(f"🌱 Plante réelle : `{true_plant}`")
373
+ st.write(f"🩺 Maladie réelle : `{true_disease}`")
374
+ else:
375
+ st.info("ℹ️ Vérité terrain non disponible pour cette image.")
376
+
377
+ st.write(f"📊 Confiance : **{res['confidence']*100:.2f}%**")
378
+ st.write(f"📈 Entropie : **{res['entropy']:.3f}**")
379
+ else:
380
+ st.warning(f"⚠️ Prédiction incertaine : `{res['pred_class_name']}`")
381
+ st.error("Les modèles ne sont pas d'accord. Veuillez vérifier l'image sur le terrain ou consulter un expert avant de décider d'un traitement.")
382
  if is_online:
383
  if "rapide" in mode_api:
384
  st.info(f"🧠 **{mode_api}** — 1 modèle utilisé : `{res['models_names'][0]}`")
app/utils.py CHANGED
@@ -92,6 +92,11 @@ class_names = [
92
  from typing import List, Any
93
  from collections import namedtuple
94
  from dataclasses import dataclass
 
 
 
 
 
95
  @dataclass
96
  class PredictionResult:
97
  pred_class_name: str
@@ -106,6 +111,35 @@ class PredictionResult:
106
  models_uncertainties: List[bool]
107
  gradcam_images: List[Any]
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  def predict_via_api(image_pil, api_url, mode="single",show_heatmap=False,default_model="EfficientNetV2M"):
111
  logging.info("🖼️ Préparation de l'image pour l'envoi à l'API...")
 
92
  from typing import List, Any
93
  from collections import namedtuple
94
  from dataclasses import dataclass
95
+
96
+
97
+
98
+
99
+
100
  @dataclass
101
  class PredictionResult:
102
  pred_class_name: str
 
111
  models_uncertainties: List[bool]
112
  gradcam_images: List[Any]
113
 
114
+ import re
115
+ import os
116
+
117
+ def extract_class_from_filename(filename):
118
+ """
119
+ Utilise une expression régulière pour extraire 'Plante - Maladie' depuis le nom de fichier.
120
+ Exemple de formats acceptés :
121
+ Rice___Blast___BLAST1_017.jpg
122
+ Blueberry___Healthy___0bfbcb95-30cb-487c-b9b9-49e4edd4af9f___RS_HL 0534.JPG
123
+ Peach___Bacterial_spot___0a620811-30ba-42bf-ace2-8888d4db6dcd___Rutg._Bact.S 1782.JPG
124
+ """
125
+ try:
126
+ base_name = os.path.basename(filename)
127
+ name_without_ext = os.path.splitext(base_name)[0]
128
+
129
+ # Regex : on cherche une structure 'texte - texte'
130
+ match = re.search(r'^([A-Za-z]+)_+([A-Za-z_]+)', name_without_ext)
131
+
132
+ if match:
133
+ plant = match.group(1).strip()
134
+ disease = match.group(2).strip()
135
+ return plant, disease
136
+ else:
137
+ return None, None
138
+ except Exception as e:
139
+ print(f"Erreur d'extraction : {e}")
140
+ return None, None
141
+
142
+
143
 
144
  def predict_via_api(image_pil, api_url, mode="single",show_heatmap=False,default_model="EfficientNetV2M"):
145
  logging.info("🖼️ Préparation de l'image pour l'envoi à l'API...")