import gradio as gr import tensorflow as tf import numpy as np from PIL import Image import json from huggingface_hub import hf_hub_download # ============================================ # Configurações do modelo # ============================================ REPO_ID = "raysarocha/plant-resnet50-38classes" # Seu modelo recém-deployado! # ============================================ # Carregamento do modelo # ============================================ def load_model(): """Carrega o modelo uma única vez e mantém em cache""" print("🔄 Baixando e carregando modelo...") # Baixa os arquivos cfg_path = hf_hub_download(REPO_ID, "config.json") model_path = hf_hub_download(REPO_ID, "model.keras") # Carrega configuração with open(cfg_path, "r") as f: cfg = json.load(f) # Carrega modelo model = tf.keras.models.load_model(model_path) print("✅ Modelo carregado com sucesso!") return model, cfg # Carrega o modelo model, cfg = load_model() # ============================================ # Dicionário de nomes amigáveis e recomendações # ============================================ PLANT_INFO = { "Apple___Apple_scab": { "name": "🍎 Maçã - Sarna", "healthy": False, "description": "Doença fúngica que causa manchas escuras nas folhas e frutos", "treatment": "• Remova folhas infectadas\n• Aplique fungicida à base de cobre\n• Melhore a circulação de ar" }, "Apple___Black_rot": { "name": "🍎 Maçã - Podridão Negra", "healthy": False, "description": "Infecção fúngica que causa podridão em frutos e folhas", "treatment": "• Pode galhos infectados\n• Remova frutos mumificados\n• Use fungicida preventivo" }, "Apple___Cedar_apple_rust": { "name": "🍎 Maçã - Ferrugem do Cedro", "healthy": False, "description": "Doença que causa manchas alaranjadas nas folhas", "treatment": "• Remova cedros próximos se possível\n• Aplique fungicida na primavera\n• Escolha variedades resistentes" }, "Apple___healthy": { "name": "🍎 Maçã - Saudável", "healthy": True, "description": "Planta em bom estado de saúde", "treatment": "• Continue com os cuidados regulares\n• Mantenha boa irrigação\n• Faça podas preventivas" }, "Tomato___Bacterial_spot": { "name": "🍅 Tomate - Mancha Bacteriana", "healthy": False, "description": "Infecção bacteriana que causa manchas nas folhas", "treatment": "• Evite molhar as folhas\n• Use sementes certificadas\n• Aplique cobre preventivamente" }, "Tomato___Early_blight": { "name": "🍅 Tomate - Requeima Precoce", "healthy": False, "description": "Doença fúngica com manchas em anéis concêntricos", "treatment": "• Remova folhas afetadas\n• Aplique fungicida\n• Faça rotação de culturas" }, "Tomato___healthy": { "name": "🍅 Tomate - Saudável", "healthy": True, "description": "Planta em bom estado de saúde", "treatment": "• Mantenha irrigação regular\n• Adube adequadamente\n• Monitore pragas" }, "Potato___Early_blight": { "name": "🥔 Batata - Requeima Precoce", "healthy": False, "description": "Manchas escuras com anéis concêntricos nas folhas", "treatment": "• Use fungicida preventivo\n• Evite irrigação excessiva\n• Destrua restos culturais" }, "Potato___Late_blight": { "name": "🥔 Batata - Requeima Tardia", "healthy": False, "description": "Doença devastadora que causa manchas aquosas", "treatment": "• Aplique fungicida imediatamente\n• Remova plantas infectadas\n• Melhore drenagem do solo" }, "Potato___healthy": { "name": "🥔 Batata - Saudável", "healthy": True, "description": "Planta em bom estado de saúde", "treatment": "• Continue monitorando\n• Faça amontoa regular\n• Controle irrigação" } } # Preenche informações padrão para classes não detalhadas for class_key in cfg["label2id"].keys(): if class_key not in PLANT_INFO: if "healthy" in class_key.lower(): PLANT_INFO[class_key] = { "name": class_key.replace("___", " - ").replace("_", " "), "healthy": True, "description": "Planta aparentemente saudável", "treatment": "• Mantenha os cuidados regulares\n• Continue monitorando" } else: PLANT_INFO[class_key] = { "name": class_key.replace("___", " - ").replace("_", " "), "healthy": False, "description": "Possível problema detectado na planta", "treatment": "• Consulte um agrônomo\n• Isole a planta se possível\n• Evite excesso de umidade" } # ============================================ # Função de classificação # ============================================ def classify_plant(image): """Classifica a imagem e retorna diagnóstico detalhado""" if image is None: return None, "", "" # Preprocessamento img = Image.fromarray(image).convert("RGB") img = img.resize((cfg["image_size"], cfg["image_size"])) arr = np.array(img).astype("float32") * cfg["rescale"] arr = np.expand_dims(arr, axis=0) # Predição predictions = model(arr) probs = tf.nn.softmax(predictions[0]).numpy() # Top 5 resultados top_5_idx = np.argsort(probs)[-5:][::-1] # Formata resultados results = {} for idx in top_5_idx: class_name = cfg["id2label"][str(idx)] info = PLANT_INFO.get(class_name, {}) friendly_name = info.get("name", class_name) confidence = float(probs[idx]) results[friendly_name] = confidence # Pega informação da classe mais provável top_class = cfg["id2label"][str(top_5_idx[0])] top_confidence = float(probs[top_5_idx[0]]) top_info = PLANT_INFO.get(top_class, {}) # Cria card de diagnóstico if top_info.get("healthy", False): status_icon = "✅" status_text = "Planta Saudável" card_color = "#10b981" # Verde bg_color = "#f0fdf4" else: status_icon = "⚠️" status_text = "Atenção Necessária" card_color = "#f59e0b" # Laranja bg_color = "#fef3c7" diagnosis_html = f"""

{status_icon} {status_text}

{top_info.get('name', top_class)}

Confiança: {top_confidence:.1%}


Descrição:
{top_info.get('description', 'Informação não disponível')}

""" # Recomendações treatment_html = f"""

📋 Recomendações:

{top_info.get('treatment', '• Consulte um especialista para orientações específicas')}
""" return results, diagnosis_html, treatment_html # ============================================ # Interface Gradio # ============================================ with gr.Blocks( title="Plant Identifier & Health Checker 🌿", theme=gr.themes.Soft( primary_hue="green", secondary_hue="emerald", ) ) as demo: gr.Markdown(""" # 🌿 Plant Identifier & Health Checker ### Identificação e Análise de Saúde de Plantas Upload uma foto da sua planta para receber um diagnóstico instantâneo e recomendações de tratamento. """) with gr.Row(): with gr.Column(scale=1): input_image = gr.Image( label="📷 Upload da Imagem", type="numpy", height=400, sources=["upload", "webcam", "clipboard"] ) with gr.Row(): clear_btn = gr.Button("🗑️ Limpar", variant="secondary") submit_btn = gr.Button("🔍 Analisar", variant="primary", scale=2) gr.Markdown(""" **💡 Dicas para melhores resultados:** - Use boa iluminação natural - Foque nas folhas afetadas - Evite sombras fortes - Aproxime-se da área problemática """) with gr.Column(scale=1): diagnosis_output = gr.HTML( label="Diagnóstico", value="

🔍 Aguardando imagem...

Faça upload de uma foto para começar

" ) treatment_output = gr.HTML(label="Tratamento Recomendado") confidence_output = gr.Label( label="📊 Análise de Probabilidade", num_top_classes=5 ) # # Exemplos # gr.Markdown("### 🖼️ Exemplos") # gr.Examples( # examples=[ # ["https://www.gardeningknowhow.com/wp-content/uploads/2017/06/apple-scab-lesions.jpg"], # ["https://www.gardeningknowhow.com/wp-content/uploads/2020/11/tomato-early-blight.jpg"], # ["https://www.gardeningknowhow.com/wp-content/uploads/2019/08/potato-blight-400x300.jpg"], # ], # inputs=input_image, # outputs=[confidence_output, diagnosis_output, treatment_output], # fn=classify_plant, # cache_examples=True # ) gr.Markdown(""" --- ### ℹ️ Sobre o Modelo - **Arquitetura:** ResNet50 - **Classes:** 38 tipos de plantas e doenças - **Plantas incluídas:** Maçã, Tomate, Batata, Uva, Milho, Pêssego, Pimentão, Morango e mais - **Precisão:** ~98% no conjunto de validação ### 🔗 Links Úteis - [Modelo no HuggingFace](https://huggingface.co/raysarocha/plant-resnet50-38classes) - [Relatório Técnico](#) - [Dataset Original](https://www.kaggle.com/datasets/vipoooool/new-plant-diseases-dataset) ---

Desenvolvido com ❤️ por Raysa Rocha | 2024

""") # Eventos submit_btn.click( fn=classify_plant, inputs=input_image, outputs=[confidence_output, diagnosis_output, treatment_output] ) clear_btn.click( fn=lambda: (None, "

🔍 Aguardando imagem...

", "", None), outputs=[input_image, diagnosis_output, treatment_output, confidence_output] ) # Análise automática ao fazer upload input_image.change( fn=classify_plant, inputs=input_image, outputs=[confidence_output, diagnosis_output, treatment_output] ) # Inicia a aplicação if __name__ == "__main__": demo.launch( server_name="0.0.0.0", share=False )