raysarocha commited on
Commit
11e7296
·
verified ·
1 Parent(s): 541e902

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +209 -122
app.py CHANGED
@@ -8,78 +8,125 @@ from huggingface_hub import hf_hub_download
8
  # ============================================
9
  # Configurações do modelo
10
  # ============================================
11
- REPO_ID = "raysarocha/plant-resnet50-38classes" # Seu repositório
12
 
13
  # ============================================
14
  # Carregamento do modelo
15
  # ============================================
16
- print("🔄 Carregando modelo...")
17
-
18
- # Baixa os arquivos
19
- cfg_path = hf_hub_download(REPO_ID, "config.json")
20
- model_path = hf_hub_download(REPO_ID, "model.keras")
21
-
22
- # Carrega configuração
23
- with open(cfg_path, "r") as f:
24
- cfg = json.load(f)
 
 
 
 
 
 
 
 
 
25
 
26
- # Carrega modelo
27
- model = tf.keras.models.load_model(model_path)
28
- print("✅ Modelo carregado com sucesso!")
29
 
30
  # ============================================
31
- # Dicionário de nomes amigáveis
32
  # ============================================
33
- FRIENDLY_NAMES = {
34
- "Apple___Apple_scab": "🍎 Maçã - Sarna",
35
- "Apple___Black_rot": "🍎 Maçã - Podridão negra",
36
- "Apple___Cedar_apple_rust": "🍎 Maçã - Ferrugem do cedro",
37
- "Apple___healthy": "🍎 Maçã - Saudável",
38
- "Blueberry___healthy": "🫐 Mirtilo - Saudável",
39
- "Cherry_(including_sour)___Powdery_mildew": "🍒 Cereja - Oídio",
40
- "Cherry_(including_sour)___healthy": "🍒 Cereja - Saudável",
41
- "Corn_(maize)___Cercospora_leaf_spot Gray_leaf_spot": "🌽 Milho - Mancha de Cercospora",
42
- "Corn_(maize)___Common_rust_": "🌽 Milho - Ferrugem comum",
43
- "Corn_(maize)___Northern_Leaf_Blight": "🌽 Milho - Queima das folhas",
44
- "Corn_(maize)___healthy": "🌽 Milho - Saudável",
45
- "Grape___Black_rot": "🍇 Uva - Podridão negra",
46
- "Grape___Esca_(Black_Measles)": "🍇 Uva - Esca",
47
- "Grape___Leaf_blight_(Isariopsis_Leaf_Spot)": "🍇 Uva - Queima das folhas",
48
- "Grape___healthy": "🍇 Uva - Saudável",
49
- "Orange___Haunglongbing_(Citrus_greening)": "🍊 Laranja - Greening",
50
- "Peach___Bacterial_spot": "🍑 Pêssego - Mancha bacteriana",
51
- "Peach___healthy": "🍑 Pêssego - Saudável",
52
- "Pepper,_bell___Bacterial_spot": "🫑 Pimentão - Mancha bacteriana",
53
- "Pepper,_bell___healthy": "🫑 Pimentão - Saudável",
54
- "Potato___Early_blight": "🥔 Batata - Requeima precoce",
55
- "Potato___Late_blight": "🥔 Batata - Requeima tardia",
56
- "Potato___healthy": "🥔 Batata - Saudável",
57
- "Raspberry___healthy": "🫐 Framboesa - Saudável",
58
- "Soybean___healthy": "🌱 Soja - Saudável",
59
- "Squash___Powdery_mildew": "🎃 Abóbora - Oídio",
60
- "Strawberry___Leaf_scorch": "🍓 Morango - Queima das folhas",
61
- "Strawberry___healthy": "🍓 Morango - Saudável",
62
- "Tomato___Bacterial_spot": "🍅 Tomate - Mancha bacteriana",
63
- "Tomato___Early_blight": "🍅 Tomate - Requeima precoce",
64
- "Tomato___Late_blight": "🍅 Tomate - Requeima tardia",
65
- "Tomato___Leaf_Mold": "🍅 Tomate - Mofo das folhas",
66
- "Tomato___Septoria_leaf_spot": "🍅 Tomate - Mancha de Septoria",
67
- "Tomato___Spider_mites Two-spotted_spider_mite": "🍅 Tomate - Ácaros",
68
- "Tomato___Target_Spot": "🍅 Tomate - Mancha alvo",
69
- "Tomato___Tomato_Yellow_Leaf_Curl_Virus": "🍅 Tomate - Vírus do enrolamento",
70
- "Tomato___Tomato_mosaic_virus": "🍅 Tomate - Vírus do mosaico",
71
- "Tomato___healthy": "🍅 Tomate - Saudável"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  # ============================================
75
  # Função de classificação
76
  # ============================================
77
  def classify_plant(image):
78
- """
79
- Classifica a imagem da planta e retorna diagnóstico
80
- """
81
  if image is None:
82
- return None, "Por favor, faça upload de uma imagem!"
83
 
84
  # Preprocessamento
85
  img = Image.fromarray(image).convert("RGB")
@@ -94,123 +141,163 @@ def classify_plant(image):
94
  # Top 5 resultados
95
  top_5_idx = np.argsort(probs)[-5:][::-1]
96
 
97
- # Formata resultados para o Gradio
98
  results = {}
99
  for idx in top_5_idx:
100
  class_name = cfg["id2label"][str(idx)]
101
- friendly_name = FRIENDLY_NAMES.get(class_name, class_name)
 
102
  confidence = float(probs[idx])
103
  results[friendly_name] = confidence
104
 
105
- # Mensagem de diagnóstico
106
  top_class = cfg["id2label"][str(top_5_idx[0])]
107
  top_confidence = float(probs[top_5_idx[0]])
 
108
 
109
- if "healthy" in top_class.lower():
110
- status = "✅ Planta Saudável!"
111
- message = f"Sua planta parece estar saudável! (Confiança: {top_confidence:.1%})"
112
- color = "green"
 
 
113
  else:
114
- status = "⚠️ Doença Detectada"
115
- message = f"Possível problema detectado. (Confiança: {top_confidence:.1%})"
116
- color = "orange"
117
-
118
- diagnosis = f"""
119
- <div style='padding: 20px; border-radius: 10px; background-color: #{color}20; border: 2px solid {color};'>
120
- <h2 style='color: {color};'>{status}</h2>
121
- <p style='font-size: 16px;'>{message}</p>
 
 
 
 
 
 
122
  </div>
123
  """
124
 
125
- return results, diagnosis
126
-
127
- # ============================================
128
- # Exemplos de imagens
129
- # ============================================
130
- examples = [
131
- ["examples/tomato_healthy.jpg"],
132
- ["examples/apple_scab.jpg"],
133
- ["examples/potato_blight.jpg"],
134
- ] # Adicione exemplos se tiver
135
 
136
  # ============================================
137
  # Interface Gradio
138
  # ============================================
139
- with gr.Blocks(title="Plant Disease Detector 🌿") as demo:
140
- gr.Markdown("""
141
- # 🌿 Detector de Doenças em Plantas
 
 
 
 
142
 
143
- ### Como usar:
144
- 1. **Faça upload** de uma foto da planta
145
- 2. **Clique em Submit** para analisar
146
- 3. **Veja o diagnóstico** e as probabilidades
147
 
148
- **Dica:** Tire fotos das folhas em boa iluminação para melhores resultados!
149
  """)
150
 
151
  with gr.Row():
152
- with gr.Column():
153
  input_image = gr.Image(
154
  label="📷 Upload da Imagem",
155
  type="numpy",
156
- height=300
157
- )
158
- submit_btn = gr.Button(
159
- "🔍 Analisar Planta",
160
- variant="primary",
161
- size="lg"
162
  )
163
 
164
- with gr.Column():
 
 
 
 
 
 
 
 
 
 
 
 
165
  diagnosis_output = gr.HTML(
166
  label="Diagnóstico",
167
- value="<div style='padding: 20px; text-align: center; color: gray;'>Aguardando imagem...</div>"
168
  )
 
169
  confidence_output = gr.Label(
170
- label="📊 Probabilidades (Top 5)",
171
  num_top_classes=5
172
  )
173
 
174
- # Exemplos (se você tiver imagens de exemplo)
175
- # gr.Examples(
176
- # examples=examples,
177
- # inputs=input_image,
178
- # outputs=[confidence_output, diagnosis_output],
179
- # fn=classify_plant,
180
- # )
 
 
 
 
 
 
181
 
182
  gr.Markdown("""
183
  ---
184
- ### 📋 Informações:
185
- - **Modelo:** ResNet50 treinado com 38 classes
186
- - **Plantas:** Maçã, Tomate, Batata, Uva, Milho, e mais
187
- - **Doenças:** Detecta várias doenças comuns em plantas
 
 
188
 
189
- ### 🔗 Links:
190
  - [Modelo no HuggingFace](https://huggingface.co/raysarocha/plant-resnet50-38classes)
191
- - [Código no GitHub](#)
 
 
 
 
 
 
192
  """)
193
 
194
- # Conecta o botão
195
  submit_btn.click(
196
  fn=classify_plant,
197
  inputs=input_image,
198
- outputs=[confidence_output, diagnosis_output]
199
  )
200
 
201
- # Upload automático
 
 
 
 
 
 
 
 
202
  input_image.change(
203
  fn=classify_plant,
204
  inputs=input_image,
205
- outputs=[confidence_output, diagnosis_output]
206
  )
207
 
208
- # ============================================
209
- # Executa a aplicação
210
- # ============================================
211
  if __name__ == "__main__":
212
  demo.launch(
213
  server_name="0.0.0.0",
214
- share=False,
215
- show_error=True
216
  )
 
8
  # ============================================
9
  # Configurações do modelo
10
  # ============================================
11
+ REPO_ID = "raysarocha/plant-resnet50-38classes" # Seu modelo recém-deployado!
12
 
13
  # ============================================
14
  # Carregamento do modelo
15
  # ============================================
16
+ @gr.utils.cache_api_call
17
+ def load_model():
18
+ """Carrega o modelo uma única vez e mantém em cache"""
19
+ print("🔄 Baixando e carregando modelo...")
20
+
21
+ # Baixa os arquivos
22
+ cfg_path = hf_hub_download(REPO_ID, "config.json")
23
+ model_path = hf_hub_download(REPO_ID, "model.keras")
24
+
25
+ # Carrega configuração
26
+ with open(cfg_path, "r") as f:
27
+ cfg = json.load(f)
28
+
29
+ # Carrega modelo
30
+ model = tf.keras.models.load_model(model_path)
31
+ print("✅ Modelo carregado com sucesso!")
32
+
33
+ return model, cfg
34
 
35
+ # Carrega o modelo
36
+ model, cfg = load_model()
 
37
 
38
  # ============================================
39
+ # Dicionário de nomes amigáveis e recomendações
40
  # ============================================
41
+ PLANT_INFO = {
42
+ "Apple___Apple_scab": {
43
+ "name": "🍎 Maçã - Sarna",
44
+ "healthy": False,
45
+ "description": "Doença fúngica que causa manchas escuras nas folhas e frutos",
46
+ "treatment": " Remova folhas infectadas\n• Aplique fungicida à base de cobre\n• Melhore a circulação de ar"
47
+ },
48
+ "Apple___Black_rot": {
49
+ "name": "🍎 Maçã - Podridão Negra",
50
+ "healthy": False,
51
+ "description": "Infecção fúngica que causa podridão em frutos e folhas",
52
+ "treatment": " Pode galhos infectados\n• Remova frutos mumificados\n• Use fungicida preventivo"
53
+ },
54
+ "Apple___Cedar_apple_rust": {
55
+ "name": "🍎 Maçã - Ferrugem do Cedro",
56
+ "healthy": False,
57
+ "description": "Doença que causa manchas alaranjadas nas folhas",
58
+ "treatment": " Remova cedros próximos se possível\n• Aplique fungicida na primavera\n• Escolha variedades resistentes"
59
+ },
60
+ "Apple___healthy": {
61
+ "name": "🍎 Maçã - Saudável",
62
+ "healthy": True,
63
+ "description": "Planta em bom estado de saúde",
64
+ "treatment": " Continue com os cuidados regulares\n• Mantenha boa irrigação\n• Faça podas preventivas"
65
+ },
66
+ "Tomato___Bacterial_spot": {
67
+ "name": "🍅 Tomate - Mancha Bacteriana",
68
+ "healthy": False,
69
+ "description": "Infecção bacteriana que causa manchas nas folhas",
70
+ "treatment": " Evite molhar as folhas\n• Use sementes certificadas\n• Aplique cobre preventivamente"
71
+ },
72
+ "Tomato___Early_blight": {
73
+ "name": "🍅 Tomate - Requeima Precoce",
74
+ "healthy": False,
75
+ "description": "Doença fúngica com manchas em anéis concêntricos",
76
+ "treatment": " Remova folhas afetadas\n• Aplique fungicida\n• Faça rotação de culturas"
77
+ },
78
+ "Tomato___healthy": {
79
+ "name": "🍅 Tomate - Saudável",
80
+ "healthy": True,
81
+ "description": "Planta em bom estado de saúde",
82
+ "treatment": "• Mantenha irrigação regular\n• Adube adequadamente\n• Monitore pragas"
83
+ },
84
+ "Potato___Early_blight": {
85
+ "name": "🥔 Batata - Requeima Precoce",
86
+ "healthy": False,
87
+ "description": "Manchas escuras com anéis concêntricos nas folhas",
88
+ "treatment": "• Use fungicida preventivo\n• Evite irrigação excessiva\n• Destrua restos culturais"
89
+ },
90
+ "Potato___Late_blight": {
91
+ "name": "🥔 Batata - Requeima Tardia",
92
+ "healthy": False,
93
+ "description": "Doença devastadora que causa manchas aquosas",
94
+ "treatment": "• Aplique fungicida imediatamente\n• Remova plantas infectadas\n• Melhore drenagem do solo"
95
+ },
96
+ "Potato___healthy": {
97
+ "name": "🥔 Batata - Saudável",
98
+ "healthy": True,
99
+ "description": "Planta em bom estado de saúde",
100
+ "treatment": "• Continue monitorando\n• Faça amontoa regular\n• Controle irrigação"
101
+ }
102
  }
103
 
104
+ # Preenche informações padrão para classes não detalhadas
105
+ for class_key in cfg["label2id"].keys():
106
+ if class_key not in PLANT_INFO:
107
+ if "healthy" in class_key.lower():
108
+ PLANT_INFO[class_key] = {
109
+ "name": class_key.replace("___", " - ").replace("_", " "),
110
+ "healthy": True,
111
+ "description": "Planta aparentemente saudável",
112
+ "treatment": "• Mantenha os cuidados regulares\n• Continue monitorando"
113
+ }
114
+ else:
115
+ PLANT_INFO[class_key] = {
116
+ "name": class_key.replace("___", " - ").replace("_", " "),
117
+ "healthy": False,
118
+ "description": "Possível problema detectado na planta",
119
+ "treatment": "• Consulte um agrônomo\n• Isole a planta se possível\n• Evite excesso de umidade"
120
+ }
121
+
122
  # ============================================
123
  # Função de classificação
124
  # ============================================
125
  def classify_plant(image):
126
+ """Classifica a imagem e retorna diagnóstico detalhado"""
127
+
 
128
  if image is None:
129
+ return None, "", ""
130
 
131
  # Preprocessamento
132
  img = Image.fromarray(image).convert("RGB")
 
141
  # Top 5 resultados
142
  top_5_idx = np.argsort(probs)[-5:][::-1]
143
 
144
+ # Formata resultados
145
  results = {}
146
  for idx in top_5_idx:
147
  class_name = cfg["id2label"][str(idx)]
148
+ info = PLANT_INFO.get(class_name, {})
149
+ friendly_name = info.get("name", class_name)
150
  confidence = float(probs[idx])
151
  results[friendly_name] = confidence
152
 
153
+ # Pega informação da classe mais provável
154
  top_class = cfg["id2label"][str(top_5_idx[0])]
155
  top_confidence = float(probs[top_5_idx[0]])
156
+ top_info = PLANT_INFO.get(top_class, {})
157
 
158
+ # Cria card de diagnóstico
159
+ if top_info.get("healthy", False):
160
+ status_icon = ""
161
+ status_text = "Planta Saudável"
162
+ card_color = "#10b981" # Verde
163
+ bg_color = "#f0fdf4"
164
  else:
165
+ status_icon = "⚠️"
166
+ status_text = "Atenção Necessária"
167
+ card_color = "#f59e0b" # Laranja
168
+ bg_color = "#fef3c7"
169
+
170
+ diagnosis_html = f"""
171
+ <div style='padding: 20px; border-radius: 12px; background: {bg_color}; border: 2px solid {card_color}; margin-bottom: 20px;'>
172
+ <h2 style='color: {card_color}; margin: 0 0 10px 0; font-size: 24px;'>
173
+ {status_icon} {status_text}
174
+ </h2>
175
+ <h3 style='color: #374151; margin: 10px 0;'>{top_info.get('name', top_class)}</h3>
176
+ <p style='color: #6b7280; margin: 10px 0;'>Confiança: {top_confidence:.1%}</p>
177
+ <hr style='border: 1px solid {card_color}; opacity: 0.3; margin: 15px 0;'>
178
+ <p style='color: #4b5563; margin: 10px 0;'><strong>Descrição:</strong><br>{top_info.get('description', 'Informação não disponível')}</p>
179
  </div>
180
  """
181
 
182
+ # Recomendações
183
+ treatment_html = f"""
184
+ <div style='padding: 15px; border-radius: 8px; background: #f9fafb; border: 1px solid #e5e7eb;'>
185
+ <h3 style='color: #1f2937; margin: 0 0 10px 0;'>📋 Recomendações:</h3>
186
+ <pre style='color: #4b5563; margin: 0; white-space: pre-wrap; font-family: sans-serif; line-height: 1.5;'>{top_info.get('treatment', '• Consulte um especialista para orientações específicas')}</pre>
187
+ </div>
188
+ """
189
+
190
+ return results, diagnosis_html, treatment_html
 
191
 
192
  # ============================================
193
  # Interface Gradio
194
  # ============================================
195
+ with gr.Blocks(
196
+ title="Plant Disease Detector 🌿",
197
+ theme=gr.themes.Soft(
198
+ primary_hue="green",
199
+ secondary_hue="emerald",
200
+ )
201
+ ) as demo:
202
 
203
+ gr.Markdown("""
204
+ # 🌿 Plant Disease Detector
205
+ ### Identificação Inteligente de Doenças em Plantas
 
206
 
207
+ Upload uma foto da sua planta para receber um diagnóstico instantâneo e recomendações de tratamento.
208
  """)
209
 
210
  with gr.Row():
211
+ with gr.Column(scale=1):
212
  input_image = gr.Image(
213
  label="📷 Upload da Imagem",
214
  type="numpy",
215
+ height=400,
216
+ sources=["upload", "webcam", "clipboard"]
 
 
 
 
217
  )
218
 
219
+ with gr.Row():
220
+ clear_btn = gr.Button("🗑️ Limpar", variant="secondary")
221
+ submit_btn = gr.Button("🔍 Analisar", variant="primary", scale=2)
222
+
223
+ gr.Markdown("""
224
+ **💡 Dicas para melhores resultados:**
225
+ - Use boa iluminação natural
226
+ - Foque nas folhas afetadas
227
+ - Evite sombras fortes
228
+ - Aproxime-se da área problemática
229
+ """)
230
+
231
+ with gr.Column(scale=1):
232
  diagnosis_output = gr.HTML(
233
  label="Diagnóstico",
234
+ value="<div style='padding: 40px; text-align: center; color: #9ca3af;'><h3>🔍 Aguardando imagem...</h3><p>Faça upload de uma foto para começar</p></div>"
235
  )
236
+ treatment_output = gr.HTML(label="Tratamento Recomendado")
237
  confidence_output = gr.Label(
238
+ label="📊 Análise de Probabilidade",
239
  num_top_classes=5
240
  )
241
 
242
+ # Exemplos
243
+ gr.Markdown("### 🖼️ Exemplos")
244
+ gr.Examples(
245
+ examples=[
246
+ ["https://www.gardeningknowhow.com/wp-content/uploads/2017/06/apple-scab-lesions.jpg"],
247
+ ["https://www.gardeningknowhow.com/wp-content/uploads/2020/11/tomato-early-blight.jpg"],
248
+ ["https://www.gardeningknowhow.com/wp-content/uploads/2019/08/potato-blight-400x300.jpg"],
249
+ ],
250
+ inputs=input_image,
251
+ outputs=[confidence_output, diagnosis_output, treatment_output],
252
+ fn=classify_plant,
253
+ cache_examples=True
254
+ )
255
 
256
  gr.Markdown("""
257
  ---
258
+ ### ℹ️ Sobre o Modelo
259
+
260
+ - **Arquitetura:** ResNet50
261
+ - **Classes:** 38 tipos de plantas e doenças
262
+ - **Plantas incluídas:** Maçã, Tomate, Batata, Uva, Milho, Pêssego, Pimentão, Morango e mais
263
+ - **Precisão:** ~98% no conjunto de validação
264
 
265
+ ### 🔗 Links Úteis
266
  - [Modelo no HuggingFace](https://huggingface.co/raysarocha/plant-resnet50-38classes)
267
+ - [Relatório Técnico](#)
268
+ - [Dataset Original](https://www.kaggle.com/datasets/vipoooool/new-plant-diseases-dataset)
269
+
270
+ ---
271
+ <p style='text-align: center; color: #9ca3af;'>
272
+ Desenvolvido com ❤️ por Raysa Rocha | 2024
273
+ </p>
274
  """)
275
 
276
+ # Eventos
277
  submit_btn.click(
278
  fn=classify_plant,
279
  inputs=input_image,
280
+ outputs=[confidence_output, diagnosis_output, treatment_output]
281
  )
282
 
283
+ clear_btn.click(
284
+ fn=lambda: (None,
285
+ "<div style='padding: 40px; text-align: center; color: #9ca3af;'><h3>🔍 Aguardando imagem...</h3></div>",
286
+ "",
287
+ None),
288
+ outputs=[input_image, diagnosis_output, treatment_output, confidence_output]
289
+ )
290
+
291
+ # Análise automática ao fazer upload
292
  input_image.change(
293
  fn=classify_plant,
294
  inputs=input_image,
295
+ outputs=[confidence_output, diagnosis_output, treatment_output]
296
  )
297
 
298
+ # Inicia a aplicação
 
 
299
  if __name__ == "__main__":
300
  demo.launch(
301
  server_name="0.0.0.0",
302
+ share=False
 
303
  )