Cainvas
Model Files
leaf_disease_model.h5
keras
Model
deepSea Compiled Models
leaf_disease_model.exe
deepSea
Ubuntu

Grape leaves disease detection

Credit: AITS Cainvas Community

Photo by Sasha Kolesnik on Dribbble

In [1]:
# Import the required libraries
import tensorflow as tf
from tensorflow import keras
import tensorflow.keras.backend as K
from tensorflow.keras import layers
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Flatten, Activation
from tensorflow.keras.utils import to_categorical
import matplotlib.pyplot as plt
import os
import cv2
import numpy as np
import pickle
import random
In [2]:
# get and unzip the data
!wget -N "https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/Grapes-Leaf-Disease-data.zip"
!unzip -qo Grapes-Leaf-Disease-data.zip
!rm Grapes-Leaf-Disease-data.zip
--2021-07-05 11:12:09--  https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/Grapes-Leaf-Disease-data.zip
Resolving cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)... 52.219.66.32
Connecting to cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)|52.219.66.32|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 23864365 (23M) [application/x-zip-compressed]
Saving to: ‘Grapes-Leaf-Disease-data.zip’

Grapes-Leaf-Disease 100%[===================>]  22.76M   107MB/s    in 0.2s    

2021-07-05 11:12:09 (107 MB/s) - ‘Grapes-Leaf-Disease-data.zip’ saved [23864365/23864365]

In [3]:
dirtrain = 'train'
In [4]:
dirtest = 'test'
In [5]:
categories= ["Black_rot","Esca_(Black_Measles)","Healthy","Leaf_blight_(Isariopsis_Leaf_Spot)"]
In [6]:
data_dir = 'train'

print("Number of samples")
for f in os.listdir(data_dir + '/'):
    if os.path.isdir(data_dir + '/' + f):
        print(f, " : ", len(os.listdir(data_dir + '/' + f +'/')))
Number of samples
Black_rot  :  456
Healthy  :  105
Leaf_blight_(Isariopsis_Leaf_Spot)  :  468
Esca_(Black_Measles)  :  516
In [7]:
data_dir = 'test'

print("Number of samples")
for f in os.listdir(data_dir + '/'):
    if os.path.isdir(data_dir + '/' + f):
        print(f, " : ", len(os.listdir(data_dir + '/' + f +'/')))
Number of samples
Black_rot  :  144
Healthy  :  143
Leaf_blight_(Isariopsis_Leaf_Spot)  :  110
Esca_(Black_Measles)  :  163
In [8]:
for c in categories:
    path=os.path.join(dirtrain,c)
    for i in os.listdir(path):
        img_array=cv2.imread(os.path.join(path,i))
        print(img_array.shape)
        plt.imshow(img_array)
        plt.show()
        break
    break
(256, 256, 3)
In [9]:
training_data = []
def create_training_data():
    count = []
    for c in categories:
        path = os.path.join(dirtrain,c)
        class_num = categories.index(c)
        c = 0
        for i in os.listdir(path):
            c = c+1
            try:
                img_array = cv2.imread(os.path.join(path,i))
                training_data.append([img_array,class_num])
            except Exception as e:
                pass
        count.append(c)
    return count
count_train=create_training_data()
In [10]:
testing_data = []
def create_testing_data():
    count=[]
    for c in categories:
        path = os.path.join(dirtest,c)
        class_num = categories.index(c)
        c = 0
        for i in os.listdir(path):
            c = c+1
            try:
                img_array = cv2.imread(os.path.join(path,i))
                testing_data.append([img_array,class_num])
            except Exception as e:
                pass
        count.append(c)
    return count
count_test=create_testing_data()
In [11]:
print(len(training_data))
print(count_train)
print(len(testing_data))
print(count_test)
1545
[456, 516, 105, 468]
560
[144, 163, 143, 110]
In [12]:
random.shuffle(training_data)
random.shuffle(testing_data)
In [13]:
x_train = []
y_train = []
x_test = []
y_test = []
In [14]:
for features, label in training_data:
    x_train.append(features)
    y_train.append(label)
x_train=np.array(x_train).reshape(-1,256,256,3)
In [15]:
x=cv2.resize(training_data[0][0],(256,256))
plt.imshow(x,cmap='gray')
Out[15]:
<matplotlib.image.AxesImage at 0x7fe210dcfba8>
In [16]:
for features, label in testing_data:
    x_test.append(features)
    y_test.append(label)
