import gradio as gr import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from matplotlib.figure import Figure # Charger ton modèle model = tf.keras.models.load_model("MobileNetV2_UL_ML_c3_l0_acc97_auc100_20251012_161415.keras") # Classes classes = ["Cubisme", "Expressionnisme", "Post-impressionnisme"] # Fonction de prédiction avec graphique personnalisé """def predire(image): # Prédiction image_resized = tf.image.resize(image, (224, 224)) / 255.0 preds = model.predict(tf.expand_dims(image_resized, axis=0))[0] # Créer le graphique avec matplotlib fig = Figure(figsize=(10, 6)) ax = fig.add_subplot(111) # Trier par probabilité décroissante sorted_indices = np.argsort(preds)[::-1] sorted_classes = [classes[i] for i in sorted_indices] sorted_probs = [preds[i] for i in sorted_indices] # Définir les couleurs : vert si > 50%, bleu sinon colors = ['#2ecc71' if prob >= 0.5 else '#bdc3c7' for prob in sorted_probs] # Créer le bar plot horizontal bars = ax.barh(sorted_classes, sorted_probs, color=colors, edgecolor='black', linewidth=1.5) # Ajouter les pourcentages sur les barres for i, (bar, prob) in enumerate(zip(bars, sorted_probs)): width = bar.get_width() label_x = width + 0.02 if width < 0.9 else width - 0.02 ha = 'left' if width < 0.9 else 'right' text_color = 'black' if width < 0.9 else 'white' ax.text(label_x, bar.get_y() + bar.get_height()/2, f'{prob*100:.1f}%', ha=ha, va='center', fontsize=12, fontweight='bold', color=text_color) # Configuration du graphique ax.set_xlabel('Probabilité', fontsize=12, fontweight='bold') ax.set_xlim(0, 1.0) ax.set_title('Probabilités par mouvement pictural', fontsize=14, fontweight='bold', pad=20) ax.grid(axis='x', alpha=0.3, linestyle='--') ax.set_axisbelow(True) # Légende from matplotlib.patches import Patch legend_elements = [ Patch(facecolor='#2ecc71', edgecolor='black', label='≥ 50%'), Patch(facecolor='#bdc3c7', edgecolor='black', label='< 50%') ] ax.legend(handles=legend_elements, loc='upper right', fontsize=10) fig.tight_layout() return fig""" # Solution 2 """def predire(image): image_resized = tf.image.resize(image, (224, 224)) / 255.0 preds = model.predict(tf.expand_dims(image_resized, axis=0))[0] sorted_indices = np.argsort(preds)[::-1] sorted_classes = [classes[i] for i in sorted_indices] sorted_probs = [preds[i] for i in sorted_indices] colors = ['#2ecc71' if prob >= 0.5 else '#bdc3c7' for prob in sorted_probs] fig = Figure(figsize=(4, 3)) # Format compact adapté mobile ax = fig.add_subplot(111) # Barres verticales bars = ax.bar(sorted_classes, sorted_probs, color=colors, edgecolor='black', linewidth=1.5) # Ajout pourcentages for bar, prob in zip(bars, sorted_probs): ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.03, f"{prob*100:.1f}%", ha='center', va='bottom', fontsize=13, fontweight='bold', color='black') ax.set_ylabel('Probabilité', fontsize=15, fontweight='bold') ax.set_ylim(0, 1.0) ax.set_title('Probabilités par mouvement pictural', fontsize=16, fontweight='bold', pad=20) ax.grid(axis='y', alpha=0.15, linestyle='--') ax.set_axisbelow(True) # Titres inclinés à 45° ax.set_xticklabels(sorted_classes, rotation=45, ha='right', fontsize=15, fontweight='bold') fig.tight_layout() return fig""" # Solution 3 : Passer par Plotly """import plotly.graph_objects as go def predire(image): image_resized = tf.image.resize(image, (224, 224)) / 255.0 preds = model.predict(tf.expand_dims(image_resized, axis=0))[0] sorted_indices = np.argsort(preds)[::-1] sorted_classes = [classes[i] for i in sorted_indices] sorted_probs = [preds[i] for i in sorted_indices] colors = ['#2ecc71' if prob >= 0.5 else '#bdc3c7' for prob in sorted_probs] fig = go.Figure(go.Bar( x=sorted_classes, y=sorted_probs, text=[f"{p*100:.1f}%" for p in sorted_probs], marker=dict(color=colors, line=dict(color='black', width=1)), textposition='auto', )) fig.update_layout( xaxis=dict(tickangle=45, tickfont=dict(size=17)), yaxis=dict(range=[0,1], title='Probabilité', tickfont=dict(size=17)), title="Probabilités par mouvement pictural", margin=dict(l=15, r=15, t=40, b=25), height=280, font=dict(size=17) ) return fig""" # Solution avec le graphique plus haut (ADAPTER LA HAUTEUR) """def predire(image): image_resized = tf.image.resize(image, (224, 224)) / 255.0 preds = model.predict(tf.expand_dims(image_resized, axis=0))[0] sorted_indices = np.argsort(preds)[::-1] sorted_classes = [classes[i] for i in sorted_indices] sorted_probs = [preds[i] for i in sorted_indices] colors = ['#2ecc71' if prob >= 0.5 else '#bdc3c7' for prob in sorted_probs] fig = Figure(figsize=(12, 4.2)) # hauteur augmentée ax = fig.add_subplot(111) bars = ax.bar(sorted_classes, sorted_probs, color=colors, edgecolor='black', linewidth=1.5) for bar, prob in zip(bars, sorted_probs): ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.035, f"{prob*100:.1f}%", ha='center', va='bottom', fontsize=12, color='black', fontweight='bold') ax.set_ylabel('Probabilité', fontsize=14, fontweight='bold') ax.set_ylim(0, 1) ax.set_title("Probabilités par mouvement pictural", fontsize=14, fontweight='bold', pad=20) ax.set_xticklabels(sorted_classes, rotation=45, ha='right', fontsize=13, fontweight='bold') fig.tight_layout(pad=2.0) return fig""" # Façon 5 uniquement sur le texte mais ça donne une erreur """def predire(image): image_resized = tf.image.resize(image, (224, 224)) / 255.0 preds = model.predict(tf.expand_dims(image_resized, axis=0))[0] sorted_indices = np.argsort(preds)[::-1] sorted_classes = [classes[i] for i in sorted_indices] sorted_probs = [preds[i] for i in sorted_indices] # HTML pour Gradio : barres remplies & label bars = [] for cls, prob in zip(sorted_classes, sorted_probs): color = "#2ecc71" if prob >= 0.5 else "#bdc3c7" bars.append(f'''