| # CropGuard GH — System Documentation |
|
|
| **Image-Based Crop Disease Detection System for Smallholder Farmers in Ghana** |
| Final Year Project · Oppong David · BTech Computer Technology, Kumasi Technical University |
|
|
| --- |
|
|
| ## 1. What this is |
|
|
| CropGuard is the working implementation of the system designed in the project report. A farmer photographs a diseased crop leaf and instantly receives: |
|
|
| - the **disease name** (55 classes across 14 crops cultivated in Ghana), |
| - a **confidence score**, |
| - a **severity level** (Early / Moderate / Severe) with colour coding, |
| - an **urgency level** (Routine / Urgent / Emergency), and |
| - a numbered list of **treatment steps** plus suggested products. |
|
|
| It ships in **two forms**, both included here: |
|
|
| | Deliverable | File | Use it for | |
| |---|---|---| |
| | **Ready-to-use HTML app** | `cropguard.html` | Open in any browser/phone. Works immediately (on-device estimate). No install. Covers all 14 Ghanaian crops when connected to the model. Bilingual (English + Twi toggle). | |
| | **Full production system** | `cropguard-system/` | The real stack from Chapter 3: trained MobileNetV2 model + FastAPI backend + React frontend. | |
|
|
| The HTML app can **also** connect to the trained backend — open Settings and paste the API URL, or set `localStorage.cropguard_api`. When no server is set it falls back to a genuine on-device colour/lesion analyser so it is never broken. |
|
|
| --- |
|
|
| ## 2. Architecture |
|
|
| The system follows the three-component client–server model described in §3.3: |
|
|
| ``` |
| ┌─────────────────────────┐ HTTPS / multipart ┌──────────────────────────┐ |
| │ Frontend (client) │ ── POST /predict (image) ──▶ │ Backend (server) │ |
| │ React app OR │ │ FastAPI │ |
| │ single-file HTML │ ◀── JSON diagnosis ────── │ ├─ MobileNetV2 model │ |
| │ (camera + gallery) │ │ ├─ severity estimator │ |
| └─────────────────────────┘ │ └─ recommendations.json │ |
| └──────────────────────────┘ |
| ``` |
|
|
| - **Inference runs on the server**, so the model can be updated without users reinstalling anything and old phones still work (§3.3). |
| - **Communication is a stateless REST API** returning JSON (§3.3). |
| - **Uploaded images are never stored** — they are processed in memory and discarded (§3.10.2 / §3.13 privacy-by-design). |
|
|
| --- |
|
|
| ## 3. The model (`backend/train.py`) |
|
|
| A transfer-learning classifier (MobileNetV2 **or** EfficientNetB0, via `--arch`), built as specified in §3.6: |
|
|
| **Accuracy target ~98%.** MobileNetV2 reaches roughly 97–98% on this benchmark; for the full multi-crop set use `--arch efficientnet` (EfficientNetB0), which typically reaches **98–99%**, in line with the published literature (Mohanty et al. 2016 = 99.35%, Ferentinos 2018 = 99.53%). The figure is reported honestly from the held-out test set at the end of training — it is never assumed. Label smoothing, class weighting and field-condition augmentation are included to push real-world accuracy toward the target. |
|
|
| - **Input:** 224×224 RGB, normalised with ImageNet mean/std. |
| - **Backbone:** MobileNetV2 or EfficientNetB0 pre-trained on ImageNet. |
| - **Head:** Global Average Pooling → BatchNorm → Dense(512, ReLU, L2=1e-4) → Dropout(0.4) → Dense(softmax). |
| - **Two-phase fine-tuning (§3.6.3):** Phase 1 trains the head with the backbone frozen (Adam, lr=1e-3, ~20 epochs); Phase 2 unfreezes the top 30% of the backbone (Adam, lr=1e-4, ~30 epochs) with `EarlyStopping` and `ReduceLROnPlateau`. |
| - **Loss:** categorical cross-entropy with label smoothing (0.05). |
| - **Class imbalance (§3.7.1):** balanced class weights computed with scikit-learn. |
| - **Augmentation (§3.5.2):** flip, rotation, zoom, brightness and contrast jitter. |
|
|
| ### Dataset layout expected |
|
|
| ``` |
| data/ |
| train/<class_name>/*.jpg |
| val/<class_name>/*.jpg |
| test/<class_name>/*.jpg |
| ``` |
|
|
| Class folder names must match the keys in `recommendations.json`: |
|
|
| ``` |
| maize_healthy maize_gls maize_nclb maize_rust maize_msv maize_faw |
| cassava_healthy cassava_cmd cassava_cbsd cassava_cbb |
| tomato_healthy tomato_early tomato_late tomato_wilt tomato_septoria tomato_tylcv |
| cocoa_healthy cocoa_blackpod cocoa_cssvd cocoa_capsid |
| cashew_healthy cashew_anthracnose cashew_gumosis cashew_leafminer |
| plantain_healthy plantain_sigatoka plantain_bbtv plantain_panama |
| yam_healthy yam_anthracnose yam_mosaic |
| pepper_healthy pepper_bacterialspot pepper_anthracnose |
| cowpea_healthy cowpea_blight cowpea_mosaic cowpea_cercospora |
| groundnut_healthy groundnut_leafspot groundnut_rosette groundnut_rust |
| rice_healthy rice_blast rice_blb rice_brownspot |
| okra_healthy okra_yvmv okra_leafspot |
| gardenegg_healthy gardenegg_wilt gardenegg_leafspot |
| mango_healthy mango_anthracnose mango_bacterialspot |
| ``` |
|
|
| **Covering all crops:** the system is not limited to a fixed list. To add any |
| further crop, drop a labelled folder of its images into `train/`, `val/` and |
| `test/`, add a matching record to `recommendations.json`, and retrain — no code |
| change is required. |
|
|
| Recommended sources (§3.4), Ghana-relevant: the **CCMT dataset** (Cashew, Cassava, Maize, Tomato — field images collected in Ghana), **cassava** disease datasets, **cocoa** (CRIG/COCOBOD imagery), the **rice / cowpea / groundnut** sets from African research programmes, and **PlantVillage/PlantDoc** for tomato, pepper and mango. Locally collected field photographs are added where possible. |
|
|
| ### Train |
|
|
| ```bash |
| cd backend |
| pip install -r requirements.txt |
| python train.py --data ./data --arch efficientnet --epochs-head 20 --epochs-fine 30 |
| # -> model/crop_model.keras and model/classes.json |
| ``` |
|
|
| --- |
|
|
| ## 4. The backend API (`backend/app.py`) |
|
|
| ```bash |
| cd backend |
| uvicorn app:app --host 0.0.0.0 --port 8000 |
| ``` |
|
|
| Interactive docs are auto-generated at `http://localhost:8000/docs`. |
|
|
| | Method | Endpoint | Returns | |
| |---|---|---| |
| | GET | `/health` | `{"status":"ok","model_loaded":bool}` | |
| | GET | `/diseases` | the full treatment knowledge base | |
| | POST | `/predict` | diagnosis JSON (below) | |
|
|
| **`POST /predict`** — send `multipart/form-data` with field `file` = the image. |
|
|
| ```json |
| { |
| "class_id": "tomato_late", |
| "confidence": 0.94, |
| "severity": "moderate", |
| "diseased_ratio": 0.42, |
| "disease": { |
| "crop": "Tomato", |
| "name": "Late Blight", |
| "cause": "An aggressive water-mould (Phytophthora infestans)...", |
| "treatment": ["Act today...", "..."], |
| "products": ["Chlorothalonil", "Mancozeb", "Metalaxyl-M"] |
| } |
| } |
| ``` |
|
|
| **Severity (§3.8)** is computed by `estimate_severity()` using colour thresholding: it measures the ratio of chlorotic (yellow), necrotic (dark) and lesion (brown) pixels to total leaf pixels, then maps `<0.20 → early`, `<0.55 → moderate`, else `severe`. |
|
|
| --- |
|
|
| ## 5. The React frontend (`frontend/src/CropGuard.jsx`) |
|
|
| The four-step flow from §3.10.4 — **home → preview → loading → result** — with camera capture, gallery upload, confidence bar, colour-coded severity, treatment steps and the safety disclaimer. |
|
|
| ```bash |
| cd frontend |
| npm create vite@latest . -- --template react # if starting fresh |
| npm install |
| echo "VITE_API_URL=http://localhost:8000" > .env |
| # drop CropGuard.jsx into src/ and render <CropGuard/> from App.jsx |
| npm run dev |
| ``` |
|
|
| --- |
|
|
| ## 6. The standalone HTML app (`cropguard.html`) |
|
|
| A single self-contained file — open it directly on a phone or host it anywhere static (Netlify, GitHub Pages, a CDN). It implements the full farmer UI in English **and Twi**, with: |
|
|
| - camera capture + gallery upload, |
| - a **real on-device analyser** (canvas pixel analysis of green vs. chlorotic/necrotic/lesion area) so it works with zero backend, |
| - **optional backend mode** — if `localStorage.cropguard_api` is set to your FastAPI URL it sends images to the trained model instead, |
| - severity colour coding, urgency icons, treatment steps, product suggestions, disease explanation, feedback and share. |
|
|
| To point it at the real model, run in the browser console: |
| ```js |
| localStorage.setItem('cropguard_api', 'https://your-api-host:8000'); |
| ``` |
|
|
| > **Note on the on-device fallback:** the heuristic analyser is honest and deterministic (it inspects actual leaf colour and damage area), but it is **not** the trained CNN. For graded, research-quality accuracy, connect the HTML app to the FastAPI backend running your trained model. |
|
|
| --- |
|
|
| ## 7. Deployment notes (§3.11) |
|
|
| - **Backend:** MobileNetV2 is light (~300M multiply-adds/inference) so a CPU-only instance serves several concurrent users; CORS and HTTPS should be enabled in production. |
| - **Frontend:** ship the React build or `cropguard.html` as static files behind a CDN for fast loads across Ghana. |
| - **Privacy:** no login, no accounts, no image storage. |
|
|
| --- |
|
|
| ## 8. Mapping to the report |
|
|
| | Report section | Where it lives in the code | |
| |---|---| |
| | §3.3 System architecture | client–server split (frontends ↔ `app.py`) | |
| | §3.4 Dataset | `train.py` `image_dataset_from_directory` layout | |
| | §3.5 Preprocessing & augmentation | `standardise()`, `build_augmenter()` | |
| | §3.6 MobileNetV2 + custom head + 2-phase fine-tune | `build_model()`, `main()` | |
| | §3.7 Loss, class weights, LR schedule | `class_weights_from_dir()`, callbacks | |
| | §3.8 Severity classification | `estimate_severity()` (backend) / `analyseOnDevice()` (HTML) | |
| | §3.9 Treatment recommendations | `recommendations.json` | |
| | §3.10 Web app & mobile-first UI | `cropguard.html`, `CropGuard.jsx` | |
| | §3.13 Privacy / ethics | in-memory image handling, no storage | |
|
|