x_test = np.array(x_test).reshape(-1,256,256,3)
In [17]:
def save_training_data(x_train,y_train):
    pickle_out=open("x_train.pickle","wb")
    pickle.dump(x_train,pickle_out)
    pickle_out.close()

    pickle_out=open("y_train.pickle","wb")
    pickle.dump(y_train,pickle_out)
    pickle_out.close
save_training_data(x_train,y_train)
In [18]:
def save_testing_data(x_test,y_test):
    pickle_out=open("x_test.pickle","wb")
    pickle.dump(x_test,pickle_out)
    pickle_out.close()

    pickle_out=open("y_test.pickle","wb")
    pickle.dump(y_test,pickle_out)
    pickle_out.close()
save_testing_data(x_test,y_test)
In [19]:
def load_data():
    pickle_in = open("x_train.pickle","rb")
    x_train = pickle.load(pickle_in)
    return x_train
In [20]:
x_train.shape
Out[20]:
(1545, 256, 256, 3)

Build and train the model

In [21]:
K.clear_session()
model = Sequential()
model.add(layers.Conv2D(32,(3,3),padding='same',input_shape=(256,256,3),activation='relu'))
model.add(layers.Conv2D(32,(3,3),activation='relu'))


model.add(layers.MaxPool2D(pool_size=(8,8)))

model.add(layers.Conv2D(32,(3,3),padding='same',activation='relu'))
model.add(layers.Conv2D(32,(3,3),activation='relu'))

model.add(layers.MaxPool2D(pool_size=(8,8)))

model.add(Activation('relu'))

model.add(Flatten())
model.add(layers.Dense(256,activation='relu'))
model.add(layers.Dense(4,activation='softmax'))

model.compile(loss = 'categorical_crossentropy',optimizer = 'rmsprop',metrics = ['accuracy'])
In [22]:
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 256, 256, 32)      896       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 254, 254, 32)      9248      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 31, 31, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 31, 31, 32)        9248      
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 29, 29, 32)        9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 3, 3, 32)          0         
_________________________________________________________________
activation (Activation)      (None, 3, 3, 32)          0         
_________________________________________________________________
flatten (Flatten)            (None, 288)               0         
_________________________________________________________________
dense (Dense)                (None, 256)               73984     
_________________________________________________________________
dense_1 (Dense)              (None, 4)                 1028      
=================================================================
Total params: 103,652
Trainable params: 103,652
Non-trainable params: 0
_________________________________________________________________
In [23]:
y_train_cat = to_categorical(y_train,4)
y_test_cat = to_categorical(y_test,4)
In [24]:
history = model.fit(x_train, y_train_cat, batch_size=32, epochs=10, verbose=1, validation_split=0.15, shuffle=True)
Epoch 1/10
 2/42 [>.............................] - ETA: 1s - loss: 30.2067 - accuracy: 0.1562WARNING:tensorflow:Callbacks method `on_train_batch_end` is slow compared to the batch time (batch time: 0.0174s vs `on_train_batch_end` time: 0.0418s). Check your callbacks.
42/42 [==============================] - 3s 68ms/step - loss: 3.2244 - accuracy: 0.4395 - val_loss: 3.6399 - val_accuracy: 0.1034
Epoch 2/10
42/42 [==============================] - 3s 61ms/step - loss: 0.8882 - accuracy: 0.6329 - val_loss: 3.9846 - val_accuracy: 0.3578
Epoch 3/10
42/42 [==============================] - 3s 61ms/step - loss: 0.6479 - accuracy: 0.7540 - val_loss: 1.0088 - val_accuracy: 0.6767
Epoch 4/10
42/42 [==============================] - 3s 62ms/step - loss: 0.4133 - accuracy: 0.8423 - val_loss: 2.3779 - val_accuracy: 0.5862
Epoch 5/10
42/42 [==============================] - 3s 62ms/step - loss: 0.3258 - accuracy: 0.8941 - val_loss: 1.9668 - val_accuracy: 0.5388
Epoch 6/10
42/42 [==============================] - 3s 62ms/step - loss: 0.3143 - accuracy: 0.8911 - val_loss: 1.5985 - val_accuracy: 0.5000
Epoch 7/10
42/42 [==============================] - 3s 62ms/step - loss: 0.1503 - accuracy: 0.9482 - val_loss: 0.8248 - val_accuracy: 0.8147
Epoch 8/10
42/42 [==============================] - 3s 62ms/step - loss: 0.2162 - accuracy: 0.9261 - val_loss: 0.2895 - val_accuracy: 0.9009
Epoch 9/10
42/42 [==============================] - 3s 62ms/step - loss: 0.1646 - accuracy: 0.9474 - val_loss: 0.6995 - val_accuracy: 0.8147
Epoch 10/10
42/42 [==============================] - 3s 62ms/step - loss: 0.0967 - accuracy: 0.9726 - val_loss: 0.1858 - val_accuracy: 0.9397
In [31]:
# save the model
model.save("leaf_disease_model.h5")
new_model = tf.keras.models.load_model("leaf_disease_model.h5")
In [32]:
#loss and accuracy of the model
loss, acc = new_model.evaluate(x_test,y_test_cat, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100*acc))
18/18 - 0s - loss: 0.1373 - accuracy: 0.9518
Restored model, accuracy: 95.18%
In [33]:
# train_loss vs Val_loss
from matplotlib import pyplot as plt
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
In [34]:
# train_accuracy vs val_accuracy
from matplotlib import pyplot as plt
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('acc')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()

