Regino commited on
Commit Β·
dd1c2c5
1
Parent(s): 27bd65f
ndnfkd
Browse files
app.py
CHANGED
|
@@ -8,22 +8,6 @@ import os
|
|
| 8 |
import random
|
| 9 |
import pandas as pd
|
| 10 |
import matplotlib.pyplot as plt
|
| 11 |
-
import zipfile # Added for zip extraction
|
| 12 |
-
|
| 13 |
-
# ---- Dataset Extraction Logic ----
|
| 14 |
-
DATASET_ZIP = "rice_leaf_diseases.zip"
|
| 15 |
-
DATASET_FOLDER = "rice_leaf_diseases"
|
| 16 |
-
|
| 17 |
-
# Check and extract dataset if needed
|
| 18 |
-
if not os.path.exists(DATASET_FOLDER):
|
| 19 |
-
if os.path.exists(DATASET_ZIP):
|
| 20 |
-
with zipfile.ZipFile(DATASET_ZIP, 'r') as zip_ref:
|
| 21 |
-
zip_ref.extractall()
|
| 22 |
-
st.success("Dataset extracted successfully!")
|
| 23 |
-
else:
|
| 24 |
-
st.error(f"Dataset zip file '{DATASET_ZIP}' not found!")
|
| 25 |
-
else:
|
| 26 |
-
st.toast("Dataset already available!", icon="β
")
|
| 27 |
|
| 28 |
# Define Model Class
|
| 29 |
class RiceDiseaseCNN(nn.Module):
|
|
@@ -67,11 +51,11 @@ transform = transforms.Compose([
|
|
| 67 |
# Class Labels
|
| 68 |
class_labels = ["Bacterial Leaf Blight", "Brown Spot", "Leaf Smut"]
|
| 69 |
|
| 70 |
-
# Streamlit App
|
| 71 |
st.set_page_config(page_title="Rice Disease Detection", layout="wide")
|
| 72 |
|
| 73 |
-
#
|
| 74 |
-
dataset_path =
|
| 75 |
|
| 76 |
# Sidebar Navigation
|
| 77 |
st.sidebar.title("Navigation")
|
|
@@ -88,7 +72,9 @@ if page == "Dataset":
|
|
| 88 |
The dataset is available on [Kaggle](https://www.kaggle.com/datasets/vbookshelf/rice-leaf-diseases).
|
| 89 |
""")
|
| 90 |
|
|
|
|
| 91 |
def get_sample_images(label, count=3):
|
|
|
|
| 92 |
label_path = os.path.join(dataset_path, label)
|
| 93 |
images = [img for img in os.listdir(label_path) if img.endswith(("png", "jpg", "jpeg"))]
|
| 94 |
sample_images = random.sample(images, min(count, len(images)))
|
|
@@ -101,80 +87,134 @@ if page == "Dataset":
|
|
| 101 |
with cols[idx]:
|
| 102 |
st.write(f"### {label}")
|
| 103 |
for img_path in images:
|
| 104 |
-
st.image(img_path,
|
| 105 |
|
| 106 |
# Data Visualization Page
|
| 107 |
elif page == "Data Visualization":
|
| 108 |
st.title("Data Visualization π")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
def get_image_count(label):
|
|
|
|
| 111 |
label_path = os.path.join(dataset_path, label)
|
| 112 |
-
|
|
|
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
| 116 |
st.subheader("Class Distribution")
|
| 117 |
-
|
| 118 |
|
| 119 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
fig, ax = plt.subplots()
|
| 121 |
ax.pie(df["Count"], labels=df["Disease"], autopct='%1.1f%%', startangle=90)
|
| 122 |
-
ax.axis('equal')
|
| 123 |
st.pyplot(fig)
|
| 124 |
-
|
| 125 |
-
# Bar Chart
|
|
|
|
| 126 |
fig, ax = plt.subplots()
|
| 127 |
-
ax.bar(df["Disease"], df["Count"], color=['
|
| 128 |
ax.set_xlabel('Disease Type')
|
| 129 |
ax.set_ylabel('Number of Images')
|
|
|
|
| 130 |
st.pyplot(fig)
|
| 131 |
|
| 132 |
# Model Metrics Page
|
| 133 |
elif page == "Model Metrics":
|
| 134 |
st.title("Model Performance Metrics π")
|
|
|
|
|
|
|
| 135 |
st.markdown("""
|
| 136 |
-
### Model
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
""")
|
| 141 |
-
|
| 142 |
# Confusion Matrix
|
| 143 |
st.subheader("Confusion Matrix")
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
| 156 |
st.subheader("Classification Report")
|
| 157 |
-
st.
|
| 158 |
-
|
| 159 |
-
Bacterial Leaf Blight 0.90 1.00 0.95 9
|
| 160 |
-
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
| 162 |
""")
|
| 163 |
|
|
|
|
| 164 |
# Classification Page
|
| 165 |
elif page == "Classification":
|
| 166 |
st.title("Rice Leaf Disease Classification π")
|
| 167 |
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
-
if uploaded_file:
|
|
|
|
| 171 |
image = Image.open(uploaded_file).convert("RGB")
|
| 172 |
-
st.image(image,
|
|
|
|
|
|
|
| 173 |
|
| 174 |
-
#
|
| 175 |
-
image_tensor = transform(image).unsqueeze(0)
|
| 176 |
with torch.no_grad():
|
| 177 |
-
|
| 178 |
-
_, predicted = torch.max(
|
| 179 |
|
| 180 |
-
|
|
|
|
|
|
|
|
|
| 8 |
import random
|
| 9 |
import pandas as pd
|
| 10 |
import matplotlib.pyplot as plt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
# Define Model Class
|
| 13 |
class RiceDiseaseCNN(nn.Module):
|
|
|
|
| 51 |
# Class Labels
|
| 52 |
class_labels = ["Bacterial Leaf Blight", "Brown Spot", "Leaf Smut"]
|
| 53 |
|
| 54 |
+
# Streamlit App
|
| 55 |
st.set_page_config(page_title="Rice Disease Detection", layout="wide")
|
| 56 |
|
| 57 |
+
# Dataset path
|
| 58 |
+
dataset_path = "rice_leaf_diseases" # Define this globally
|
| 59 |
|
| 60 |
# Sidebar Navigation
|
| 61 |
st.sidebar.title("Navigation")
|
|
|
|
| 72 |
The dataset is available on [Kaggle](https://www.kaggle.com/datasets/vbookshelf/rice-leaf-diseases).
|
| 73 |
""")
|
| 74 |
|
| 75 |
+
# Show sample images per class
|
| 76 |
def get_sample_images(label, count=3):
|
| 77 |
+
"""Gets sample images from a given disease class folder."""
|
| 78 |
label_path = os.path.join(dataset_path, label)
|
| 79 |
images = [img for img in os.listdir(label_path) if img.endswith(("png", "jpg", "jpeg"))]
|
| 80 |
sample_images = random.sample(images, min(count, len(images)))
|
|
|
|
| 87 |
with cols[idx]:
|
| 88 |
st.write(f"### {label}")
|
| 89 |
for img_path in images:
|
| 90 |
+
st.image(img_path, use_container_width=True)
|
| 91 |
|
| 92 |
# Data Visualization Page
|
| 93 |
elif page == "Data Visualization":
|
| 94 |
st.title("Data Visualization π")
|
| 95 |
+
st.markdown("Here is a sample visualization of rice leaf disease image distribution.")
|
| 96 |
+
|
| 97 |
+
# Count images per class
|
| 98 |
+
class_counts = {}
|
| 99 |
|
| 100 |
def get_image_count(label):
|
| 101 |
+
"""Counts the number of images in a given class folder."""
|
| 102 |
label_path = os.path.join(dataset_path, label)
|
| 103 |
+
images = [img for img in os.listdir(label_path) if img.endswith(("png", "jpg", "jpeg"))]
|
| 104 |
+
return len(images)
|
| 105 |
|
| 106 |
+
# Count images for each class
|
| 107 |
+
for label in class_labels:
|
| 108 |
+
class_counts[label] = get_image_count(label)
|
| 109 |
+
|
| 110 |
+
# Display class distribution
|
| 111 |
st.subheader("Class Distribution")
|
| 112 |
+
st.write(f"Total number of images in each class:")
|
| 113 |
|
| 114 |
+
# Convert counts to DataFrame for visualization
|
| 115 |
+
df = pd.DataFrame(list(class_counts.items()), columns=["Disease", "Count"])
|
| 116 |
+
|
| 117 |
+
# Pie Chart Visualization (Matplotlib)
|
| 118 |
+
st.subheader("Disease Distribution as Pie Chart")
|
| 119 |
fig, ax = plt.subplots()
|
| 120 |
ax.pie(df["Count"], labels=df["Disease"], autopct='%1.1f%%', startangle=90)
|
| 121 |
+
ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
|
| 122 |
st.pyplot(fig)
|
| 123 |
+
|
| 124 |
+
# Bar Chart Visualization (Matplotlib)
|
| 125 |
+
st.subheader("Disease Distribution as Bar Chart")
|
| 126 |
fig, ax = plt.subplots()
|
| 127 |
+
ax.bar(df["Disease"], df["Count"], color=['blue', 'green', 'red'])
|
| 128 |
ax.set_xlabel('Disease Type')
|
| 129 |
ax.set_ylabel('Number of Images')
|
| 130 |
+
ax.set_title('Rice Leaf Disease Distribution')
|
| 131 |
st.pyplot(fig)
|
| 132 |
|
| 133 |
# Model Metrics Page
|
| 134 |
elif page == "Model Metrics":
|
| 135 |
st.title("Model Performance Metrics π")
|
| 136 |
+
|
| 137 |
+
# Model Description
|
| 138 |
st.markdown("""
|
| 139 |
+
### Model Overview
|
| 140 |
+
The model used for this classification task is a **Convolutional Neural Network (CNN)**.
|
| 141 |
+
CNNs are commonly used for image classification tasks because they are effective at recognizing spatial hierarchies in images.
|
| 142 |
+
|
| 143 |
+
#### Model Architecture
|
| 144 |
+
The architecture consists of the following layers:
|
| 145 |
+
- **Convolutional Layers**: These layers apply filters to the image to detect features such as edges, textures, and patterns.
|
| 146 |
+
- **Conv1**: 3 input channels (RGB), 32 output channels, 3x3 kernel.
|
| 147 |
+
- **Conv2**: 32 input channels, 64 output channels, 3x3 kernel.
|
| 148 |
+
- **Conv3**: 64 input channels, 128 output channels, 3x3 kernel.
|
| 149 |
+
- **Batch Normalization**: Applied after each convolutional layer to stabilize and speed up training.
|
| 150 |
+
- **MaxPooling**: Reduces the spatial dimensions of the feature maps (2x2 pool).
|
| 151 |
+
- **Fully Connected Layers**: The output from the convolutional layers is flattened and passed through fully connected layers.
|
| 152 |
+
- **FC1**: 128 * 16 * 16 input features, 512 output units.
|
| 153 |
+
- **FC2**: 512 input units, output units corresponding to the number of disease classes (3 classes in total).
|
| 154 |
+
|
| 155 |
+
#### Model Training
|
| 156 |
+
The model was trained on a dataset of rice leaf disease images. The training process involved optimizing the model using a **cross-entropy loss** function and an **Adam optimizer**.
|
| 157 |
+
The model was trained to minimize the error between predicted and actual class labels.
|
| 158 |
+
|
| 159 |
""")
|
| 160 |
+
|
| 161 |
# Confusion Matrix
|
| 162 |
st.subheader("Confusion Matrix")
|
| 163 |
+
cm_image = Image.open("con_mat.png")
|
| 164 |
+
st.image(cm_image, caption="Confusion Matrix", use_container_width=True)
|
| 165 |
+
|
| 166 |
+
# Training Loss
|
| 167 |
+
st.subheader("Training Loss")
|
| 168 |
+
loss_image = Image.open("train_loss.png")
|
| 169 |
+
st.image(loss_image, caption="Training Loss Curve", use_container_width=True)
|
| 170 |
+
|
| 171 |
+
# Validation Accuracy
|
| 172 |
+
st.subheader("Validation Accuracy")
|
| 173 |
+
acc_image = Image.open("val_acc.png")
|
| 174 |
+
st.image(acc_image, caption="Validation Accuracy Curve", use_container_width=True)
|
| 175 |
+
|
| 176 |
+
# Accuracy Table
|
| 177 |
st.subheader("Classification Report")
|
| 178 |
+
st.text("""
|
| 179 |
+
precision recall f1-score support
|
| 180 |
+
Bacterial Leaf Blight 0.90 1.00 0.95 9
|
| 181 |
+
Brown Spot 1.00 1.00 1.00 5
|
| 182 |
+
Leaf Smut 1.00 0.75 0.86 4
|
| 183 |
+
Accuracy 0.94 18
|
| 184 |
+
Macro Avg 0.97 0.92 0.93 18
|
| 185 |
+
Weighted Avg 0.95 0.94 0.94 18
|
| 186 |
""")
|
| 187 |
|
| 188 |
+
|
| 189 |
# Classification Page
|
| 190 |
elif page == "Classification":
|
| 191 |
st.title("Rice Leaf Disease Classification π")
|
| 192 |
|
| 193 |
+
st.markdown("""
|
| 194 |
+
### About the Classification Model
|
| 195 |
+
This model is designed to classify rice leaf diseases based on images. It uses a Convolutional Neural Network (CNN) trained on a dataset of rice leaf images.
|
| 196 |
+
The model can classify the following rice leaf diseases:
|
| 197 |
+
- **Bacterial Leaf Blight**: Caused by *Xanthomonas oryzae* bacteria.
|
| 198 |
+
- **Brown Spot**: Caused by *Cochliobolus miyabeanus* fungus.
|
| 199 |
+
- **Leaf Smut**: Caused by *Entyloma oryzae* fungus.
|
| 200 |
+
|
| 201 |
+
The model analyzes the uploaded image and predicts which disease the rice leaf is affected by. The image is processed through the network and the disease type is determined by comparing the features extracted from the image to the trained data.
|
| 202 |
+
""")
|
| 203 |
+
|
| 204 |
+
uploaded_file = st.file_uploader("Upload an image of a rice leaf", type=["jpg", "png", "jpeg"])
|
| 205 |
|
| 206 |
+
if uploaded_file is not None:
|
| 207 |
+
# Preprocess Image
|
| 208 |
image = Image.open(uploaded_file).convert("RGB")
|
| 209 |
+
st.image(image, caption="Uploaded Image", use_container_width=True)
|
| 210 |
+
|
| 211 |
+
image = transform(image).unsqueeze(0)
|
| 212 |
|
| 213 |
+
# Predict
|
|
|
|
| 214 |
with torch.no_grad():
|
| 215 |
+
outputs = model(image)
|
| 216 |
+
_, predicted = torch.max(outputs, 1)
|
| 217 |
|
| 218 |
+
# Display Prediction
|
| 219 |
+
st.subheader("Prediction Result:")
|
| 220 |
+
st.success(f"Predicted Disease: **{class_labels[predicted.item()]}**")
|