iqramukhtiar commited on
Commit
800cbbf
·
verified ·
1 Parent(s): 8b6482d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +213 -107
app.py CHANGED
@@ -1,61 +1,123 @@
1
  import gradio as gr
2
  import pandas as pd
3
  import os
4
- import random
5
- from PIL import Image
6
  import torch
7
- from torchvision import transforms
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
- # --- Load CSV Data ---
10
  def load_treatments_data():
11
  try:
12
- context = pd.read_csv('./crop_diseases_treatments.csv')
13
  print("CSV file loaded successfully.")
14
  return context
15
  except FileNotFoundError:
16
  print("Error: crop_diseases_treatments.csv not found.")
17
  # Create a minimal dataframe for demonstration
18
  return pd.DataFrame({
19
- 'Crop': ['Tomato', 'Apple', 'Corn', 'Rice', 'Potato'],
20
- 'Disease': ['Early Blight', 'Apple Scab', 'Common Rust', 'Bacterial Leaf Blight', 'Late Blight'],
21
- 'Symptoms': ['Yellow spots on leaves', 'Dark scab-like lesions', 'Rust-colored pustules', 'Yellow-orange lesions', 'Dark water-soaked spots'],
22
- 'Treatment': ['Remove affected leaves', 'Prune affected branches', 'Remove infected plants', 'Drain fields', 'Apply fungicide early'],
23
- 'Medicine/Chemical Control': ['Copper fungicide', 'Sulfur spray', 'Propiconazole', 'Streptomycin sulfate', 'Chlorothalonil']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  })
25
 
26
- # --- Disease Classification ---
27
- def prepare_disease_classifier():
28
- # Set up image transformation
29
- transform = transforms.Compose([
30
  transforms.Resize((224, 224)),
31
  transforms.ToTensor(),
32
  transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
33
  ])
34
-
35
- # Example class names (to be replaced with actual classes from the dataset)
36
- class_names = [
37
- "Apple___Apple_scab",
38
- "Apple___Black_rot",
39
- "Apple___Cedar_apple_rust",
40
- "Apple___healthy",
41
- "Corn_(maize)___Cercospora_leaf_spot",
42
- "Corn_(maize)___Common_rust",
43
- "Corn_(maize)___healthy",
44
- "Tomato___Early_blight",
45
- "Tomato___Late_blight",
46
- "Tomato___healthy"
47
- ]
48
-
49
- return transform, class_names
50
 
51
- # Function to classify plant disease from image
52
- def classify_disease(image):
53
- transform, class_names = prepare_disease_classifier()
 
54
 
55
  # Process the image
56
- if image is not None:
57
- # For demonstration, we'll randomly select a class
58
- class_idx = random.randint(0, len(class_names) - 1)
 
 
 
 
 
 
59
  class_name = class_names[class_idx]
60
 
61
  # Extract crop and disease from class name
@@ -65,9 +127,9 @@ def classify_disease(image):
65
 
66
  return crop, disease
67
 
68
- return None, None
69
 
70
- # Function to find treatment in the database
71
  def find_treatment(crop, disease, df):
72
  if disease.lower() == "healthy":
73
  return {
@@ -108,11 +170,11 @@ def find_treatment(crop, disease, df):
108
  "crop": crop,
109
  "disease": disease,
110
  "symptoms": "Unknown",
111
- "treatment": "No specific treatment information found",
112
- "medicine": "Consult a plant pathologist"
113
  }
114
 
115
- # Simple function to answer questions based on the database
116
  def answer_question(question, df):
117
  question = question.lower()
118
 
@@ -136,35 +198,40 @@ def answer_question(question, df):
136
  if not matches.empty:
137
  match = matches.iloc[0]
138
  return f"""
139
- Crop: {match['Crop']}
140
- Disease: {match['Disease']}
141
- Symptoms: {match['Symptoms']}
142
- Treatment: {match['Treatment']}
143
- Medicine: {match['Medicine/Chemical Control']}
 
 
 
 
 
144
  """
145
 
