import streamlit as st import torch import torch.nn as nn from torchvision import models, transforms from PIL import Image import numpy as np import time import os import json # Set page configuration st.set_page_config( page_title="Spider Mite Detection", page_icon="🍃", layout="wide", initial_sidebar_state="expanded", menu_items={ 'Get Help': 'https://www.github.com/your-repo', 'Report a bug': 'https://www.github.com/your-repo/issues', 'About': 'Advanced AI system for detecting spider mite infestations on plant leaves' } ) # Define model architectures MODEL_MAP = { 'mobilenetv3': { 'model_fn': models.mobilenet_v3_small, 'classifier_update': lambda model, num_classes: setattr( model, 'classifier', nn.Sequential( *list(model.classifier.children())[:-1], nn.Linear(model.classifier[-1].in_features, num_classes) ) ) }, 'efficientnet': { 'model_fn': models.efficientnet_b0, 'classifier_update': lambda model, num_classes: setattr( model, 'classifier', nn.Sequential( *list(model.classifier.children())[:-1], nn.Linear(model.classifier[-1].in_features, num_classes) ) ) }, 'resnet18': { 'model_fn': models.resnet18, 'classifier_update': lambda model, num_classes: setattr( model, 'fc', nn.Linear(model.fc.in_features, num_classes) ) } } # Define image transformation def get_transform(): return transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) # Define function to load model @st.cache_resource def load_model(model_path="models/model.pth"): # Try to find model_info.json to determine which model architecture to use model_dir = os.path.dirname(model_path) model_info_path = os.path.join(model_dir, "model_info.json") # Default model type if info file doesn't exist model_type = "mobilenetv3" if os.path.exists(model_info_path): try: with open(model_info_path, 'r') as f: model_info = json.load(f) model_type = model_info.get('model_name', model_type) except: st.warning("Couldn't read model info file. Using default model type.") # Initialize the model if model_type not in MODEL_MAP: st.error(f"Unknown model type: {model_type}") return None model = MODEL_MAP[model_type]['model_fn'](weights=None) MODEL_MAP[model_type]['classifier_update'](model, 2) # 2 classes: healthy, infested # Load weights if os.path.exists(model_path): try: model.load_state_dict(torch.load(model_path, map_location=torch.device('cpu'))) model.eval() return model except Exception as e: st.error(f"Error loading model: {e}") return None else: st.error(f"Model file not found: {model_path}") return None # Predict function def predict(model, image): transform = get_transform() image_tensor = transform(image).unsqueeze(0) # Add batch dimension # Make prediction with torch.no_grad(): start_time = time.time() outputs = model(image_tensor) inference_time = time.time() - start_time # Get probabilities probabilities = torch.nn.functional.softmax(outputs[0], dim=0) return probabilities.numpy(), inference_time # Main app UI def main(): # Custom CSS st.markdown(""" """, unsafe_allow_html=True) # Sidebar information st.sidebar.markdown('', unsafe_allow_html=True) # Main area st.markdown('

Spider Mite Detection System

', unsafe_allow_html=True) # Tabs for different functionalities tab1, tab2 = st.tabs(["🔍 Detect Spider Mites", "â„šī¸ About the Project"]) with tab1: col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.markdown('

Upload a leaf image for analysis

', unsafe_allow_html=True) # Load model with st.spinner("Loading AI model..."): model = load_model() if model is None: st.error("âš ī¸ Failed to load model. Please check if the model file exists.") return else: st.success("✅ AI model loaded successfully") # Image upload with enhanced UI upload_container = st.container() with upload_container: uploaded_file = st.file_uploader("Choose a leaf image to analyze", type=["jpg", "jpeg", "png"]) # Add test images from test_images folder st.markdown("

Or select a test image:

", unsafe_allow_html=True) test_cols = st.columns(4) # Get test images from test_images folder test_images = [] for root, dirs, files in os.walk("test_images"): for file in files: if file.lower().endswith((".jpg", ".jpeg", ".png")): test_images.append({"name": file, "path": os.path.join(root, file)}) # Display test images use_test = None for i, test_img in enumerate(test_images): with test_cols[i % 4]: folder_type = "Healthy" if "healthy" in test_img["path"].lower() else "Spider Mite Infested" st.image(test_img["path"], caption=folder_type, width=150) if st.button(f"Use {folder_type}", key=f"test_button_{i}"): use_test = test_img["path"] uploaded_file = use_test # Process image if uploaded if uploaded_file is not None: # Handle test image path if isinstance(uploaded_file, str): try: image = Image.open(uploaded_file).convert('RGB') except: st.error(f"Could not open test image: {uploaded_file}") return st.markdown("---") analysis_container = st.container() with analysis_container: col1, col2 = st.columns([1, 1]) with col1: st.markdown('

Uploaded Image

', unsafe_allow_html=True) image = Image.open(uploaded_file).convert('RGB') st.image(image, caption="", use_container_width=True) with col2: st.markdown('

Analysis Result

', unsafe_allow_html=True) # Run prediction with st.spinner("🔍 Analyzing leaf image..."): probabilities, inference_time = predict(model, image) # Class names class_names = ['Healthy', 'Spider Mite Infested'] # Get prediction predicted_class = np.argmax(probabilities) confidence = probabilities[predicted_class] * 100 # Display result with improved UI if predicted_class == 0: st.markdown(f'
✅ {class_names[predicted_class]}
', unsafe_allow_html=True) emoji = "đŸŒŋ" result_color = "#2E7D32" else: st.markdown(f'
âš ī¸ {class_names[predicted_class]}
', unsafe_allow_html=True) emoji = "đŸ•ˇī¸" result_color = "#C62828" # Result metrics in a nice grid st.markdown('
', unsafe_allow_html=True) st.markdown(f"""
{confidence:.1f}%
Confidence
{inference_time*1000:.0f}ms
Processing Time
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) # Progress bars for confidence scores st.markdown("### Detection Confidence") for i, class_name in enumerate(class_names): # Convert float32 to Python float to fix the error prob_value = float(probabilities[i]) prob_pct = prob_value * 100 emoji_prefix = "đŸŒŋ" if i == 0 else "đŸ•ˇī¸" st.progress(prob_value) st.markdown(f"{emoji_prefix} **{class_name}:** {prob_pct:.1f}%") # Recommendation with enhanced styling st.markdown("### Recommendation") if predicted_class == 0: st.success("✅ No action needed. Your plant appears healthy!") else: if confidence > 90: st.error(""" 🚨 **Immediate treatment recommended!** High probability of spider mite infestation detected. """) st.markdown("""

Treatment options:

""", unsafe_allow_html=True) else: st.warning(""" âš ī¸ **Potential infestation detected.** Monitor your plant closely and consider preventative treatment. """) else: # Display placeholder when no image is uploaded st.info("👆 Upload a leaf image to get started with the analysis.") # Add a placeholder image with instructions col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.markdown("""

Upload a clear image of your plant leaf to detect spider mite infestations

""", unsafe_allow_html=True) with tab2: col1, col2 = st.columns([3, 2]) with col1: st.markdown('

About This Project

', unsafe_allow_html=True) st.markdown(""" ## Spider Mite Detection Using AI Spider mites are tiny pests that cause significant damage to crops worldwide. Early detection is crucial to prevent severe crop damage and yield loss. Our AI-powered detection system helps farmers and gardeners identify infestations before they become severe. ### Project Goals 1. Develop an AI model capable of classifying leaves as infested or healthy 2. Achieve high accuracy (>90%) in detection 3. Create an accessible application for farmers to use 4. Help reduce crop losses due to spider mite damage ### Technology Used - **Deep Learning**: Transfer learning with modern CNN architectures - **Model Architectures**: MobileNetV3, EfficientNet, ResNet18 - **Training Data**: Curated dataset of healthy and infested plant leaves - **Web Application**: Built with Streamlit for accessibility ### Team Members - Nitesh Kumar Datha Vemanapall - Jithin Garapati - Pavan Sai Korlapati ### Future Improvements - Mobile application for in-field use - Multi-class detection for various plant diseases - Integration with automated spraying systems - Expanded dataset for more plant species """) with col2: st.image("https://www.cropscience.bayer.co.uk/-/media/bcs-inter/ws_uk/images/article-images/pest-encyclopedia/two-spotted-spider-mite.jpg", caption="Spider mite damage on leaves", use_column_width=True) st.image("https://www.planetnatural.com/wp-content/uploads/2013/01/spider-mite-control.jpg", caption="Spider mite close-up", use_column_width=True) # Add some statistics st.markdown("""

Spider Mite Impact

""", unsafe_allow_html=True) if __name__ == "__main__": main()