Back to All Projects
Machine Learning  ·  Agriculture  ·  Live on Hugging Face

Crop Disease Detector

An AI model that identifies plant diseases from a single leaf photo. MobileNetV2 + Transfer Learning trained on 87,000+ images across 38 disease classes. ~97% accuracy. Live on Hugging Face Spaces, free to use.

TensorFlow MobileNetV2 Transfer Learning PlantVillage Dataset Gradio Hugging Face
Live on Hugging Face Spaces: Free · No account needed · Upload a leaf photo and get an instant diagnosis
Status
Completed · Live
Year
2026
Model
MobileNetV2
Accuracy
~97%
Classes
38 disease types
Dataset
87K+ images
01 Project Overview

Crop Disease Detector reads a leaf photo and tells you what's wrong with the plant. Upload a photo and the model names which of 38 disease conditions it's likely showing — in seconds, for free.

MobileNetV2 was chosen for efficiency — near-ResNet accuracy at a fraction of the compute, which is what makes free-tier deployment viable. The model is trained on the PlantVillage dataset: 87,000+ high-quality images of healthy and diseased leaves across 14 crop types.

The motivation: Crop disease is estimated to cost agriculture over $220 billion a year globally. Most of that loss is preventable with early detection, but access to diagnosis tools is extremely unequal. This was my attempt at making one more accessible.
02 In Practice

What the model actually sees, and what it returns. The two leaf samples below are the kind of input a farmer would photograph; the result screens are the app's output for each.

Diseased leafInput sample with visible disease symptoms
Healthy leafInput sample from an unaffected plant
PredictionClassification and confidence returned for the diseased sample
PredictionClassification returned for the healthy sample
DatasetClass distribution across the training set
TrainingTraining and validation curves
PipelineHow a photo becomes a prediction, end to end
03 Model Architecture & Training Math

MobileNetV2 uses depthwise separable convolutions to drastically reduce parameter count while preserving feature extraction power. Transfer Learning from ImageNet weights means we start with powerful low-level feature detectors (edges, textures) already learned.

01Depthwise Separable Convolution vs Standard
Standard Conv     = K × K × C_in × C_out
Depthwise Sep     = K × K × C_in          ← depthwise
                  + 1 × 1 × C_in × C_out  ← pointwise

Rather than one filter across all channels, MobileNetV2 splits the work: a per-channel spatial filter (depthwise), then a 1×1 channel mixer (pointwise). That's ~8–9× fewer multiply-adds for the same output shape — why it runs fast on a phone CPU.

3×3 conv, 32 channels in → 64 channels out:

  Standard:  3 × 3 × 32 × 64  = 18,432 params
  DepthSep:  3 × 3 × 32       =    288  (depthwise)
           + 1 × 1 × 32 × 64  =  2,048  (pointwise)
           =                     2,336  total  (≈8× fewer)
02Transfer Learning Fine-Tuning Strategy
Phase 1, Feature Extraction
  Freeze all MobileNetV2 layers
  Train only top head  |  epochs=10, LR=1e-3

Phase 2, Fine-Tuning  
  Unfreeze top 30 MobileNetV2 layers
  Retrain with low LR  |  epochs=20, LR=1e-4

Augmentation: RandomFlip · RandomRotation(0.2)
              RandomZoom(0.1) · RandomContrast(0.1)

Two-phase training is a standard trick with pretrained models. Phase 1 warms up the new classification head without touching the ImageNet weights (so you don't immediately destroy what was learned). Phase 2 uses a tiny learning rate to gently nudge the upper layers toward leaf disease patterns, aggressive updates here would cause "catastrophic forgetting."

# TensorFlow / Keras pseudocode

# Phase 1
base_model.trainable = False
model.compile(optimizer=Adam(1e-3)...)
model.fit(train_ds, epochs=10)

# Phase 2  
for layer in base_model.layers[-30:]:
    layer.trainable = True
model.compile(optimizer=Adam(1e-4)...)
model.fit(train_ds, epochs=20)
03Loss Function & Final Metrics
Loss = Categorical Cross-Entropy
     = −Σ y_i × log(ŷ_i)  for i in 1..38 classes

Validation Results
  Accuracy   ~97.2%     Top-5 Acc  ~99.8%
  Precision  ~96.9%     Recall     ~97.1%
  F1-Score   ~97.0%     (all macro avg)

Cross-entropy penalises confidence in the wrong class — 80% confidence on Healthy when the label is Tomato Blight scores a high loss. That pushes the network toward being right and confident. The macro-average F1 of 97% means consistent performance across rare and common classes, not just the easy majority.

# Concrete example for one prediction:
true_label   = [0, 0, 1, 0...]  # class 2 = "Tomato Blight"
predicted    = [0.01, 0.02, 0.93, 0.01...]

loss = −log(0.93) = 0.073   ← low, model was right

# If model was uncertain:
predicted    = [0.10, 0.30, 0.40, 0.05...]
loss = −log(0.40) = 0.916   ← higher penalty
04 Processing Pipeline
Input
Leaf Photo
Any format
Preprocess
Resize + Normalize
224×224 px
Backbone
MobileNetV2
Feature extraction
Head
Dense + Softmax
38-class output
Output
Disease Class
+ confidence %
swipe to explore the full pipeline
05 Disease Classes (38 Total)

The model covers 14 crop types and 38 disease conditions including healthy states. A sample of the classes:

Apple, Apple Scab
Apple, Black Rot
Apple, Cedar Rust
Corn, Gray Leaf Spot
Corn, Common Rust
Grape, Black Rot
Potato, Early Blight
Potato, Late Blight
Tomato, Leaf Mold
Tomato, Mosaic Virus
Tomato, Blight
Strawberry, Leaf Scorch

+ 26 more classes across rice, wheat, pepper, peach, cherry, orange, and soybean. All classes include a "Healthy" baseline.

Tech Stack
Python 3 TensorFlow Keras MobileNetV2 Gradio NumPy Pillow HF Spaces
Try it live: no setup needed.
Open the Hugging Face Space, upload a leaf photo, and get an instant AI diagnosis. Free, public, zero install. 38 disease classes, 87K training images, ~97% accuracy.
Open on Hugging Face