Eric2mangel commited on
Commit
28737e2
·
1 Parent(s): 2e7922b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +164 -1
app.py CHANGED
@@ -3,6 +3,169 @@ import tensorflow as tf
3
  import numpy as np
4
  import plotly.graph_objects as go
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  # === Charger les trois modèles binaires ===
7
  model_cubisme = tf.keras.models.load_model("Cubisme_MobileNetV2_UL_c2_l0_v96_20251013_114051.keras")
8
  model_expressionnisme = tf.keras.models.load_model("Expressionnisme_MobileNetV2_UL_c2_l0_v84_20251012_232500.keras")
@@ -121,7 +284,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
121
  "à un mouvement pictural. Les barres vertes indiquent une reconnaissance ≥ 50%."
122
  )
123
 
124
- demo.launch()
125
 
126
  """
127
  # Première version
 
3
  import numpy as np
4
  import plotly.graph_objects as go
5
 
6
+ # ============================================================================
7
+ # CONFIGURATION GLOBALE - Modifiez uniquement cette section
8
+ # ============================================================================
9
+
10
+ MOUVEMENTS_CONFIG = {
11
+ "Cubisme": {
12
+ "modele": "Cubisme_MobileNetV2_UL_c2_l0_v96_20251013_114051.keras",
13
+ "couleur": "#2ecc71" # Vert
14
+ },
15
+ "Expressionnisme": {
16
+ "modele": "Expressionnisme_MobileNetV2_UL_c2_l0_v84_20251012_232500.keras",
17
+ "couleur": "#2ecc71" # Vert
18
+ },
19
+ "Post-impressionnisme": {
20
+ "modele": "Postimpressionnisme_MobileNetV2_UL_c2_l0_v89_20251013_111049.keras",
21
+ "couleur": "#2ecc71" # Vert
22
+ }
23
+ # Pour ajouter un nouveau mouvement, décommentez et modifiez :
24
+ # "Surréalisme": {
25
+ # "modele": "Surrealisme_MobileNetV2_v1.keras",
26
+ # "couleur": "#3498db" # Bleu
27
+ # }
28
+ }
29
+
30
+ # Seuil de reconnaissance (probabilité minimale pour afficher un mouvement)
31
+ SEUIL_RECONNAISSANCE = 0.5 # 50%
32
+
33
+ # Paramètres visuels du graphique
34
+ LARGEUR_BARRES = 0.4
35
+ HAUTEUR_GRAPHIQUE = 600
36
+
37
+ # ============================================================================
38
+ # FIN DE LA CONFIGURATION - Ne modifiez pas le code ci-dessous
39
+ # ============================================================================
40
+
41
+ # === Charger les modèles dynamiquement ===
42
+ modeles_disponibles = {}
43
+ for mouvement, config in MOUVEMENTS_CONFIG.items():
44
+ try:
45
+ modeles_disponibles[mouvement] = tf.keras.models.load_model(config["modele"])
46
+ print(f"✓ Modèle '{mouvement}' chargé avec succès")
47
+ except Exception as e:
48
+ print(f"✗ Erreur lors du chargement du modèle '{mouvement}': {e}")
49
+
50
+ # Liste des mouvements disponibles (pour l'interface)
51
+ MOUVEMENTS_DISPONIBLES = list(MOUVEMENTS_CONFIG.keys())
52
+
53
+ # === Fonction de prédiction ===
54
+ def predire(image, mouvements_selectionnes):
55
+ # Vérifier qu'au moins un mouvement est sélectionné
56
+ if not mouvements_selectionnes:
57
+ return None, gr.update(value="⚠️ **Veuillez sélectionner au moins un mouvement pictural à analyser.**", visible=True)
58
+
59
+ # Prétraitement
60
+ image_resized = tf.image.resize(image, (224, 224)) / 255.0
61
+ image_batch = tf.expand_dims(image_resized, axis=0)
62
+
63
+ # Prédictions uniquement pour les modèles sélectionnés
64
+ resultats = {}
65
+ for mouvement in mouvements_selectionnes:
66
+ modele = modeles_disponibles[mouvement]
67
+ prob = float(modele.predict(image_batch, verbose=0)[0][0])
68
+ resultats[mouvement] = prob
69
+
70
+ # Filtrer les mouvements reconnus (≥ seuil)
71
+ mouvements_reconnus = {m: p for m, p in resultats.items() if p >= SEUIL_RECONNAISSANCE}
72
+
73
+ # Si aucun mouvement n'atteint le seuil
74
+ if not mouvements_reconnus:
75
+ return None, gr.update(value=f"❌ **Aucun des mouvements picturaux sélectionnés n'a été reconnu** (seuil : {SEUIL_RECONNAISSANCE*100:.0f}%).", visible=True)
76
+
77
+ # Tri par probabilité décroissante
78
+ mouvements_tries = sorted(mouvements_reconnus.items(), key=lambda x: x[1], reverse=True)
79
+ classes_triees = [m for m, _ in mouvements_tries]
80
+ probs_triees = [p for _, p in mouvements_tries]
81
+
82
+ # Couleurs selon la configuration
83
+ colors = [MOUVEMENTS_CONFIG[m]["couleur"] for m in classes_triees]
84
+
85
+ # === Construction du graphique ===
86
+ fig = go.Figure(go.Bar(
87
+ x=classes_triees,
88
+ y=probs_triees,
89
+ marker=dict(color=colors, line=dict(color='black', width=1)),
90
+ text=[f"{p*100:.1f}%" for p in probs_triees],
91
+ textposition='auto',
92
+ width=LARGEUR_BARRES
93
+ ))
94
+
95
+ fig.update_layout(
96
+ xaxis=dict(
97
+ fixedrange=True,
98
+ tickangle=45,
99
+ tickfont=dict(size=15),
100
+ automargin=True
101
+ ),
102
+ yaxis=dict(
103
+ fixedrange=True,
104
+ range=[0, 1],
105
+ title="Probabilité",
106
+ tickfont=dict(size=14)
107
+ ),
108
+ title=dict(
109
+ text=f"Mouvements picturaux<br>reconnus (≥ {SEUIL_RECONNAISSANCE*100:.0f}%)",
110
+ y=0.90,
111
+ pad=dict(b=30)
112
+ ),
113
+ margin=dict(l=60, r=60, t=80, b=80),
114
+ height=HAUTEUR_GRAPHIQUE,
115
+ width=500,
116
+ font=dict(size=13)
117
+ )
118
+
119
+ fig.data[0].textfont = dict(color='black', size=14, family="Arial")
120
+
121
+ return fig, gr.update(visible=False)
122
+
123
+ # === Interface Gradio ===
124
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
125
+ gr.Markdown(f"# 🎨 Classification de style pictural ({len(MOUVEMENTS_DISPONIBLES)} mouvements)")
126
+ gr.Markdown(
127
+ f"Sélectionnez les mouvements picturaux à analyser. "
128
+ f"Seuls ceux atteignant une probabilité ≥ {SEUIL_RECONNAISSANCE*100:.0f}% seront affichés."
129
+ )
130
+
131
+ with gr.Row():
132
+ with gr.Column(scale=1):
133
+ image_input = gr.Image(type="numpy", label="Importer une œuvre")
134
+
135
+ mouvements_checkbox = gr.CheckboxGroup(
136
+ choices=MOUVEMENTS_DISPONIBLES,
137
+ value=MOUVEMENTS_DISPONIBLES,
138
+ label="Mouvements à analyser",
139
+ info="Cochez les mouvements picturaux à tester"
140
+ )
141
+
142
+ analyser_btn = gr.Button("🔍 Analyser", variant="primary", size="lg")
143
+
144
+ with gr.Column(scale=1):
145
+ output_plot = gr.Plot(label="Résultats de la classification")
146
+ output_message = gr.Markdown(visible=False)
147
+
148
+ analyser_btn.click(
149
+ fn=predire,
150
+ inputs=[image_input, mouvements_checkbox],
151
+ outputs=[output_plot, output_message]
152
+ )
153
+
154
+ gr.Markdown(
155
+ "---\n"
156
+ f"**Note :** Chaque CNN évalue indépendamment la probabilité d'appartenance "
157
+ f"à un mouvement pictural. Les barres colorées indiquent une reconnaissance ≥ {SEUIL_RECONNAISSANCE*100:.0f}%."
158
+ )
159
+
160
+ demo.launch()
161
+
162
+ """
163
+ VERSION 2 avec sélection des mouvements et affichage des graphiques uniquement pour les mouvements reconnus
164
+ import gradio as gr
165
+ import tensorflow as tf
166
+ import numpy as np
167
+ import plotly.graph_objects as go
168
+
169
  # === Charger les trois modèles binaires ===
170
  model_cubisme = tf.keras.models.load_model("Cubisme_MobileNetV2_UL_c2_l0_v96_20251013_114051.keras")
171
  model_expressionnisme = tf.keras.models.load_model("Expressionnisme_MobileNetV2_UL_c2_l0_v84_20251012_232500.keras")
 
284
  "à un mouvement pictural. Les barres vertes indiquent une reconnaissance ≥ 50%."
285
  )
286
 
287
+ demo.launch()"""
288
 
289
  """
290
  # Première version