jithin14 commited on
Commit
0ccb899
Β·
1 Parent(s): f77a517

Add app, models, requirements, and test images

Browse files
app.py ADDED
@@ -0,0 +1,483 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import torch
3
+ import torch.nn as nn
4
+ from torchvision import models, transforms
5
+ from PIL import Image
6
+ import numpy as np
7
+ import time
8
+ import os
9
+ import json
10
+
11
+ # Set page configuration
12
+ st.set_page_config(
13
+ page_title="Spider Mite Detection",
14
+ page_icon="πŸƒ",
15
+ layout="wide",
16
+ initial_sidebar_state="expanded",
17
+ menu_items={
18
+ 'Get Help': 'https://www.github.com/your-repo',
19
+ 'Report a bug': 'https://www.github.com/your-repo/issues',
20
+ 'About': 'Advanced AI system for detecting spider mite infestations on plant leaves'
21
+ }
22
+ )
23
+
24
+ # Define model architectures
25
+ MODEL_MAP = {
26
+ 'mobilenetv3': {
27
+ 'model_fn': models.mobilenet_v3_small,
28
+ 'classifier_update': lambda model, num_classes: setattr(
29
+ model, 'classifier', nn.Sequential(
30
+ *list(model.classifier.children())[:-1],
31
+ nn.Linear(model.classifier[-1].in_features, num_classes)
32
+ )
33
+ )
34
+ },
35
+ 'efficientnet': {
36
+ 'model_fn': models.efficientnet_b0,
37
+ 'classifier_update': lambda model, num_classes: setattr(
38
+ model, 'classifier', nn.Sequential(
39
+ *list(model.classifier.children())[:-1],
40
+ nn.Linear(model.classifier[-1].in_features, num_classes)
41
+ )
42
+ )
43
+ },
44
+ 'resnet18': {
45
+ 'model_fn': models.resnet18,
46
+ 'classifier_update': lambda model, num_classes: setattr(
47
+ model, 'fc', nn.Linear(model.fc.in_features, num_classes)
48
+ )
49
+ }
50
+ }
51
+
52
+ # Define image transformation
53
+ def get_transform():
54
+ return transforms.Compose([
55
+ transforms.Resize((224, 224)),
56
+ transforms.ToTensor(),
57
+ transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
58
+ ])
59
+
60
+ # Define function to load model
61
+ @st.cache_resource
62
+ def load_model(model_path="models/model.pth"):
63
+ # Try to find model_info.json to determine which model architecture to use
64
+ model_dir = os.path.dirname(model_path)
65
+ model_info_path = os.path.join(model_dir, "model_info.json")
66
+
67
+ # Default model type if info file doesn't exist
68
+ model_type = "mobilenetv3"
69
+
70
+ if os.path.exists(model_info_path):
71
+ try:
72
+ with open(model_info_path, 'r') as f:
73
+ model_info = json.load(f)
74
+ model_type = model_info.get('model_name', model_type)
75
+ except:
76
+ st.warning("Couldn't read model info file. Using default model type.")
77
+
78
+ # Initialize the model
79
+ if model_type not in MODEL_MAP:
80
+ st.error(f"Unknown model type: {model_type}")
81
+ return None
82
+
83
+ model = MODEL_MAP[model_type]['model_fn'](weights=None)
84
+ MODEL_MAP[model_type]['classifier_update'](model, 2) # 2 classes: healthy, infested
85
+
86
+ # Load weights
87
+ if os.path.exists(model_path):
88
+ try:
89
+ model.load_state_dict(torch.load(model_path, map_location=torch.device('cpu')))
90
+ model.eval()
91
+ return model
92
+ except Exception as e:
93
+ st.error(f"Error loading model: {e}")
94
+ return None
95
+ else:
96
+ st.error(f"Model file not found: {model_path}")
97
+ return None
98
+
99
+ # Predict function
100
+ def predict(model, image):
101
+ transform = get_transform()
102
+ image_tensor = transform(image).unsqueeze(0) # Add batch dimension
103
+
104
+ # Make prediction
105
+ with torch.no_grad():
106
+ start_time = time.time()
107
+ outputs = model(image_tensor)
108
+ inference_time = time.time() - start_time
109
+
110
+ # Get probabilities
111
+ probabilities = torch.nn.functional.softmax(outputs[0], dim=0)
112
+
113
+ return probabilities.numpy(), inference_time
114
+
115
+ # Main app UI
116
+ def main():
117
+ # Custom CSS
118
+ st.markdown("""
119
+ <style>
120
+ .main-header {
121
+ font-size: 3rem;
122
+ background: linear-gradient(90deg, #4CAF50, #2196F3);
123
+ -webkit-background-clip: text;
124
+ background-clip: text;
125
+ color: transparent;
126
+ text-align: center;
127
+ margin-bottom: 2rem;
128
+ padding: 20px 0;
129
+ font-weight: 800;
130
+ letter-spacing: 1px;
131
+ text-shadow: 0px 2px 4px rgba(0,0,0,0.1);
132
+ }
133
+ .sub-header {
134
+ font-size: 1.8rem;
135
+ color: #1E88E5;
136
+ margin-bottom: 1.5rem;
137
+ border-bottom: 2px solid #E0E0E0;
138
+ padding-bottom: 10px;
139
+ }
140
+ .result-header {
141
+ font-size: 2rem;
142
+ font-weight: bold;
143
+ margin-bottom: 1.5rem;
144
+ color: #333;
145
+ }
146
+ .healthy {
147
+ color: #2E7D32;
148
+ font-weight: bold;
149
+ font-size: 1.5rem;
150
+ display: flex;
151
+ align-items: center;
152
+ background-color: rgba(46, 125, 50, 0.1);
153
+ padding: 10px 15px;
154
+ border-radius: 8px;
155
+ }
156
+ .infested {
157
+ color: #C62828;
158
+ font-weight: bold;
159
+ font-size: 1.5rem;
160
+ display: flex;
161
+ align-items: center;
162
+ background-color: rgba(198, 40, 40, 0.1);
163
+ padding: 10px 15px;
164
+ border-radius: 8px;
165
+ }
166
+ .sidebar-content {
167
+ font-size: 1.1rem;
168
+ padding: 15px 0;
169
+ }
170
+ .sidebar-title {
171
+ background: linear-gradient(90deg, #4CAF50, #2196F3);
172
+ -webkit-background-clip: text;
173
+ background-clip: text;
174
+ color: transparent;
175
+ font-weight: 700;
176
+ margin-bottom: 15px;
177
+ }
178
+ .stProgress > div > div {
179
+ background-color: #4CAF50;
180
+ }
181
+ div[data-testid="stFileUploadDropzone"] {
182
+ border: 2px dashed #4CAF50;
183
+ border-radius: 8px;
184
+ padding: 30px 20px;
185
+ background-color: rgba(76, 175, 80, 0.05);
186
+ margin-bottom: 25px;
187
+ transition: all 0.3s ease;
188
+ }
189
+ div[data-testid="stFileUploadDropzone"]:hover {
190
+ background-color: rgba(76, 175, 80, 0.1);
191
+ border-color: #2E7D32;
192
+ }
193
+ .stButton>button {
194
+ background-color: #2196F3;
195
+ color: white;
196
+ border-radius: 5px;
197
+ border: none;
198
+ padding: 10px 20px;
199
+ font-weight: 600;
200
+ transition: all 0.3s ease;
201
+ }
202
+ .stButton>button:hover {
203
+ background-color: #1976D2;
204
+ transform: translateY(-2px);
205
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
206
+ }
207
+ .info-box {
208
+ background-color: #E3F2FD;
209
+ border-left: 5px solid #2196F3;
210
+ padding: 15px;
211
+ border-radius: 5px;
212
+ margin-bottom: 20px;
213
+ }
214
+ .metrics-container {
215
+ display: grid;
216
+ grid-template-columns: 1fr 1fr;
217
+ gap: 15px;
218
+ margin-bottom: 20px;
219
+ }
220
+ .metric-card {
221
+ background-color: #f8f9fa;
222
+ border-radius: 8px;
223
+ padding: 15px;
224
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
225
+ }
226
+ .metric-value {
227
+ font-size: 1.8rem;
228
+ font-weight: bold;
229
+ color: #1976D2;
230
+ }
231
+ .metric-label {
232
+ color: #5f6368;
233
+ font-size: 0.9rem;
234
+ margin-top: 5px;
235
+ }
236
+ </style>
237
+ """, unsafe_allow_html=True)
238
+
239
+ # Sidebar information
240
+ st.sidebar.markdown('<div class="sidebar-content">', unsafe_allow_html=True)
241
+ st.sidebar.image("https://www.gardeningknowhow.com/wp-content/uploads/2019/08/spider-mite-1.jpg", width=280)
242
+ st.sidebar.markdown('<h2 class="sidebar-title">About This Tool</h2>', unsafe_allow_html=True)
243
+ st.sidebar.markdown("""
244
+ <div class="info-box">
245
+ This application uses deep learning to detect spider mite infestations on plant leaves with high accuracy.
246
+ </div>
247
+
248
+ ### What are Spider Mites?
249
+ - Tiny arachnids (0.5mm) that damage crops
250
+ - Feed on plant tissues, causing yellowing and spotting
251
+ - Can rapidly reproduce and spread throughout plants
252
+ - Often go unnoticed until significant damage occurs
253
+
254
+ ### How to Use This Tool
255
+ 1. Upload a high-quality image of a plant leaf
256
+ 2. Our AI will analyze the image for infestation signs
257
+ 3. Review the detection results and follow recommendations
258
+
259
+ ### Model Information
260
+ - Technology: Deep Learning with Transfer Learning
261
+ - Architecture: MobileNetV3
262
+ - Accuracy: ~95%+ on validation data
263
+ - Training: Custom dataset of healthy and infested leaves
264
+ """, unsafe_allow_html=True)
265
+ st.sidebar.markdown('</div>', unsafe_allow_html=True)
266
+
267
+ # Main area
268
+ st.markdown('<h1 class="main-header">Spider Mite Detection System</h1>', unsafe_allow_html=True)
269
+
270
+ # Tabs for different functionalities
271
+ tab1, tab2 = st.tabs(["πŸ” Detect Spider Mites", "ℹ️ About the Project"])
272
+
273
+ with tab1:
274
+ col1, col2, col3 = st.columns([1, 2, 1])
275
+ with col2:
276
+ st.markdown('<h2 class="sub-header">Upload a leaf image for analysis</h2>', unsafe_allow_html=True)
277
+
278
+ # Load model
279
+ with st.spinner("Loading AI model..."):
280
+ model = load_model()
281
+
282
+ if model is None:
283
+ st.error("⚠️ Failed to load model. Please check if the model file exists.")
284
+ return
285
+ else:
286
+ st.success("βœ… AI model loaded successfully")
287
+
288
+ # Image upload with enhanced UI
289
+ upload_container = st.container()
290
+ with upload_container:
291
+ uploaded_file = st.file_uploader("Choose a leaf image to analyze", type=["jpg", "jpeg", "png"])
292
+
293
+ # Add example images
294
+ st.markdown("<h3>Or try an example:</h3>", unsafe_allow_html=True)
295
+ example_cols = st.columns(4)
296
+
297
+ # Example images from URLs
298
+ example_images = [
299
+ {"name": "Healthy Leaf", "path": "https://www.gardendesign.com/pictures/images/900x705Max/site_3/helianthus-yellow-flower-pixabay_12708.jpg"},
300
+ {"name": "Mild Infestation", "path": "https://extension.umn.edu/sites/extension.umn.edu/files/styles/caption_medium/public/two-spotted-spider-mite-feeding-damage-JWeiland-iStock.jpg?itok=VLzrPzLc"},
301
+ {"name": "Severe Infestation", "path": "https://www.planetnatural.com/wp-content/uploads/2012/12/spider-mite-damage-1.jpg"},
302
+ {"name": "Spider Mite Closeup", "path": "https://bugguide.net/images/raw/ZR0/ZXR/ZR0ZXRCZMLJLUL1LJLQZ5RRR9RHH5RQZIRFZIRCZKRQZ5RNLKRFZ5RULARCZIRGZIZ9RTLSZPR.jpg"},
303
+ ]
304
+
305
+ use_example = None
306
+ for i, example in enumerate(example_images):
307
+ with example_cols[i]:
308
+ st.image(example["path"], caption=example["name"], width=150)
309
+ if st.button(f"Use Example {i+1}", key=f"example_{i}"):
310
+ use_example = example["path"]
311
+
312
+ # Process image
313
+ if uploaded_file is not None or use_example is not None:
314
+ # Handle example image
315
+ if use_example is not None:
316
+ try:
317
+ import requests
318
+ from io import BytesIO
319
+ response = requests.get(use_example)
320
+ image = Image.open(BytesIO(response.content)).convert('RGB')
321
+ except Exception as e:
322
+ st.error(f"Error loading example image: {e}")
323
+ return
324
+ else:
325
+ # User uploaded image
326
+ image = Image.open(uploaded_file).convert('RGB')
327
+
328
+ st.markdown("---")
329
+
330
+ analysis_container = st.container()
331
+ with analysis_container:
332
+ col1, col2 = st.columns([1, 1])
333
+
334
+ with col1:
335
+ st.markdown('<h3 class="sub-header">Uploaded Image</h3>', unsafe_allow_html=True)
336
+ st.image(image, caption="", use_container_width=True)
337
+
338
+ with col2:
339
+ st.markdown('<h3 class="result-header">Analysis Result</h3>', unsafe_allow_html=True)
340
+
341
+ # Run prediction
342
+ with st.spinner("πŸ” Analyzing leaf image..."):
343
+ probabilities, inference_time = predict(model, image)
344
+
345
+ # Class names
346
+ class_names = ['Healthy', 'Spider Mite Infested']
347
+
348
+ # Get prediction
349
+ predicted_class = np.argmax(probabilities)
350
+ confidence = probabilities[predicted_class] * 100
351
+
352
+ # Display result with improved UI
353
+ if predicted_class == 0:
354
+ st.markdown(f'<div class="healthy">βœ… {class_names[predicted_class]}</div>', unsafe_allow_html=True)
355
+ emoji = "🌿"
356
+ result_color = "#2E7D32"
357
+ else:
358
+ st.markdown(f'<div class="infested">⚠️ {class_names[predicted_class]}</div>', unsafe_allow_html=True)
359
+ emoji = "πŸ•·οΈ"
360
+ result_color = "#C62828"
361
+
362
+ # Result metrics in a nice grid
363
+ st.markdown('<div class="metrics-container">', unsafe_allow_html=True)
364
+ st.markdown(f"""
365
+ <div class="metric-card">
366
+ <div class="metric-value">{confidence:.1f}%</div>
367
+ <div class="metric-label">Confidence</div>
368
+ </div>
369
+ <div class="metric-card">
370
+ <div class="metric-value">{inference_time*1000:.0f}ms</div>
371
+ <div class="metric-label">Processing Time</div>
372
+ </div>
373
+ """, unsafe_allow_html=True)
374
+ st.markdown('</div>', unsafe_allow_html=True)
375
+
376
+ # Progress bars for confidence scores
377
+ st.markdown("### Detection Confidence")
378
+ for i, class_name in enumerate(class_names):
379
+ # Convert float32 to Python float to fix the error
380
+ prob_value = float(probabilities[i])
381
+ prob_pct = prob_value * 100
382
+ emoji_prefix = "🌿" if i == 0 else "πŸ•·οΈ"
383
+ st.progress(prob_value)
384
+ st.markdown(f"{emoji_prefix} **{class_name}:** {prob_pct:.1f}%")
385
+
386
+ # Recommendation with enhanced styling
387
+ st.markdown("### Recommendation")
388
+ if predicted_class == 0:
389
+ st.success("βœ… No action needed. Your plant appears healthy!")
390
+ else:
391
+ if confidence > 90:
392
+ st.error("""
393
+ 🚨 **Immediate treatment recommended!**
394
+
395
+ High probability of spider mite infestation detected.
396
+ """)
397
+
398
+ st.markdown("""
399
+ <div style="background-color: #fff3e0; padding: 15px; border-radius: 5px; border-left: 5px solid #c62828;">
400
+ <h4 style="color: #c62828; margin-top: 0;">Treatment options:</h4>
401
+ <ul style="color: #333;">
402
+ <li><strong>Natural remedies:</strong> Apply neem oil or insecticidal soap</li>
403
+ <li><strong>Biological control:</strong> Introduce predatory mites</li>
404
+ <li><strong>Management:</strong> Prune heavily infested leaves</li>
405
+ <li><strong>Prevention:</strong> Increase humidity and monitor regularly</li>
406
+ </ul>
407
+ </div>
408
+ """, unsafe_allow_html=True)
409
+ else:
410
+ st.warning("""
411
+ ⚠️ **Potential infestation detected.**
412
+
413
+ Monitor your plant closely and consider preventative treatment.
414
+ """)
415
+ else:
416
+ # Display placeholder when no image is uploaded
417
+ st.info("πŸ‘† Upload a leaf image to get started with the analysis.")
418
+
419
+ # Add a placeholder image with instructions
420
+ col1, col2, col3 = st.columns([1, 2, 1])
421
+ with col2:
422
+ st.markdown("""
423
+ <div style="text-align: center; padding: 40px; background-color: #f5f5f5; border-radius: 10px; margin: 20px 0;">
424
+ <img src="https://www.planetnatural.com/wp-content/uploads/2013/01/spider-mite-control.jpg" style="max-width: 80%; border-radius: 8px; margin-bottom: 20px;" />
425
+ <p style="font-size: 1.2rem; color: #555;">Upload a clear image of your plant leaf to detect spider mite infestations</p>
426
+ </div>
427
+ """, unsafe_allow_html=True)
428
+
429
+ with tab2:
430
+ col1, col2 = st.columns([3, 2])
431
+
432
+ with col1:
433
+ st.markdown('<h2 class="sub-header">About This Project</h2>', unsafe_allow_html=True)
434
+ st.markdown("""
435
+ ## Spider Mite Detection Using AI
436
+
437
+ Spider mites are tiny pests that cause significant damage to crops worldwide. Early detection is crucial to
438
+ prevent severe crop damage and yield loss. Our AI-powered detection system helps farmers and gardeners
439
+ identify infestations before they become severe.
440
+
441
+ ### Project Goals
442
+ 1. Develop an AI model capable of classifying leaves as infested or healthy
443
+ 2. Achieve high accuracy (>90%) in detection
444
+ 3. Create an accessible application for farmers to use
445
+ 4. Help reduce crop losses due to spider mite damage
446
+
447
+ ### Technology Used
448
+ - **Deep Learning**: Transfer learning with modern CNN architectures
449
+ - **Model Architectures**: MobileNetV3, EfficientNet, ResNet18
450
+ - **Training Data**: Curated dataset of healthy and infested plant leaves
451
+ - **Web Application**: Built with Streamlit for accessibility
452
+
453
+ ### Team Members
454
+ - Nitesh Kumar Datha Vemanapall
455
+ - Jithin Garapati
456
+ - Pavan Sai Korlapati
457
+
458
+ ### Future Improvements
459
+ - Mobile application for in-field use
460
+ - Multi-class detection for various plant diseases
461
+ - Integration with automated spraying systems
462
+ - Expanded dataset for more plant species
463
+ """)
464
+
465
+ with col2:
466
+ 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)
467
+ st.image("https://www.planetnatural.com/wp-content/uploads/2013/01/spider-mite-control.jpg", caption="Spider mite close-up", use_column_width=True)
468
+
469
+ # Add some statistics
470
+ st.markdown("""
471
+ <div style="background-color: #e8f5e9; padding: 20px; border-radius: 10px; margin-top: 20px;">
472
+ <h3 style="color: #2e7d32; margin-top: 0;">Spider Mite Impact</h3>
473
+ <ul>
474
+ <li><strong>Up to 60%</strong> crop yield reduction in severe infestations</li>
475
+ <li><strong>$1+ billion</strong> in annual agricultural losses worldwide</li>
476
+ <li><strong>200+ plant species</strong> are vulnerable to spider mite attacks</li>
477
+ <li><strong>95% accuracy</strong> achieved by our detection system</li>
478
+ </ul>
479
+ </div>
480
+ """, unsafe_allow_html=True)
481
+
482
+ if __name__ == "__main__":
483
+ main()
models/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:381c94a5c235c4432b7ecbce4e3dcfde91fe46acdbe93b612ebac6c7210d6e97
3
+ size 6193306
models/model_info.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "mobilenetv3",
3
+ "accuracy": 0.9908396946564886,
4
+ "epochs_trained": 10,
5
+ "dataset": "processed"
6
+ }
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ streamlit==1.31.0
2
+ torch==2.0.1
3
+ torchvision==0.15.2
4
+ Pillow==10.0.0
5
+ numpy==1.24.3
6
+ requests==2.31.0
test_images/healthy/0a31e630-0d98-416b-b0e4-88a88aad1dc5___RS_HL 9653.JPG ADDED
test_images/healthy/0a9986e6-b629-4ff5-8aab-7488ea9b935b___RS_HL 9704.JPG ADDED
test_images/healthy/0aacdad5-c9b9-4309-96e3-0797bbed1375___RS_HL 9836.JPG ADDED
test_images/spider_mite/0a1c03ea-1a2d-449e-bcc4-4a8b62febf88___Com.G_SpM_FL 9433.JPG ADDED
test_images/spider_mite/0cc75e2e-9e6f-4b8e-b564-3840c9ecff58___Com.G_SpM_FL 1442.JPG ADDED
test_images/spider_mite/0cee18fc-bbbd-40dd-8d73-93df072c09ea___Com.G_SpM_FL 8904.JPG ADDED