Informasi Penelitian
Penelitian kolaborasi dua kampus mengenai ekstraksi fitur dan klasifikasi citra daun untuk deteksi penyakit serta identifikasi jenis tanaman.
Universitas Pembangunan Nasional "Veteran" Jawa Timur
Dhian Satria Yudha Kartika, S.Kom, M.Kom
NIDN 0722058601 — Program Studi Bisnis Digital, UPN "Veteran" Jawa Timur
Nur Cahyo Wibowo, S.Kom, M.Kom
NIDN 0717037901 — Program Studi Sistem Informasi, UPN "Veteran" Jawa Timur
Dita Atasa, S.P, M.P
NIDN 0021029501 — Program Studi Agribisnis, UPN "Veteran" Jawa Timur
Priza Pandunata, S.Kom, M.Kom
NIDN 0031018303 — Program Studi Teknologi Informasi, Universitas Jember
Penelitian ini mengembangkan sistem berbasis Machine Learning untuk mendukung deteksi dini masalah pada tanaman melalui citra daun, diusulkan oleh tim peneliti UPN "Veteran" Jawa Timur bersama anggota dari Universitas Jember. Sistem dibangun dari dua model dengan fokus berbeda namun saling melengkapi.
Model 1 berfokus pada deteksi penyakit tanaman menggunakan arsitektur Convolutional Neural Network (CNN) yang dibangun dari awal (from scratch), sementara Model 2 berfokus pada identifikasi jenis tanaman menggunakan pendekatan Transfer Learning dengan arsitektur InceptionV3.
Dashboard
Gambaran umum skala dataset dan performa akhir kedua model.
Model 1 — Deteksi Penyakit
CNN · from scratch- Jumlah kelas38 kelas penyakit tanaman
- Data uji5.850 citra
Model 2 — Jenis Tanaman
InceptionV3 · transfer learning- Jumlah kelas22 kelas jenis tanaman
- Data uji2.579 citra
Plant Village Disease
61.000 citra daun sehat & terinfeksi penyakit, dikurasi dari platform PlantVillage. Terdiri dari 15 jenis tanaman dan 20 jenis penyakit, membentuk 38 kelas klasifikasi untuk Model 1.
PlantVillage + House Plant Species
Gabungan citra sehat dari PlantVillage (tanaman pangan) dan House Plant Species (14.790 citra, 47 kelas tanaman hias via Bing Images). Diseleksi menjadi 22 kelas relevan untuk konteks Indonesia.
Pre-processing
Tahapan umum sebelum data masuk ke pelatihan, diikuti detail spesifik tiap model.
Data Gathering
Pengumpulan dataset dari Kaggle untuk kebutuhan masing-masing model.
Labeling Otomatis
Label kelas diambil otomatis dari nama folder tempat tiap citra disimpan.
Eksplorasi Data
Memeriksa distribusi kelas, sampel citra acak, dan konsistensi resolusi gambar.
Balancing Data
Menyeimbangkan jumlah citra tiap kelas lewat oversampling & undersampling.
Resize & Normalisasi
Menyeragamkan dimensi citra dan menskalakan nilai piksel ke rentang [0, 1].
Oversampling & Undersampling ke Target 1.500 Citra/Kelas
Jumlah gambar tiap kelas pada dataset awal tidak seimbang, berkisar antara 189 hingga 5.507 gambar/kelas. Untuk mencegah bias model terhadap kelas mayoritas, dilakukan proses balancing dengan target seragam:
- Kelas dengan jumlah gambar > 1.500 → undersampling (random sampling ke 1.500 gambar)
- Kelas dengan jumlah gambar < 1.500 → oversampling dengan augmentasi (rotasi, shift, zoom, flip) hingga mencapai 1.500 gambar
Model 1 — Deteksi Penyakit
Resize 256×256px · Normalisasi piksel (÷255)
- Resizing seluruh citra ke 256×256 piksel
- Normalisasi piksel dari rentang [0, 255] ke [0, 1]
- Split dataset dengan rasio 80 : 10 : 10
Model 2 — Jenis Tanaman
Resize 224×224px · Normalisasi piksel (÷255)
- Resizing seluruh citra ke 224×224 piksel (standar arsitektur modern)
- Normalisasi piksel dari rentang [0, 255] ke [0, 1]
- Split dataset 80 : 10 : 10 via sklearn.train_test_split
Model
Dua model dengan tujuan berbeda: satu mendeteksi penyakit, satu lagi mengenali jenis tanaman.
Model 1 — Deteksi Penyakit Tanaman
from tensorflow.keras import layers, Model, Input
from tensorflow.keras.layers import Rescaling
input_layer = Input(shape=(256, 256, 3))
x = Rescaling(1.0 / 255)(input_layer)
x = layers.Conv2D(32, (3, 3), activation='relu')(input_layer)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Conv2D(128, (3, 3), activation='relu')(x)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.Conv2D(256, (3, 3), activation='relu')(x)
x = layers.MaxPooling2D((2, 2))(x)
x = layers.GlobalAveragePooling2D(name='global_avg_pool')(x)
x = layers.Dense(128, activation='relu')(x)
x = layers.Dropout(0.2)(x)
output_layer = layers.Dense(39, activation='softmax')(x)
model = Model(inputs=input_layer, outputs=output_layer)
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
callbacks = [
tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5),
tf.keras.callbacks.ModelCheckpoint('best_model.h5', save_best_only=True)
]
history = model.fit(
train_dataset,
epochs=30,
validation_data=val_dataset,
callbacks=callbacks,
verbose=1
)
Model 2 — Klasifikasi Jenis Tanaman
from tensorflow.keras.applications import InceptionV3
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout
from tensorflow.keras.models import Model
import tensorflow as tf
# Load model InceptionV3 tanpa output layer
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
base_model.trainable = False # Freeze base model
# Dapatkan lapisan hingga mixed7
x = base_model.get_layer('mixed7').output
# Tambahkan custom classifier
x = GlobalAveragePooling2D()(x)
x = Dense(128, activation='relu')(x)
x = Dropout(0.2)(x)
predictions = Dense(num_classes, activation='softmax')(x)
# Buat model akhir
model = Model(inputs=base_model.input, outputs=predictions)
model.summary()
Akurasi & Grafik
Kurva akurasi dan loss selama pelatihan, serta hasil akhir evaluasi pada data uji.
Model 1 — Deteksi Penyakit
Train (biru) vs Validation (oranye)
Model 2 — Jenis Tanaman
Training (biru) vs Validation (merah)
Model 1 — Deteksi Penyakit (39 Kelas)
5.850 citra data uji
| # | Kelas | Accuracy | Precision | Recall | F1-Score |
|---|---|---|---|---|---|
| 0 | Apple___Apple_scab | 0.9995 | 0.9933 | 0.9867 | 0.9900 |
| 1 | Apple___Black_rot | 0.9991 | 0.9739 | 0.9933 | 0.9835 |
| 2 | Apple___Cedar_apple_rust | 0.9993 | 0.9740 | 1.0000 | 0.9868 |
| 3 | Apple___healthy | 0.9991 | 0.9866 | 0.9800 | 0.9833 |
| 4 | Background_without_leaves | 0.9991 | 0.9801 | 0.9867 | 0.9834 |
| 5 | Blueberry___healthy | 0.9995 | 0.9804 | 1.0000 | 0.9901 |
| 6 | Cherry___Powdery_mildew | 0.9990 | 1.0000 | 0.9600 | 0.9796 |
| 7 | Cherry___healthy | 0.9995 | 0.9868 | 0.9933 | 0.9900 |
| 8 | Corn___Cercospora_leaf_spot Gray_leaf_spot | 0.9957 | 0.9496 | 0.8800 | 0.9135 |
| 9 | Corn___Common_rust | 0.9998 | 1.0000 | 0.9933 | 0.9967 |
| 10 | Corn___Northern_Leaf_Blight | 0.9959 | 0.8889 | 0.9600 | 0.9231 |
| 11 | Corn___healthy | 0.9998 | 1.0000 | 0.9933 | 0.9967 |
| 12 | Grape___Black_rot | 0.9995 | 0.9868 | 0.9933 | 0.9900 |
| 13 | Grape___Esca_(Black_Measles) | 0.9998 | 0.9934 | 1.0000 | 0.9967 |
| 14 | Grape___Leaf_blight_(Isariopsis_Leaf_Spot) | 0.9997 | 0.9868 | 1.0000 | 0.9934 |
| 15 | Grape___healthy | 0.9995 | 0.9804 | 1.0000 | 0.9901 |
| 16 | Orange___Haunglongbing_(Citrus_greening) | 0.9997 | 0.9933 | 0.9933 | 0.9933 |
| 17 | Peach___Bacterial_spot | 0.9985 | 1.0000 | 0.9400 | 0.9691 |
| 18 | Peach___healthy | 0.9993 | 0.9740 | 1.0000 | 0.9868 |
| 19 | Pepper,_bell___Bacterial_spot | 0.9981 | 0.9728 | 0.9533 | 0.9630 |
| 20 | Pepper,_bell___healthy | 0.9988 | 1.0000 | 0.9533 | 0.9761 |
| 21 | Potato___Early_blight | 0.9995 | 0.9933 | 0.9867 | 0.9900 |
| 22 | Potato___Late_blight | 0.9985 | 0.9930 | 0.9467 | 0.9693 |
| 23 | Potato___healthy | 0.9991 | 0.9677 | 1.0000 | 0.9836 |
| 24 | Raspberry___healthy | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
| 25 | Soybean___healthy | 0.9993 | 1.0000 | 0.9733 | 0.9865 |
| 26 | Squash___Powdery_mildew | 0.9988 | 0.9673 | 0.9867 | 0.9769 |
| 27 | Strawberry___Leaf_scorch | 0.9995 | 1.0000 | 0.9800 | 0.9899 |
| 28 | Strawberry___healthy | 0.9997 | 1.0000 | 0.9867 | 0.9933 |
| 29 | Tomato___Bacterial_spot | 0.9990 | 0.9932 | 0.9667 | 0.9797 |
| 30 | Tomato___Early_blight | 0.9973 | 0.9467 | 0.9467 | 0.9467 |
| 31 | Tomato___Late_blight | 0.9974 | 0.9470 | 0.9533 | 0.9502 |
| 32 | Tomato___Leaf_Mold | 0.9991 | 0.9866 | 0.9800 | 0.9833 |
| 33 | Tomato___Septoria_leaf_spot | 0.9976 | 0.9359 | 0.9733 | 0.9542 |
| 34 | Tomato___Spider_mites Two-spotted_spider_mite | 0.9968 | 0.9712 | 0.9000 | 0.9343 |
| 35 | Tomato___Target_Spot | 0.9956 | 0.8563 | 0.9933 | 0.9198 |
| 36 | Tomato___Tomato_Yellow_Leaf_Curl_Virus | 0.9993 | 0.9867 | 0.9867 | 0.9867 |
| 37 | Tomato___Tomato_mosaic_virus | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
| 38 | Tomato___healthy | 0.9995 | 0.9933 | 0.9867 | 0.9900 |
Model 2 — Jenis Tanaman (22 Kelas)
2.579 citra data uji
| # | Kelas | Accuracy | Precision | Recall | F1-Score |
|---|---|---|---|---|---|
| 0 | Aloe Vera | 0.9955 | 0.9718 | 0.9283 | 0.9495 |
| 1 | Apple___healthy | 0.9988 | 0.9740 | 1.0000 | 0.9868 |
| 2 | Areca Palm (Dypsis lutescens) | 0.9962 | 0.9598 | 0.9556 | 0.9577 |
| 3 | Birds Nest Fern (Asplenium nidus) | 0.9955 | 0.9856 | 0.9152 | 0.9491 |
| 4 | Blueberry___healthy | 0.9998 | 0.9956 | 1.0000 | 0.9978 |
| 5 | Cherry___healthy | 0.9994 | 0.9912 | 0.9956 | 0.9933 |
| 6 | Chinese Evergreen (Aglaonema) | 0.9864 | 0.8527 | 0.8489 | 0.8508 |
| 7 | Corn___healthy | 1.0000 | 1.0000 | 1.0000 | 1.0000 |
| 8 | Dracaena | 0.9897 | 0.8686 | 0.9111 | 0.8894 |
| 9 | Dumb Cane (Dieffenbachia spp.) | 0.9895 | 0.9326 | 0.8219 | 0.8738 |
| 10 | Elephant Ear (Alocasia spp.) | 0.9929 | 0.9025 | 0.9467 | 0.9241 |
| 11 | Grape___healthy | 0.9998 | 1.0000 | 0.9956 | 0.9978 |
| 12 | Monstera Deliciosa (Monstera deliciosa) | 0.9927 | 0.8884 | 0.9598 | 0.9227 |
| 13 | Peach___healthy | 0.9994 | 1.0000 | 0.9867 | 0.9933 |
| 14 | Pepper,_bell___healthy | 0.9998 | 1.0000 | 0.9956 | 0.9978 |
| 15 | Polka Dot Plant (Hypoestes phyllostachya) | 0.9978 | 0.9693 | 0.9822 | 0.9757 |
| 16 | Ponytail Palm (Beaucarnea recurvata) | 0.9980 | 0.9654 | 0.9911 | 0.9781 |
| 17 | Potato___healthy | 0.9992 | 0.9868 | 0.9956 | 0.9912 |
| 18 | Raspberry___healthy | 0.9980 | 1.0000 | 0.9556 | 0.9773 |
| 19 | Snake Plant (Sanseviera) | 0.9937 | 0.9174 | 0.9462 | 0.9316 |
| 20 | Strawberry___healthy | 0.9984 | 0.9780 | 0.9867 | 0.9823 |
| 21 | Tomato___healthy | 0.9998 | 0.9956 | 1.0000 | 0.9978 |
Kedua model menunjukkan performa yang tinggi dan stabil pada tugasnya masing-masing. Model 1 mencapai akurasi test 97,71% dalam mendeteksi 38 kelas penyakit tanaman, sementara Model 2 mencapai akurasi validasi 96,01% dalam mengklasifikasikan 22 jenis tanaman. Kurva training dan validasi pada kedua model bergerak beriringan tanpa jarak (gap) yang signifikan, menandakan tidak terjadi overfitting berarti pada proses pelatihan.