Potato Disease Classification
Deep learning model that identifies potato leaf diseases with 95%+ accuracy, deployed as a FastAPI service with a Streamlit interface.
- Role
- Solo build — model, API, UI
- Year
- 2024
- Stack
- Python · TensorFlow · CNN · FastAPI · Streamlit
- Links
- GitHub ↗

Overview
An end-to-end computer vision system that classifies potato leaves as Healthy, Early Blight, or Late Blight from a single photo. Trained on the PlantVillage dataset with a convolutional neural network, packaged behind a FastAPI inference endpoint, and served through a lightweight Streamlit interface intended for farmers and field workers.
Problem statement
Late diagnosis of potato foliar diseases is a major yield-loss driver for smallholder farmers. Existing tooling is either lab-bound or requires strong connectivity. The goal was to ship a fast, offline-friendly classifier that runs on a phone photo and returns actionable output in under a second.
Architecture
- 01Data pipeline: PlantVillage images resized to 256×256, augmented with random flips, rotations, and zoom to reduce overfitting on background artifacts.
- 02Model: a compact CNN (3 conv-pool blocks → dense head) trained with sparse categorical cross-entropy and Adam. Class weights tuned to handle mild dataset imbalance.
- 03Serving: model exported to TensorFlow SavedModel format and loaded once per FastAPI worker; predictions returned as JSON with class probabilities.
- 04UI: Streamlit front-end for drag-and-drop images that calls the FastAPI endpoint over HTTP.
Tech stack
- Python
- TensorFlow
- CNN
- FastAPI
- Streamlit
Features
- Real-time inference under 300ms per image on CPU
- Confidence score returned alongside the predicted class
- Image preprocessing handled server-side so mobile clients stay thin
- Swagger docs auto-generated from FastAPI schemas for easy integration
Challenges
- Class imbalance between healthy and late-blight samples was hurting recall — solved by class weighting and targeted augmentation.
- Streamlit and FastAPI had to run as separate processes; introduced a small shared config module to avoid drift between the two.
- Cold-start latency on first inference — solved by warming the model with a dummy tensor at startup.
Results
- 95%+ accuracy on held-out test set across all three classes
- Sub-300ms average inference on commodity CPU
- Reusable inference module packaged for other crop-disease datasets
Lessons learned
- A small, well-augmented CNN beats a large under-regularized one on niche image datasets.
- Serving and modelling are two very different disciplines — keeping them in separate modules paid off during iteration.
- Streamlit is great for demos but the real product surface belongs behind a proper HTTP API.