Predictions

In [35]:
img = cv2.resize(x_test[0],(256,256))
plt.imshow(img)
Out[35]:
<matplotlib.image.AxesImage at 0x7fe1845e5518>
In [36]:
img = img.reshape(-1,256,256,3)
In [37]:
predict_class = new_model.predict_classes(img)
predict_class
WARNING:tensorflow:From <ipython-input-37-32b631f435b0>:1: Sequential.predict_classes (from tensorflow.python.keras.engine.sequential) is deprecated and will be removed after 2021-01-01.
Instructions for updating:
Please use instead:* `np.argmax(model.predict(x), axis=-1)`,   if your model does multi-class classification   (e.g. if it uses a `softmax` last-layer activation).* `(model.predict(x) > 0.5).astype("int32")`,   if your model does binary classification   (e.g. if it uses a `sigmoid` last-layer activation).
Out[37]:
array([0])
In [38]:
categories[predict_class[0]]
Out[38]:
'Black_rot'
In [39]:
img0 = cv2.resize(x_test[199],(256,256))
plt.imshow(img0)
Out[39]:
<matplotlib.image.AxesImage at 0x7fe184503b70>
In [40]:
img0 = img0.reshape(-1,256,256,3)
In [41]:
predict_class = new_model.predict_classes(img0)
predict_class
Out[41]:
array([1])
In [42]:
categories[predict_class[0]]
Out[42]:
'Esca_(Black_Measles)'

deepCC

In [43]:
!deepCC leaf_disease_model.h5
[INFO]
Reading [keras model] 'leaf_disease_model.h5'
[SUCCESS]
Saved 'leaf_disease_model_deepC/leaf_disease_model.onnx'
[INFO]
Reading [onnx model] 'leaf_disease_model_deepC/leaf_disease_model.onnx'
[INFO]
Model info:
  ir_vesion : 5
  doc       : 
[WARNING]
[ONNX]: graph-node conv2d's attribute auto_pad has no meaningful data.
[WARNING]
[ONNX]: graph-node conv2d_2's attribute auto_pad has no meaningful data.
[WARNING]
[ONNX]: terminal (input/output) conv2d_input's shape is less than 1. Changing it to 1.
[WARNING]
[ONNX]: terminal (input/output) dense_1's shape is less than 1. Changing it to 1.
WARN (GRAPH): found operator node with the same name (dense_1) as io node.
[INFO]
Running DNNC graph sanity check ...
[SUCCESS]
Passed sanity check.
[INFO]
Writing C++ file 'leaf_disease_model_deepC/leaf_disease_model.cpp'
[INFO]
deepSea model files are ready in 'leaf_disease_model_deepC/' 
[RUNNING COMMAND]
g++ -std=c++11 -O3 -fno-rtti -fno-exceptions -I. -I/opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/include -isystem /opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/packages/eigen-eigen-323c052e1731 "leaf_disease_model_deepC/leaf_disease_model.cpp" -D_AITS_MAIN -o "leaf_disease_model_deepC/leaf_disease_model.exe"
[RUNNING COMMAND]
size "leaf_disease_model_deepC/leaf_disease_model.exe"
   text	   data	    bss	    dec	    hex	filename
 584957	   3792	    760	 589509	  8fec5	leaf_disease_model_deepC/leaf_disease_model.exe
[SUCCESS]
Saved model as executable "leaf_disease_model_deepC/leaf_disease_model.exe"
In [ ]: