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('', 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('', unsafe_allow_html=True)
image = Image.open(uploaded_file).convert('RGB')
st.image(image, caption="", use_container_width=True)
with col2:
st.markdown('', 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:
- Natural remedies: Apply neem oil or insecticidal soap
- Biological control: Introduce predatory mites
- Management: Prune heavily infested leaves
- Prevention: Increase humidity and monitor regularly
""", 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('', 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
- Up to 60% crop yield reduction in severe infestations
- $1+ billion in annual agricultural losses worldwide
- 200+ plant species are vulnerable to spider mite attacks
- 95% accuracy achieved by our detection system
""", unsafe_allow_html=True)
if __name__ == "__main__":
main()