walidchaib commited on
Commit
fd204ac
·
verified ·
1 Parent(s): 1e005e2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -0
app.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ================================
2
+ # 0. PATCH pour huggingface_hub (contourne l'absence de HfFolder)
3
+ # ================================
4
+ import huggingface_hub
5
+ if not hasattr(huggingface_hub, 'HfFolder'):
6
+ class HfFolder:
7
+ _token = None
8
+ @staticmethod
9
+ def get_token():
10
+ return HfFolder._token
11
+ @staticmethod
12
+ def save_token(token):
13
+ HfFolder._token = token
14
+ huggingface_hub.HfFolder = HfFolder
15
+
16
+ # ================================
17
+ # 1. PATCH pour contourner le bug de Gradio 4.44.0
18
+ # (TypeError: argument of type 'bool' is not iterable)
19
+ # ================================
20
+ import gradio_client.utils
21
+
22
+ original_get_type = gradio_client.utils.get_type
23
+
24
+ def patched_get_type(schema):
25
+ if isinstance(schema, bool):
26
+ return "boolean"
27
+ return original_get_type(schema)
28
+
29
+ gradio_client.utils.get_type = patched_get_type
30
+
31
+ # ================================
32
+ # 2. IMPORTS STANDARDS
33
+ # ================================
34
+ import gradio as gr
35
+ import tensorflow as tf
36
+ import numpy as np
37
+ from PIL import Image
38
+
39
+ # ================================
40
+ # 3. CHARGEMENT DU MODÈLE (72 classes)
41
+ # ================================
42
+ MODEL_PATH = "final_model.keras"
43
+ model = tf.keras.models.load_model(MODEL_PATH)
44
+
45
+ # ================================
46
+ # 4. NOMS DES CLASSES (issus de l'entraînement)
47
+ # ================================
48
+ class_names = [
49
+ "Apple___alternaria_leaf_spot",
50
+ "Apple___black_rot",
51
+ "Apple___brown_spot",
52
+ "Apple___gray_spot",
53
+ "Apple___healthy",
54
+ "Apple___rust",
55
+ "Apple___scab",
56
+ "Bell_pepper___bacterial_spot",
57
+ "Bell_pepper___healthy",
58
+ "Blueberry___healthy",
59
+ "Cassava___bacterial_blight",
60
+ "Cassava___brown_streak_disease",
61
+ "Cassava___green_mottle",
62
+ "Cassava___healthy",
63
+ "Cassava___mosaic_disease",
64
+ "Cherry___healthy",
65
+ "Cherry___powdery_mildew",
66
+ "Coffee___healthy",
67
+ "Coffee___red_spider_mite",
68
+ "Coffee___rust",
69
+ "Corn___common_rust",
70
+ "Corn___gray_leaf_spot",
71
+ "Corn___healthy",
72
+ "Corn___northern_leaf_blight",
73
+ "Grape___Leaf_blight",
74
+ "Grape___black_measles",
75
+ "Grape___black_rot",
76
+ "Grape___healthy",
77
+ "Orange___citrus_greening",
78
+ "Peach___bacterial_spot",
79
+ "Peach___healthy",
80
+ "Potato___bacterial_wilt",
81
+ "Potato___early_blight",
82
+ "Potato___healthy",
83
+ "Potato___late_blight",
84
+ "Potato___leafroll_virus",
85
+ "Potato___mosaic_virus",
86
+ "Potato___nematode",
87
+ "Potato___pests",
88
+ "Potato___phytophthora",
89
+ "Raspberry___healthy",
90
+ "Rice___bacterial_blight",
91
+ "Rice___blast",
92
+ "Rice___brown_spot",
93
+ "Rice___tungro",
94
+ "Rose___healthy",
95
+ "Rose___rust",
96
+ "Rose___slug_sawfly",
97
+ "Soybean___healthy",
98
+ "Squash___powdery_mildew",
99
+ "Strawberry___healthy",
100
+ "Strawberry___leaf_scorch",
101
+ "Sugercane___healthy",
102
+ "Sugercane___mosaic",
103
+ "Sugercane___red_rot",
104
+ "Sugercane___rust",
105
+ "Sugercane___yellow_leaf",
106
+ "Tomato___bacterial_spot",
107
+ "Tomato___early_blight",
108
+ "Tomato___healthy",
109
+ "Tomato___late_blight",
110
+ "Tomato___leaf_curl",
111
+ "Tomato___leaf_mold",
112
+ "Tomato___mosaic_virus",
113
+ "Tomato___septoria_leaf_spot",
114
+ "Tomato___spider_mites",
115
+ "Tomato___target_spot",
116
+ "Watermelon___anthracnose",
117
+ "Watermelon___downy_mildew",
118
+ "Watermelon___healthy",
119
+ "Watermelon___mosa"
120
+ ]
121
+
122
+ # ================================
123
+ # 5. FONCTION DE PRÉDICTION
124
+ # ================================
125
+ def preprocess_image(img):
126
+ """Redimensionne et normalise l'image pour le modèle EfficientNet."""
127
+ img = img.resize((224, 224))
128
+ img_array = np.array(img)
129
+ img_array = tf.keras.applications.efficientnet.preprocess_input(img_array)
130
+ img_array = np.expand_dims(img_array, axis=0)
131
+ return img_array
132
+
133
+ def predict(img):
134
+ """
135
+ img : image PIL fournie par gr.Image(type="pil")
136
+ Retourne un dictionnaire {classe: probabilité} pour le composant gr.Label
137
+ """
138
+ processed = preprocess_image(img)
139
+ preds = model.predict(processed, verbose=0)[0]
140
+ # Créer le dictionnaire des probabilités
141
+ results = {class_names[i]: float(preds[i]) for i in range(len(class_names))}
142
+ return results
143
+
144
+ # ================================
145
+ # 6. INTERFACE GRADIO
146
+ # ================================
147
+ iface = gr.Interface(
148
+ fn=predict,
149
+ inputs=gr.Image(type="pil", label="Chargez une image de feuille"),
150
+ outputs=gr.Label(num_top_classes=3, label="Maladie prédite (top 3)"),
151
+ title="Classification des maladies des plantes (72 classes)",
152
+ description="Chargez une photo de feuille et le modèle prédira la maladie parmi 72 classes. Modèle basé sur EfficientNetB0 avec fine-tuning.",
153
+ examples=None,
154
+ allow_flagging="never"
155
+ )
156
+
157
+ if __name__ == "__main__":
158
+ iface.launch(share=True)