146
  # If we found only crop
147
  elif crop_match:
148
  matches = df[df['Crop'] == crop_match]
149
  if not matches.empty:
150
- response = f"Information about diseases affecting {crop_match}:\n\n"
151
  for _, row in matches.iterrows():
152
- response += f"Disease: {row['Disease']}\n"
153
- response += f"Symptoms: {row['Symptoms']}\n"
154
- response += f"Treatment: {row['Treatment']}\n"
155
- response += f"Medicine: {row['Medicine/Chemical Control']}\n\n"
156
  return response
157
 
158
  # If we found only disease
159
  elif disease_match:
160
  matches = df[df['Disease'] == disease_match]
161
  if not matches.empty:
162
- response = f"Information about {disease_match} affecting various crops:\n\n"
163
  for _, row in matches.iterrows():
164
- response += f"Crop: {row['Crop']}\n"
165
- response += f"Symptoms: {row['Symptoms']}\n"
166
- response += f"Treatment: {row['Treatment']}\n"
167
- response += f"Medicine: {row['Medicine/Chemical Control']}\n\n"
168
  return response
169
 
170
  # General search
@@ -195,80 +262,107 @@ def answer_question(question, df):
195
  relevant_rows.sort(key=lambda x: x[0], reverse=True)
196
  top_matches = relevant_rows[:3] # Get top 3 matches
197
 
198
- response = "Here's what I found based on your question:\n\n"
199
  for _, row in top_matches:
200
- response += f"Crop: {row['Crop']}\n"
201
- response += f"Disease: {row['Disease']}\n"
202
- response += f"Symptoms: {row['Symptoms']}\n"
203
- response += f"Treatment: {row['Treatment']}\n"
204
- response += f"Medicine: {row['Medicine/Chemical Control']}\n\n"
205
  return response
206
 
207
- return "I couldn't find specific information related to your question in the database. Please try asking about specific crops or diseases."
208
 
209
- # Function to process image uploads
210
- def process_image(image, df):
211
  if image is None:
212
  return "Please upload an image to analyze.", None, None, None, None
213
 
214
  # Identify the crop and disease
215
- crop, disease = classify_disease(image)
 
 
 
216
 
217
  # Get treatment information
218
  treatment_info = find_treatment(crop, disease, df)
219
 
220
  # Create analysis text
221
  if disease.lower() == "healthy":
222
- analysis = f"Good news! This {crop} plant appears to be healthy."
223
  else:
224
- analysis = f"Analysis: This {crop} plant appears to be affected by {disease}.\n\n"
225
- analysis += f"Typical symptoms of {disease} include {treatment_info['symptoms']}.\n\n"
226
- analysis += f"Recommended treatment: {treatment_info['treatment']}"
 
227
 
228
  return analysis, treatment_info["crop"], treatment_info["disease"], treatment_info["treatment"], treatment_info["medicine"]
229
 
230
- # Main function to set up the Gradio interface
231
  def main():
232
- # Load data
 
 
 
233
  df = load_treatments_data()
234
 
235
- # Create a simplified Gradio interface
236
- with gr.Blocks(title="Plant Disease Assistant") as app:
237
- gr.Markdown("# Plant Disease Treatment Assistant")
238
- gr.Markdown("Upload a plant image or ask a question to get disease and treatment information")
239
 
240
- with gr.Row():
241
- with gr.Column():
242
- # Image input section
243
- gr.Markdown("### Image Analysis")
244
- image_input = gr.Image(type="pil", label="Upload Plant Image")
245
- image_submit = gr.Button("Analyze Image")
246
-
247
- # Question input section
248
- gr.Markdown("### Ask a Question")
249
- question_input = gr.Textbox(
250
- lines=2,
251
- placeholder="Ask a question like 'How do I treat early blight in tomatoes?'",
252
- label="Your Question"
253
- )
254
- question_submit = gr.Button("Get Answer")
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
- with gr.Column():
257
- # Results display
258
- gr.Markdown("### Results")
259
- analysis_output = gr.Markdown(label="Analysis")
260
-
261
- # Structured information display
262
- with gr.Group():
263
- gr.Markdown("### Plant Information")
264
- crop_output = gr.Textbox(label="Crop")
265
- disease_output = gr.Textbox(label="Disease")
266
- treatment_output = gr.Textbox(label="Treatment", lines=3)
267
- medicine_output = gr.Textbox(label="Medicine/Chemical Control", lines=3)
 
 
 
 
 
 
 
 
268
 
