HoangTN11 commited on
Commit
bd35edc
·
verified ·
1 Parent(s): 85382cf

Upload 12 files

Browse files
.gitignore ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ *.pyc
2
+ __pycache__/
3
+
4
+ model/efficientnetb1_plant_final.weights.h5
5
+ model/efficientnetb1_plant_model.h5
6
+
7
+ assets/Pepper__bell___healthy.jpg
8
+ assets/Potato___Early_blight.jpg
9
+ assets/Potato___healthy.jpg
README.md CHANGED
@@ -1,13 +1,149 @@
1
  ---
2
- title: EfficientNetB1
3
- emoji: 🏢
4
- colorFrom: pink
5
- colorTo: gray
6
  sdk: gradio
7
- sdk_version: 6.3.0
8
  app_file: app.py
9
- pinned: false
10
- license: apache-2.0
 
 
 
 
 
 
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Plant-Disease-Detection-EfficientNetB1
3
+ emoji: 🌿
4
+ colorFrom: green
5
+ colorTo: purple
6
  sdk: gradio
 
7
  app_file: app.py
8
+ pinned: true
9
+ license: mit
10
+ tags:
11
+ - plant-disease
12
+ - image-classification
13
+ - efficientnet
14
+ - tensorflow
15
+ - gradio
16
+ - computer-vision
17
+ - huggingface-spaces
18
  ---
19
 
