Evaluating the robustness of modern deep learning models to image quality degradation in plant disease diagnosis from leaf photographs.
This repository contains the full, reproducible experimental pipeline behind the paper "Evaluating the Robustness of Modern Deep Learning Models to Image Quality Degradation in Plant Disease Diagnosis from Leaf Photographs." It fine-tunes four modern architectures on the PlantVillage dataset, evaluates them under five types of synthetic image corruption at five severity levels each, and produces all tables, figures, and statistical tests reported in the paper — with no manually entered or assumed numbers.
Clean-test accuracy does not predict robustness. All four models exceed
99% accuracy on clean PlantVillage images, but under synthetic corruption
(Gaussian noise, blur, brightness reduction, JPEG compression,
resolution loss) their behavior diverges sharply: ConvNeXt-Tiny and
ViT-B/16 are significantly more robust than ResNet-50 and EfficientNet-B0
(Friedman test, χ² = 34.40, p < 10⁻⁶; Nemenyi post-hoc, α = 0.05).
EfficientNet-B0 — despite having the second-highest clean accuracy of the
four — is the least robust model overall and collapses to a single
dominant prediction under severe Gaussian noise (6.1% accuracy, near the
2.6% random-guessing floor for 38 classes). Full results, figures, and
statistical detail are in the paper (paper/article_draft_en.md), included
in this repository together with its figures (paper/graphs/).
PlantAIResearch/
├── data/
│ ├── raw/ # PlantVillage in ImageFolder layout: raw/{train,val,test}/<class>/*.jpg
│ │ # (populated by prepare_data.py — not committed to git, see .gitignore)
│ └── degraded/ # corrupted copies of the test set, generated by degrade.py
├── models/
│ └── checkpoints/ # trained model checkpoints (*.pt) + a config.json per model
├── results/
│ ├── metrics_<model>_<condition>.json # full metrics + confusion matrix for every run
│ ├── summary.csv # summary table across all runs
│ └── mce_summary.csv # mean Corruption Error per model
├── graphs/ # accuracy-vs-severity plots (PNG), one per corruption type
├── paper/
│ ├── article_draft_en.md # the paper itself, with tables and embedded figures
│ └── graphs/ # copies of the figures referenced by the paper
├── utils.py # seeding, dataloaders, metrics, experiment config
├── prepare_data.py # downloads PlantVillage and lays it out as ImageFolder
├── degrade.py # generates the five types of corrupted test images
├── train.py # fine-tunes each of the four architectures
├── evaluate.py # evaluates a checkpoint on clean/corrupted data
├── analyze.py # statistical tests (Friedman/Nemenyi), mCE, plots
├── requirements.txt
├── LICENSE
└── CITATION.cff
| Script | Responsibility | Typical invocation |
|---|---|---|
utils.py |
Shared library code: seeding for reproducibility, ImageFolder-based DataLoader construction, metric computation (Accuracy/Precision/Recall/F1, confusion matrix), experiment config save/load. Not run directly. |
— |
prepare_data.py |
Downloads the official PlantVillage split files and image archive from Hugging Face Hub (mohanty/PlantVillage) and materializes data/raw/{train,val,test}/<class>/*.jpg. The official leaf-grouped train/test split is preserved; val is carved out of train via a stratified split. Does not require a GPU. |
python prepare_data.py |
degrade.py |
Applies five synthetic corruption types (Gaussian blur, Gaussian noise, brightness reduction, JPEG compression, downscale–upscale) at five severity levels each to a clean image folder (normally data/raw/test), writing corrupted copies to data/degraded/<corruption>/severity_<n>/<class>/. |
python degrade.py --input data/raw/test --output data/degraded |
train.py |
Fine-tunes one architecture (resnet50, efficientnet_b0, convnext_tiny, or vit_b_16) on data/raw/train, validating on data/raw/val. Two-phase schedule: linear probing (frozen backbone) for the first --freeze_backbone_epochs epochs, then full fine-tuning at a reduced learning rate. Saves the best checkpoint (by validation macro-F1) to models/checkpoints/. Requires a GPU for practical runtimes. |
python train.py --model resnet50 |
evaluate.py |
Loads a trained checkpoint and evaluates it on a clean directory (--data_dir) and/or on every corrupted condition under data/degraded (--sweep_all), appending a row per condition to results/summary.csv and writing a full-detail JSON per run. |
python evaluate.py --checkpoint models/checkpoints/resnet50_best.pt --data_dir data/raw/test --condition clean --sweep_all |
analyze.py |
Reads results/summary.csv, plots accuracy-vs-severity per corruption type into graphs/, computes mean Corruption Error (mCE, normalized against ResNet-50) into results/mce_summary.csv, and runs the Friedman test (plus Nemenyi post-hoc, if scikit-posthocs is installed) for statistical comparison of the four architectures. |
python analyze.py |
- Python 3.10–3.12
- A CUDA-capable GPU is strongly recommended for
train.py(fine-tuning four architectures on ~54k images on CPU is possible but takes far longer).prepare_data.pyanddegrade.pydo not require a GPU. - ~3 GB of free disk space (the PlantVillage archive is ~2.2 GB; corrupted copies and checkpoints add a few GB more).
All Python dependencies are listed in requirements.txt:
torch>=2.2
torchvision>=0.17
timm>=0.9
huggingface_hub>=0.23
opencv-python-headless>=4.9
numpy>=1.26
pandas>=2.2
matplotlib>=3.8
scikit-learn>=1.4
scipy>=1.12
scikit-posthocs>=0.9
Pillow>=10.2
tqdm>=4.66
timm is included for convenience/future extension but is not currently
imported by any script — all four architectures are built directly from
torchvision.models.
git clone https://github.com/gorasatryanGH/PlantAIResearch.git
cd PlantAIResearch
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activateInstall PyTorch with CUDA support first, matching your GPU driver (see pytorch.org/get-started/locally for the exact command for your platform), for example:
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124Then install the remaining dependencies:
pip install -r requirements.txtVerify that PyTorch sees your GPU:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"Run each command from the repository root, in order, waiting for each to finish before starting the next:
# 1. Download PlantVillage and lay it out as ImageFolder (no GPU needed, ~2.2 GB download)
python prepare_data.py
# 2. Fine-tune all four architectures (GPU strongly recommended)
python train.py --model resnet50
python train.py --model efficientnet_b0
python train.py --model convnext_tiny
python train.py --model vit_b_16
# 3. Generate corrupted versions of the test set
python degrade.py --input data/raw/test --output data/degraded \
--corruptions gaussian_blur gaussian_noise brightness_down jpeg_compression downscale_upscale \
--severities 1 2 3 4 5
# 4. Evaluate each model on the clean test set and on every corrupted condition
python evaluate.py --checkpoint models/checkpoints/resnet50_best.pt --data_dir data/raw/test --condition clean --sweep_all
python evaluate.py --checkpoint models/checkpoints/efficientnet_b0_best.pt --data_dir data/raw/test --condition clean --sweep_all
python evaluate.py --checkpoint models/checkpoints/convnext_tiny_best.pt --data_dir data/raw/test --condition clean --sweep_all
python evaluate.py --checkpoint models/checkpoints/vit_b_16_best.pt --data_dir data/raw/test --condition clean --sweep_all
# 5. Statistical analysis and plots
python analyze.pyOutputs land in results/ (tables, per-run JSON metrics) and graphs/
(PNG plots) at the repository root.
If train.py raises a CUDA out-of-memory error, reduce the batch size,
e.g. python train.py --model resnet50 --batch_size 16.
These are enforced by the code and are worth restating for anyone auditing or extending this repository:
- The training set is never corrupted.
degrade.pyis only ever applied to evaluation data (typicallydata/raw/test). Training on corrupted images and then evaluating robustness against the same corruption types would conflate data augmentation with genuine out-of-the-box robustness. - The same test set is reused across severity levels. Only the corruption strength changes between severity 1 and 5 — the underlying set of images stays identical, so accuracy differences are attributable to corruption strength alone.
- All stochastic steps use a fixed seed (42). Weight initialization
order effects, the train/val split, and data ordering are reproducible
run-to-run, modulo the well-known limits of exact CUDA-kernel-level
determinism (see the docstring of
utils.set_seed). - Class order is checked at evaluation time.
evaluate.pycomparesImageFolder.classesbetween the training-time class list (stored in the checkpoint) and the evaluation directory, and warns if they differ — a common, silent source of label-mismatch bugs in this kind of pipeline. - The official leaf-grouped PlantVillage split is preserved.
prepare_data.pyuses the dataset authors'splits/color_train.txt/splits/color_test.txt, in which photographs of the same physical leaf never appear in both partitions, avoiding a common source of inflated accuracy in prior work on this dataset.
- PlantVillage images are captured under controlled laboratory conditions (uniform background, standardized lighting). This repository measures sensitivity to technical image-quality degradation in isolation; it does not measure robustness to the full combination of factors present in field deployment (background clutter, viewpoint, multiple leaves per frame), which is a separate, already well-studied problem (see the PlantDoc dataset).
- The five corruption functions in
degrade.pyare synthetic approximations of real capture artifacts (implemented via OpenCV/PIL), not calibrated models of any specific smartphone sensor. - Robustness is evaluated only for models fine-tuned on clean data; this
is a deliberate choice (see
utils.build_transformsdocstring) to avoid conflating training-time data augmentation with architectural robustness.
If you use this code, please cite the accompanying paper (see
CITATION.cff) and the original PlantVillage dataset papers:
- Hughes, D. P., & Salathé, M. (2015). An Open Access Repository of Images on Plant Health to Enable the Development of Mobile Disease Diagnostics. arXiv:1511.08060.
- Mohanty, S. P., Hughes, D. P., & Salathé, M. (2016). Using Deep Learning for Image-Based Plant Disease Detection. Frontiers in Plant Science, 7:1419.
Code in this repository is released under the MIT License (see
LICENSE). The PlantVillage dataset itself is distributed by its
original authors under its own terms — see the
mohanty/PlantVillage
dataset card on Hugging Face for details before redistributing any data.