269
  # Set up event handlers
270
  image_submit.click(
271
- fn=lambda img: process_image(img, df),
272
  inputs=[image_input],
273
  outputs=[analysis_output, crop_output, disease_output, treatment_output, medicine_output]
274
  )
@@ -276,7 +370,7 @@ def main():
276
  question_submit.click(
277
  fn=lambda q: (answer_question(q, df), "", "", "", ""),
278
  inputs=[question_input],
279
- outputs=[analysis_output, crop_output, disease_output, treatment_output, medicine_output]
280
  )
281
 
282
  # Example questions
@@ -284,14 +378,26 @@ def main():
284
  examples=[
285
  ["How do I treat early blight in tomatoes?"],
286
  ["What are the symptoms of powdery mildew?"],
287
- ["What chemical controls work on apple scab?"]
 
 
288
  ],
289
  inputs=question_input
290
  )
 
 
 
 
 
 
 
 
 
 
291
 
292
  return app
293
 
294
  # Launch the app
295
  if __name__ == "__main__":
296
  app = main()
297
- app.launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
  import os
 
 
4
  import torch
5
+ from torchvision import models, transforms
6
+ from PIL import Image
7
+ import numpy as np
8
+ import json
9
+
10
+ # --- Model Setup ---
11
+ def load_model():
12
+ # Load a pre-trained ResNet model
13
+ model = models.resnet50(pretrained=False)
14
+
15
+ # Modify the final layer for our number of classes
16
+ num_classes = 38 # PlantVillage has 38 classes
17
+ model.fc = torch.nn.Linear(model.fc.in_features, num_classes)
18
+
19
+ # Load the trained weights
20
+ try:
21
+ model.load_state_dict(torch.load('plant_disease_model.pth', map_location=torch.device('cpu')))
22
+ print("Model loaded successfully")
23
+ except:
24
+ print("Model weights not found, using untrained model for demonstration")
25
+
26
+ model.eval()
27
+ return model
28
+
29
+ # --- Data Loading ---
30
+ def load_class_names():
31
+ try:
32
+ with open('class_names.json', 'r') as f:
33
+ class_names = json.load(f)
34
+ print("Class names loaded successfully")
35
+ return class_names
36
+ except:
37
+ print("Class names file not found, using default classes")
38
+ # Default class names from PlantVillage dataset
39
+ return [
40
+ "Apple___Apple_scab", "Apple___Black_rot", "Apple___Cedar_apple_rust", "Apple___healthy",
41
+ "Cherry___healthy", "Cherry___Powdery_mildew", "Corn___Cercospora_leaf_spot",
42
+ "Corn___Common_rust", "Corn___healthy", "Corn___Northern_Leaf_Blight",
43
+ "Grape___Black_rot", "Grape___Esca_(Black_Measles)", "Grape___healthy",
44
+ "Grape___Leaf_blight_(Isariopsis_Leaf_Spot)", "Orange___Haunglongbing_(Citrus_greening)",
45
+ "Peach___Bacterial_spot", "Peach___healthy", "Pepper,_bell___Bacterial_spot",
46
+ "Pepper,_bell___healthy", "Potato___Early_blight", "Potato___healthy",
47
+ "Potato___Late_blight", "Squash___Powdery_mildew", "Strawberry___healthy",
48
+ "Strawberry___Leaf_scorch", "Tomato___Bacterial_spot", "Tomato___Early_blight",
49
+ "Tomato___healthy", "Tomato___Late_blight", "Tomato___Leaf_Mold",
50
+ "Tomato___Septoria_leaf_spot", "Tomato___Spider_mites Two-spotted_spider_mite",
51
+ "Tomato___Target_Spot", "Tomato___Tomato_mosaic_virus",
52
+ "Tomato___Tomato_Yellow_Leaf_Curl_Virus"
53
+ ]
54
 
 
55
  def load_treatments_data():
