Dev's family runs a small coconut farm in Thrissur district. Every monsoon, coconut palms get attacked by pests and fungal diseases. His father shows photos to an agricultural officer who visits once a month โ but by then, the disease has spread. Dev thought: "I have a trained CNN model from Lesson 1 that classifies plant diseases. What if farmers could upload a photo from their phone and get an instant answer?"
The problem: building a website needs HTML, CSS, JavaScript. FastAPI from Lesson 8 needs a separate frontend. Dev discovered Streamlit โ a Python library that turns a Python script into a full web application. No HTML. No CSS. Just Python. He had a working app in 40 minutes and deployed it online for free.
Streamlit is a Python library that converts a regular Python script into an interactive web application by simply calling functions like st.title(), st.text_input(), and st.image(). Every time a user interacts with a widget (slider, button, file upload), the entire script re-runs from top to bottom and the UI updates.
Drop files here or click to browse
๐ Recommended: Copper oxychloride spray, 3g/litre water.
This is what Dev built. The UI above is a static preview of what the Streamlit app looks like.
import streamlit as st
# Layout
st.title("My AI App")
st.header("Section heading")
st.subheader("Sub-heading")
st.write("Any text, dataframe, chart, dict โ all rendered automatically")
st.markdown("**Bold**, *italic*, and `code` formatting supported")
# Input widgets
name = st.text_input("Your name", placeholder="e.g. Priya")
age = st.number_input("Age", min_value=5, max_value=100, value=15)
lang = st.selectbox("Preferred language", ["English", "Telugu", "Hindi", "Malayalam"])
conf = st.slider("Confidence threshold", min_value=0.0, max_value=1.0, value=0.5)
clicked = st.button("Run prediction")
# File upload
uploaded = st.file_uploader("Upload image", type=["jpg","jpeg","png"])
# Output
st.success("Great job! ๐") # green box
st.warning("Check your input") # yellow box
st.error("Invalid file") # red box
# Show image
if uploaded:
st.image(uploaded, caption="Uploaded image", use_container_width=True)
# Show data and charts
import pandas as pd
df = pd.DataFrame({"Score": [85, 92, 78]}, index=["Run1","Run2","Run3"])
st.dataframe(df)
st.bar_chart(df)# plant_disease_app.py
# Run locally: streamlit run plant_disease_app.py
# Deploy free: https://share.streamlit.io
import streamlit as st
import numpy as np
from PIL import Image
# โโ Page config โโ
st.set_page_config(
page_title="Plant Disease Detector",
page_icon="๐ฟ",
layout="centered"
)
# โโ Cache the model โ loaded once, not on every re-run โโ
@st.cache_resource
def load_model():
"""Load the trained CNN model. Cached so it only loads once."""
try:
import tensorflow as tf
model = tf.keras.models.load_model("plant_disease_model.h5")
return model
except Exception:
return None
# โโ Class labels (matches training dataset order) โโ
CLASSES = [
"Cashew Anthracnose",
"Cashew Gumosis",
"Cassava Bacterial Blight",
"Cassava Brown Spot",
"Coconut Leaf Blight",
"Coconut Leaf Rot",
"Healthy",
"Maize Leaf Blight",
"Maize Leaf Spot",
"Tomato Early Blight"
]
TREATMENTS = {
"Cashew Anthracnose": "Spray Mancozeb 75WP (2.5g/L). Remove infected branches.",
"Cashew Gumosis": "Apply Bordeaux paste on affected areas. Improve drainage.",
"Cassava Bacterial Blight":"Remove and burn infected parts. Use disease-free cuttings.",
"Cassava Brown Spot": "Apply Carbendazim 50WP (1g/L). Ensure good spacing.",
"Coconut Leaf Blight": "Spray Copper oxychloride (3g/L). Improve air circulation.",
"Coconut Leaf Rot": "Apply Bordeaux mixture. Remove fallen debris.",
"Healthy": "No treatment needed. Plant is healthy! โ
",
"Maize Leaf Blight": "Spray Propiconazole (1ml/L). Use resistant varieties.",
"Maize Leaf Spot": "Apply Zineb 75WP (2g/L). Destroy infected crop residue.",
"Tomato Early Blight": "Spray Chlorothalonil 75WP (2g/L). Stake plants well."
}
# โโ App UI โโ
st.title("๐ฟ Plant Disease Detector")
st.markdown("Upload a photo of a plant leaf to identify disease and get treatment advice.")
st.markdown("---")
model = load_model()
if model is None:
st.warning("โ ๏ธ Model file not found. Running in demo mode with random predictions.")
# Sidebar โ settings
with st.sidebar:
st.header("Settings")
confidence_threshold = st.slider("Minimum confidence", 0.3, 1.0, 0.6)
show_top3 = st.checkbox("Show top 3 predictions", value=True)
st.markdown("---")
st.markdown("**Supported crops:**")
st.markdown("Cashew ยท Cassava ยท Coconut ยท Maize ยท Tomato")
# File upload
uploaded_file = st.file_uploader(
"๐ท Upload a leaf image",
type=["jpg", "jpeg", "png"],
help="Take a clear photo of the leaf in good lighting"
)
if uploaded_file is not None:
# Display uploaded image
image = Image.open(uploaded_file).convert("RGB")
col1, col2 = st.columns([1, 1])
with col1:
st.image(image, caption="Uploaded leaf", use_container_width=True)
with col2:
with st.spinner("Analysing..."):
# Preprocess for CNN (224ร224, normalised)
img_array = np.array(image.resize((224, 224))) / 255.0
img_array = np.expand_dims(img_array, axis=0) # (1, 224, 224, 3)
if model is not None:
predictions = model.predict(img_array)[0]
else:
# Demo mode: fake predictions for illustration
predictions = np.random.dirichlet(np.ones(len(CLASSES)) * 0.5)
top_idx = np.argmax(predictions)
top_conf = predictions[top_idx]
top_cls = CLASSES[top_idx]
if top_conf >= confidence_threshold:
if top_cls == "Healthy":
st.success(f"โ
**{top_cls}**\n\n{top_conf*100:.1f}% confident")
else:
st.error(f"โ ๏ธ **{top_cls}**\n\n{top_conf*100:.1f}% confident")
else:
st.warning(f"Low confidence ({top_conf*100:.1f}%). Please upload a clearer photo.")
# Treatment recommendation
if top_conf >= confidence_threshold:
st.markdown("### ๐ Recommended Treatment")
treatment = TREATMENTS.get(top_cls, "Consult an agricultural officer.")
st.info(treatment)
# Top 3 predictions bar chart
if show_top3:
st.markdown("### ๐ Top 3 Predictions")
top3_idx = np.argsort(predictions)[-3:][::-1]
top3_data = {CLASSES[i]: float(predictions[i]) for i in top3_idx}
import pandas as pd
st.bar_chart(pd.Series(top3_data))
# Feedback button
st.markdown("---")
correct = st.radio("Was this prediction correct?", ["Yes", "No"], horizontal=True)
if st.button("Submit feedback"):
st.success("Thank you! Your feedback helps improve the model.")- Create a free GitHub account and push your app code +
requirements.txtto a public repo. Requirements:streamlit,tensorflow,pillow,numpy - Go to share.streamlit.io and sign in with GitHub
- Click "New app", select your repo, set main file as
plant_disease_app.py - Click "Deploy" โ Streamlit Cloud installs packages and starts your app automatically
- Share the public URL (e.g.,
yourname-plant-detector.streamlit.app) โ anyone in the world can use your app from any browser
gdown or boto3 rather than committed to GitHub.