20
+ [![HF Spaces](https://img.shields.io/badge/🤗%20HuggingFace-Space-blue?logo=huggingface&style=flat-square)](https://huggingface.co/spaces/McKlay/Plant-Disease-Detection-EfficientNetB1)
21
+ [![Gradio](https://img.shields.io/badge/Built%20with-Gradio-orange?logo=gradio&style=flat-square)](https://www.gradio.app/)
22
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
23
+
24
+ ![GitHub last commit](https://img.shields.io/github/last-commit/McKlay/plant-disease-type-EfficientNetB1)
25
+ ![GitHub stars](https://img.shields.io/github/stars/McKlay/plant-disease-type-EfficientNetB1?style=social)
26
+ ![GitHub forks](https://img.shields.io/github/forks/McKlay/plant-disease-type-EfficientNetB1?style=social)
27
+ ![MIT License](https://img.shields.io/github/license/McKlay/plant-disease-type-EfficientNetB1)
28
+ ![Visitors](https://visitor-badge.laobi.icu/badge?page_id=McKlay.plant-disease-type-EfficientNetB1)
29
+
30
+ # 🌿 Plant Disease Detection with EfficientNetB1
31
+
32
+ **Plant-Disease-Detection-EfficientNetB1** is a deep learning-powered app that identifies 15 types of plant diseases from leaf images using a fine-tuned **EfficientNetB1** model trained on the PlantVillage dataset.
33
+
34
+ > 📸 Upload an image, paste from clipboard, or use **webcam input**
35
+ > Get instant predictions on plant disease type — with confidence score and class label.
36
+
37
+ ---
38
+
39
+ ## 🌐 Demo
40
+
41
+ Deployed on Hugging Face Spaces:
42
+ [![Open in Spaces](https://huggingface.co/datasets/huggingface/badges/raw/main/open-in-hf-spaces-sm.svg)](https://huggingface.co/spaces/McKlay/Plant-Disease-Detection-EfficientNetB1)
43
+
44
+ ---
45
+
46
+ ## 🧠 Model Details
47
+
48
+ - **Model:** EfficientNetB1 (Keras, Sequential API)
49
+ - **Classes:** 15 plant disease types
50
+ - **Input Size:** 240×240
51
+ - **Preprocessing:** Normalization (0–1), real-time data augmentation
52
+ - **Training:**
53
+ - Phase 1: Freeze base, train classification head
54
+ - Phase 2: Unfreeze all, fine-tune at low learning rate (`1e-5`)
55
+ - **Validation Accuracy:** ~97%
56
+
57
+ ---
58
+
59
+ ## 📓 Training Notebook (Kaggle)
60
+
61
+ The model was trained using TensorFlow and Keras on Kaggle.
62
+ [🔗 fine-tuning-efficientnetb1-plantdiseasedetection](https://www.kaggle.com/code/claymarksarte/fine-tuning-efficientnetb1-plantdiseasedetection/notebook)
63
+ Includes:
64
+ - Stratified 80/20 data split using `ImageDataGenerator`
65
+ - Real-time augmentations
66
+ - Early stopping and checkpointing (best weights only)
67
+ - Final `.h5` weights file exported
68
+
69
+ ---
70
+
71
+ ## Features
72
+
73
+ - Classifies **15 plant diseases**
74
+ - Supports **upload**, **webcam**, and **clipboard paste**
75
+ - Outputs **predicted class name** and **confidence score**
76
+ - Lightweight & fast inference — powered by Gradio
77
+
78
+ ---
79
+
80
+ ## ⚠️ Grad-CAM Note
81
+
82
+ Grad-CAM is **disabled** in this version due to using `Sequential()` with `load_weights()`
83
+ To enable Grad-CAM, re-train with `Functional API` and access the last convolutional layer output.
84
+
85
+ ---
86
+
87
+ ## 📁 Folder Structure
88
+
89
+ ```bash
90
+ 12_PlantDiseaseDetection-HF/
91
+ ├── app.py # Gradio interface
92
+ ├── inference_utils.py # Model loading + prediction
93
+ ├── model/
94
+ │ ├── efficientnetb1_plant_final.weights.h5
95
+ │ └── class_names.json
96
+ ├── assets/ # Demo/test images
97
+ ├── requirements.txt
98
+ └── README.md
99
+ ````
100
+
101
+ ---
102
+
103
+ ## Example Output
104
+
105
+ | Input Image | Prediction |
106
+ | ------------------------------------------------------------------------------------------------------------ | -------------------------------- |
107
+ | ![sample](https://huggingface.co/datasets/McKlay/documentation-images/resolve/main/plant-disease-detect-EfficientNetB1/Tomato_Early_blight.jpg) | 🍅 Tomato - Early Blight (99%) |
108
+
109
+ ---
110
+
111
+ ## Installation
112
+
113
+ To run locally:
114
+
115
+ ```bash
116
+ git clone https://github.com/McKlay/plant-disease-type-EfficientNetB1
117
+ cd plant-disease-type-EfficientNetB1
118
+ pip install -r requirements.txt
119
+ python app.py
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Requirements
125
+
126
+ ```txt
127
+ tensorflow
128
+ gradio
129
+ opencv-python
130
+ numpy
131
+ Pillow
132
+ ```
133
+
134
+ ---
135
+
136
+ ## 👨‍💻 Author
137
+
138
+ Developed by [Clay Mark Sarte](https://github.com/McKlay)
139
+ Built with TensorFlow + Gradio
140
+ Deployed to Hugging Face Spaces
141
+
142
+ ---
143
+
144
+ ## ⚠️ Disclaimer
145
+
146
+ > **This tool is for educational use only.**
147
+ > Not intended for use in real-world agricultural decisions or medical treatment.
148
+
149
+ ---
app.py CHANGED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from inference_utils import predict_plant_disease
3
+
4
+ title = "🌿 Plant Disease Classifier (EfficientNetB1)"
5
+ description = """
6
+ Upload a plant leaf image, use your webcam, or paste an image from your clipboard.
7
+ The model will predict the **plant + disease** and display the confidence.
8
+ """
9
+
10
+ examples = [
11
+ "assets/Pepper__bell___Bacterial_spot.jpg",
12
+ "assets/Pepper__bell___healthy.jpg",
13
+ "assets/Potato___Early_blight.jpg",
14
+ "assets/Potato___healthy.jpg"
15
+ ]
16
+
17
+ iface = gr.Interface(
18
+ fn=predict_plant_disease,
19
+ inputs=gr.Image(type="filepath", label="Input Leaf Image"),
20
+ outputs=gr.Label(label="Prediction & Confidence"),
21
+ title=title,
22
+ description=description,
23
+ examples=examples,
24
+ flagging_mode="never",
25
+ theme="default",
26
+ live=False,
27
+ cache_examples=False,
28
+ )
29
+
30
+ iface.launch()
assets/Pepper__bell___Bacterial_spot.jpg ADDED
assets/Pepper__bell___healthy.jpg ADDED
assets/Potato___Early_blight.jpg ADDED
assets/Potato___healthy.jpg ADDED
inference_utils.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ import numpy as np
3
+ import cv2
4
+ from PIL import Image
5
+ import json
6
+
7
+ # Constants
8
+ IMG_SIZE = 240
9
+ MODEL_PATH = "model/efficientnetb1_plant_final.weights.h5"
10
+ CLASS_NAMES_PATH = "model/class_names.json"
11
+
12
+ # Load CLASS_NAMES
13
+ with open(CLASS_NAMES_PATH, "r") as f:
14
+ CLASS_NAMES = json.load(f)
15
+
16
+ # Build model EXACTLY like in training
17
+ base_model = tf.keras.applications.EfficientNetB1(
18
+ include_top=False,
19
+ weights="imagenet",
20
+ input_shape=(IMG_SIZE, IMG_SIZE, 3)
21
+ )
22
+ base_model.trainable = True
23
+
24
+ model = tf.keras.Sequential([
25
+ base_model,
26
+ tf.keras.layers.GlobalAveragePooling2D(),
27
+ tf.keras.layers.Dropout(0.2),
28
+ tf.keras.layers.Dense(len(CLASS_NAMES), activation='softmax')
29
+ ])
30
+
31
+ # Load weights
32
+ model.load_weights(MODEL_PATH)
33
+
34
+ # Preprocess image
35
+ def preprocess_image(image_path):
36
+ img = tf.keras.preprocessing.image.load_img(image_path, target_size=(IMG_SIZE, IMG_SIZE))
37
+ img_array = tf.keras.preprocessing.image.img_to_array(img) / 255.0
38
+ return np.expand_dims(img_array, axis=0)
39
+
40
+ # Grad-CAM
41
+ def generate_gradcam(img_path, model, class_index, layer_name="efficientnetb1"):
42
+ img_array = preprocess_image(img_path)
43
+
44
+ grad_model = tf.keras.models.Model(
45
+ [model.inputs],
46
+ [model.get_layer(layer_name).output, model.output]
47
+ )
48
+
49
+ with tf.GradientTape() as tape:
50
+ conv_outputs, predictions = grad_model(img_array)
51
+ loss = predictions[:, class_index]
52
+
53
+ grads = tape.gradient(loss, conv_outputs)[0]
54
+ pooled_grads = tf.reduce_mean(grads, axis=(0, 1))
55
+
56
+ conv_outputs = conv_outputs[0]
57
+ heatmap = tf.reduce_sum(conv_outputs * pooled_grads, axis=-1)
58
+
59
+ heatmap = np.maximum(heatmap, 0)
60
+ heatmap /= tf.math.reduce_max(heatmap) + 1e-6
61
+ heatmap = heatmap.numpy()
62
+
63
+ # Overlay heatmap
64
+ img = cv2.imread(img_path)
65
+ img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
66
+ heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
67
+ heatmap = np.uint8(255 * heatmap)
68
+ heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
69
+ superimposed_img = heatmap * 0.4 + img
70
+ result_img = Image.fromarray(np.uint8(superimposed_img))
71
+
72
+ return result_img
73
+
74
+ # Inference
75
+ def predict_plant_disease(image_path):
76
+ img_array = preprocess_image(image_path)
77
+ preds = model.predict(img_array)[0]
78
+
79
+ class_index = int(np.argmax(preds))
80
+ confidence = float(preds[class_index])
81
+ label = CLASS_NAMES[class_index]
82
+
83
+ return {label: confidence}
84
+
85
+
86
+ ''' gradcam_img = generate_gradcam(image_path, model, class_index)
87
+ we will disable gradcam for now, we need to rebuild the model in kaggle using functional API to for this to work'''
88
+
89
+ ''' def build_model(num_classes=15):
90
+ inputs = tf.keras.Input(shape=(240, 240, 3))
91
+ base_model = tf.keras.applications.EfficientNetB1(include_top=False, weights='imagenet', input_tensor=inputs)
92
+ x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)
93
+ x = tf.keras.layers.Dropout(0.2)(x)
94
+ outputs = tf.keras.layers.Dense(num_classes, activation='softmax')(x)
95
+ return tf.keras.Model(inputs=inputs, outputs=outputs)
96
+
97
+ model = build_model()
98
+ model.load_weights("model/efficientnetb1_plant_final.weights.h5")'''
model/README.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Model Links
2
+
3
+ ## Hugging Face Space
4
+ - 🌐 Live Demo: [Click here to open the Hugging Face Space](https://huggingface.co/spaces/McKlay/Plant-Disease-Detection-EfficientNetB1)
5
+
6
+ ## Other Resources
7
+ - 📄 Kaggle Notebook: [Download the output file](https://www.kaggle.com/code/claymarksarte/fine-tuning-efficientnetb1-plantdiseasedetection/output)
model/class_names.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "Pepper__bell___Bacterial_spot",
3
+ "Pepper__bell___healthy",
4
+ "Potato___Early_blight",
5
+ "Potato___Late_blight",
6
+ "Potato___healthy",
7
+ "Tomato_Bacterial_spot",
8
+ "Tomato_Early_blight",
9
+ "Tomato_Late_blight",
10
+ "Tomato_Leaf_Mold",
11
+ "Tomato_Septoria_leaf_spot",
12
+ "Tomato_Spider_mites_Two_spotted_spider_mite",
13
+ "Tomato__Target_Spot",
14
+ "Tomato__Tomato_YellowLeaf__Curl_Virus",
15
+ "Tomato__Tomato_mosaic_virus",
16
+ "Tomato_healthy"
17
+ ]
model/efficientnetb1_plant_final.weights.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ede5a7ff9786621bf47a5013c3698e940c24118e9d39445399c90d90f3578dd2
3
+ size 79735368
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ tensorflow
2
+ gradio
3
+ opencv-python
4
+ numpy
5
+ Pillow