56
  try:
57
+ context = pd.read_csv('crop_diseases_treatments.csv')
58
  print("CSV file loaded successfully.")
59
  return context
60
  except FileNotFoundError:
61
  print("Error: crop_diseases_treatments.csv not found.")
62
  # Create a minimal dataframe for demonstration
63
  return pd.DataFrame({
64
+ 'Crop': ['Tomato', 'Apple', 'Corn', 'Potato', 'Grape', 'Cherry', 'Peach', 'Strawberry'],
65
+ 'Disease': ['Early Blight', 'Apple Scab', 'Common Rust', 'Late Blight', 'Black Rot', 'Powdery Mildew', 'Bacterial Spot', 'Leaf Scorch'],
66
+ 'Symptoms': [
67
+ 'Brown spots with concentric rings on leaves',
68
+ 'Olive-green to brown spots on leaves and fruit',
69
+ 'Rust-colored pustules on leaves',
70
+ 'Dark water-soaked spots on leaves that turn brown',
71
+ 'Reddish-brown spots on leaves and fruit',
72
+ 'White powdery coating on leaves and stems',
73
+ 'Small brown spots on leaves and fruit',
74
+ 'Scorched appearance on leaf margins'
75
+ ],
76
+ 'Treatment': [
77
+ 'Remove affected leaves, improve air circulation, rotate crops',
78
+ 'Prune affected branches, remove fallen leaves, apply fungicide',
79
+ 'Remove infected plants, apply fungicide early in season',
80
+ 'Remove infected plants, avoid overhead watering, apply fungicide',
81
+ 'Prune infected areas, remove mummified fruit, apply fungicide',
82
+ 'Improve air circulation, apply fungicide, remove infected parts',
83
+ 'Copper-based sprays, crop rotation, remove infected plants',
84
+ 'Ensure proper watering, add mulch, improve soil drainage'
85
+ ],
86
+ 'Medicine/Chemical Control': [
87
+ 'Chlorothalonil, Mancozeb, Copper fungicides',
88
+ 'Captan, Myclobutanil, Sulfur sprays',
89
+ 'Propiconazole, Azoxystrobin, Mancozeb',
90
+ 'Chlorothalonil, Mancozeb, Copper-based fungicides',
91
+ 'Captan, Myclobutanil, Mancozeb',
92
+ 'Sulfur, Potassium bicarbonate, Neem oil',
93
+ 'Copper hydroxide, Streptomycin sulfate',
94
+ 'Calcium nitrate sprays, Fungicides with Captan'
95
+ ]
96
  })
97
 
98
+ # --- Image Processing ---
99
+ def prepare_image_transform():
100
+ return transforms.Compose([
 
101
  transforms.Resize((224, 224)),
102
  transforms.ToTensor(),
103
  transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
104
  ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
+ # --- Disease Classification ---
107
+ def classify_disease(image, model, class_names, transform):
108
+ if image is None:
109
+ return None, None
110
 
111
  # Process the image
112
+ img_tensor = transform(image).unsqueeze(0)
113
+
114
+ # Make prediction
115
+ with torch.no_grad():
116
+ outputs = model(img_tensor)
117
+ _, predicted = torch.max(outputs, 1)
118
+ class_idx = predicted.item()
119
+
120
+ if class_idx < len(class_names):
121
  class_name = class_names[class_idx]
122
 
123
  # Extract crop and disease from class name
 
127
 
128
  return crop, disease
129
 
130
+ return "Unknown", "Unknown"
131
 
132
+ # --- Treatment Lookup ---
133
  def find_treatment(crop, disease, df):
134
  if disease.lower() == "healthy":
135
  return {
 
170
  "crop": crop,
171
  "disease": disease,
172
  "symptoms": "Unknown",
173
+ "treatment": "No specific treatment information found. General advice: Remove affected parts, ensure proper spacing for air circulation, and consider organic or chemical fungicides appropriate for your region.",
174
+ "medicine": "Consult a local agricultural extension office or plant pathologist for specific recommendations for your region."
175
  }
176
 
177
+ # --- Q&A Function ---
178
  def answer_question(question, df):
179
  question = question.lower()
180
 
 
198
  if not matches.empty:
199
  match = matches.iloc[0]
200
  return f"""
201
+ ## {match['Crop']} - {match['Disease']}
202
+
203
+ **Symptoms:**
204
+ {match['Symptoms']}
205
+
206
+ **Treatment:**
207
+ {match['Treatment']}
208
+
209
+ **Recommended Products:**
210
+ {match['Medicine/Chemical Control']}
211
  """
212
 
213
  # If we found only crop
214
  elif crop_match:
215
  matches = df[df['Crop'] == crop_match]
216
  if not matches.empty:
217
+ response = f"## Common Diseases Affecting {crop_match}\n\n"
218
  for _, row in matches.iterrows():
219
+ response += f"### {row['Disease']}\n"
220
+ response += f"**Symptoms:** {row['Symptoms']}\n\n"
221
+ response += f"**Treatment:** {row['Treatment']}\n\n"
222
+ response += f"**Products:** {row['Medicine/Chemical Control']}\n\n"
223
  return response
224
 
225
  # If we found only disease
226
  elif disease_match:
227
  matches = df[df['Disease'] == disease_match]
228
  if not matches.empty:
229
+ response = f"## {disease_match} in Different Crops\n\n"
230
  for _, row in matches.iterrows():
231
+ response += f"### {row['Crop']}\n"
232
+ response += f"**Symptoms:** {row['Symptoms']}\n\n"
233
+ response += f"**Treatment:** {row['Treatment']}\n\n"
234
+ response += f"**Products:** {row['Medicine/Chemical Control']}\n\n"
235
  return response
236
 
237
  # General search
 
262
  relevant_rows.sort(key=lambda x: x[0], reverse=True)
263
  top_matches = relevant_rows[:3] # Get top 3 matches
264
 
265
+ response = "## Here's what I found based on your question:\n\n"
266
  for _, row in top_matches:
267
+ response += f"### {row['Crop']} - {row['Disease']}\n"
268
+ response += f"**Symptoms:** {row['Symptoms']}\n\n"
269
+ response += f"**Treatment:** {row['Treatment']}\n\n"
270
+ response += f"**Products:** {row['Medicine/Chemical Control']}\n\n"
 
271
  return response
272
 
273
+ return "I couldn't find specific information related to your question in my database. Please try asking about specific crops or diseases, or upload an image for analysis."
274
 
275
+ # --- Image Processing Function ---
276
+ def process_image(image, model, class_names, transform, df):
277
  if image is None:
278
  return "Please upload an image to analyze.", None, None, None, None
279
 
280
  # Identify the crop and disease
281
+ crop, disease = classify_disease(image, model, class_names, transform)
282
+
283
+ if crop is None or disease is None:
284
+ return "Unable to analyze the image. Please try a clearer image of a plant leaf.", None, None, None, None
285
 
286
  # Get treatment information
287
  treatment_info = find_treatment(crop, disease, df)
288
 
289
  # Create analysis text
290
  if disease.lower() == "healthy":
291
+ analysis = f"## Good news! \nThis {crop} plant appears to be healthy."
292
  else:
293
+ analysis = f"## Analysis Results\n\nThis {crop} plant appears to be affected by **{disease}**.\n\n"
294
+ analysis += f"**Typical symptoms:**\n{treatment_info['symptoms']}\n\n"
295
+ analysis += f"**Recommended treatment:**\n{treatment_info['treatment']}\n\n"
296
+ analysis += f"**Recommended products:**\n{treatment_info['medicine']}"
297
 
298
  return analysis, treatment_info["crop"], treatment_info["disease"], treatment_info["treatment"], treatment_info["medicine"]
299
 
300
+ # --- Main Function ---
301
  def main():
302
+ # Load model and data
303
+ model = load_model()
304
+ class_names = load_class_names()
305
+ transform = prepare_image_transform()
306
  df = load_treatments_data()
307
 
308
+ # Create Gradio interface
309
+ with gr.Blocks(title="Plant Disease Assistant", css="footer {visibility: hidden}") as app:
310
+ gr.Markdown("""
311
+ # 🌱 Plant Disease Treatment Assistant
312
 
313
+ Upload a plant image or ask a question to get disease identification and treatment information.
314
+ This tool uses a machine learning model trained on the PlantVillage dataset to identify plant diseases.
315
+ """)
316
+
317
+ with gr.Tabs():
318
+ with gr.TabItem("Image Analysis"):
319
+ with gr.Row():
320
+ with gr.Column(scale=1):
321
+ image_input = gr.Image(type="pil", label="Upload Plant Image")
322
+ image_submit = gr.Button("Analyze Image", variant="primary")
323
+
324
+ gr.Markdown("""
325
+ ### Tips for best results:
326
+ - Upload a clear, well-lit image
327
+ - Focus on affected leaves or plant parts
328
+ - Include multiple symptoms if possible
329
+ """)
330
+
331
+ with gr.Column(scale=2):
332
+ analysis_output = gr.Markdown(label="Analysis")
333
+
334
+ with gr.Group():
335
+ gr.Markdown("### Plant Information")
336
+ with gr.Row():
337
+ crop_output = gr.Textbox(label="Crop")
338
+ disease_output = gr.Textbox(label="Disease")
339
+ treatment_output = gr.Textbox(label="Treatment", lines=3)
340
+ medicine_output = gr.Textbox(label="Recommended Products", lines=3)
341
 
342
+ with gr.TabItem("Q&A"):
343
+ with gr.Row():
344
+ with gr.Column():
345
+ question_input = gr.Textbox(
346
+ lines=2,
347
+ placeholder="Ask a question like 'How do I treat early blight in tomatoes?'",
348
+ label="Your Question"
349
+ )
350
+ question_submit = gr.Button("Get Answer", variant="primary")
351
+
352
+ gr.Markdown("""
353
+ ### Example questions:
354
+ - How do I treat early blight in tomatoes?
355
+ - What are the symptoms of powdery mildew?
356
+ - What chemical controls work on apple scab?
357
+ - What causes leaf curl in peach trees?
358
+ """)
359
+
360
+ with gr.Column():
361
+ qa_output = gr.Markdown(label="Answer")
362
 
363
  # Set up event handlers
364
  image_submit.click(
365
+ fn=lambda img: process_image(img, model, class_names, transform, df),
366
  inputs=[image_input],
367
  outputs=[analysis_output, crop_output, disease_output, treatment_output, medicine_output]
368
  )
 
370
  question_submit.click(
371
  fn=lambda q: (answer_question(q, df), "", "", "", ""),
372
  inputs=[question_input],
373
+ outputs=[qa_output, crop_output, disease_output, treatment_output, medicine_output]
374
  )
375
 
376
  # Example questions
 
378
  examples=[
379
  ["How do I treat early blight in tomatoes?"],
380
  ["What are the symptoms of powdery mildew?"],
381
+ ["What chemical controls work on apple scab?"],
382
+ ["How can I prevent late blight in potatoes?"],
383
+ ["What causes black spots on rose leaves?"]
384
  ],
385
  inputs=question_input
386
  )
387
+
388
+ # Example images
389
+ gr.Examples(
390
+ examples=[
391
+ "example_images/tomato_early_blight.jpg",
392
+ "example_images/apple_scab.jpg",
393
+ "example_images/corn_rust.jpg"
394
+ ],
395
+ inputs=image_input
396
+ )
397
 
398
  return app
399
 
400
  # Launch the app
401
  if __name__ == "__main__":
402
  app = main()
403
+ app.launch()