PlantMD is an image-based plant disease diagnosis web app. Upload a photo of a leaf and it predicts the most likely disease (or healthy) class out of 38 categories, along with a confidence score and a short description.
The model is a VGG16 transfer-learning network trained on the 54,000-image PlantVillage dataset, augmented (mainly via rotation) to ~87,000 images to balance the originally skewed class distribution, then split 80/20 into training and validation sets.
👇 Screenshots:
app.py # Streamlit entrypoint
src/plantmd/
inference.py # preprocessing + top-k prediction
descriptions.py # disease description lookup
model.py # cached model loading (downloads from HF Hub)
models/
disease_description.csv # per-class description text
tests/ # pytest suite (no real model weights required)
Dependencies are declared in pyproject.toml (the source of truth). A root
requirements.txt is also kept, containing only -e ., purely because
Streamlit Community Cloud and Hugging Face Spaces auto-detect dependencies
from a root requirements.txt file rather than pyproject.toml — it installs
this project itself, so there's nothing to keep in sync by hand.
The trained model weights (model_vgg16_2.hdf5) are not committed to
this repo. They're hosted on Hugging Face Hub
and downloaded automatically by src/plantmd/model.py the first time the app
runs, then cached under models/ for subsequent runs. No Git LFS involved.
The weights are an old-style HDF5 file saved with Keras 2. TensorFlow 2.16+
switched tf.keras to Keras 3 by default, which can't load that format, so
tf-keras is pinned alongside tensorflow and src/plantmd/__init__.py
sets TF_USE_LEGACY_KERAS=1 to keep tf.keras on the legacy Keras 2
implementation that can still read it.
git clone https://github.com/upendrak/plantmd.git && cd plantmd
pip install -e .[dev]
streamlit run app.pyThe first run downloads the model weights from Hugging Face Hub (a one-time
cost); after that they're read from the local models/ cache. Open
http://localhost:8501/ and upload an image (a few samples are in
example_images/).
Run the test suite (works without the real model weights, using fakes/fixtures):
pytestdocker build -t plantmd .
docker run --rm -p 8501:8501 plantmdOpen http://localhost:8501/. The container downloads the model weights from Hugging Face Hub on its first run (needs outbound internet access).
Both platforms can deploy directly from this repo:
- Streamlit Community Cloud: point a new app at this repo, branch
master, main fileapp.py. It installs fromrequirements.txtautomatically, and the model weights download from Hugging Face Hub on first run. - Hugging Face Spaces: create a Space with SDK "Streamlit", then use
docs/huggingface-space-readme.mdas a starting template for that Space's ownREADME.md(Spaces require SDK metadata in the Space's README frontmatter, which is a separate file from this repo's README).
GPLv3 — see LICENSE.

