├── README.md └── Leaf_Disease_Detection.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # leaf_disease_detection 2 | LINK TO DATASET-https://www.kaggle.com/emmarex/plantdisease 3 | -------------------------------------------------------------------------------- /Leaf_Disease_Detection.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import numpy as np\n", 12 | "import pickle\n", 13 | "import cv2\n", 14 | "from os import listdir\n", 15 | "from sklearn.preprocessing import LabelBinarizer\n", 16 | "from keras.models import Sequential\n", 17 | "from keras.layers.normalization import BatchNormalization\n", 18 | "from keras.layers.convolutional import Conv2D\n", 19 | "from keras.layers.convolutional import MaxPooling2D\n", 20 | "from keras.layers.core import Activation, Flatten, Dropout, Dense\n", 21 | "from keras import backend as K\n", 22 | "from keras.preprocessing.image import ImageDataGenerator\n", 23 | "from keras.optimizers import Adam\n", 24 | "from keras.preprocessing import image\n", 25 | "from keras.preprocessing.image import img_to_array\n", 26 | "from sklearn.preprocessing import MultiLabelBinarizer\n", 27 | "from sklearn.model_selection import train_test_split\n", 28 | "import matplotlib.pyplot as plt" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": { 35 | "collapsed": true 36 | }, 37 | "outputs": [], 38 | "source": [ 39 | "EPOCHS = 25\n", 40 | "INIT_LR = 1e-3\n", 41 | "BS = 32\n", 42 | "default_image_size = tuple((256, 256))\n", 43 | "image_size = 0\n", 44 | "directory_root = '../input/plantvillage/'\n", 45 | "width=256\n", 46 | "height=256\n", 47 | "depth=3" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "collapsed": true 55 | }, 56 | "outputs": [], 57 | "source": [ 58 | "def convert_image_to_array(image_dir):\n", 59 | " try:\n", 60 | " image = cv2.imread(image_dir)\n", 61 | " if image is not None :\n", 62 | " image = cv2.resize(image, default_image_size) \n", 63 | " return img_to_array(image)\n", 64 | " else :\n", 65 | " return np.array([])\n", 66 | " except Exception as e:\n", 67 | " print(f\"Error : {e}\")\n", 68 | " return None" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": { 75 | "collapsed": true 76 | }, 77 | "outputs": [], 78 | "source": [ 79 | "image_list, label_list = [], []\n", 80 | "try:\n", 81 | " print(\"[INFO] Loading images ...\")\n", 82 | " root_dir = listdir(directory_root)\n", 83 | " for directory in root_dir :\n", 84 | " # remove .DS_Store from list\n", 85 | " if directory == \".DS_Store\" :\n", 86 | " root_dir.remove(directory)\n", 87 | "\n", 88 | " for plant_folder in root_dir :\n", 89 | " plant_disease_folder_list = listdir(f\"{directory_root}/{plant_folder}\")\n", 90 | " \n", 91 | " for disease_folder in plant_disease_folder_list :\n", 92 | " # remove .DS_Store from list\n", 93 | " if disease_folder == \".DS_Store\" :\n", 94 | " plant_disease_folder_list.remove(disease_folder)\n", 95 | "\n", 96 | " for plant_disease_folder in plant_disease_folder_list:\n", 97 | " print(f\"[INFO] Processing {plant_disease_folder} ...\")\n", 98 | " plant_disease_image_list = listdir(f\"{directory_root}/{plant_folder}/{plant_disease_folder}/\")\n", 99 | " \n", 100 | " for single_plant_disease_image in plant_disease_image_list :\n", 101 | " if single_plant_disease_image == \".DS_Store\" :\n", 102 | " plant_disease_image_list.remove(single_plant_disease_image)\n", 103 | "\n", 104 | " for image in plant_disease_image_list[:200]:\n", 105 | " image_directory = f\"{directory_root}/{plant_folder}/{plant_disease_folder}/{image}\"\n", 106 | " if image_directory.endswith(\".jpg\") == True or image_directory.endswith(\".JPG\") == True:\n", 107 | " image_list.append(convert_image_to_array(image_directory))\n", 108 | " label_list.append(plant_disease_folder)\n", 109 | " print(\"[INFO] Image loading completed\") \n", 110 | "except Exception as e:\n", 111 | " print(f\"Error : {e}\")" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "outputs": [], 121 | "source": [ 122 | "image_size = len(image_list)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": null, 128 | "metadata": { 129 | "collapsed": true 130 | }, 131 | "outputs": [], 132 | "source": [ 133 | "label_binarizer = LabelBinarizer()\n", 134 | "image_labels = label_binarizer.fit_transform(label_list)\n", 135 | "pickle.dump(label_binarizer,open('label_transform.pkl', 'wb'))\n", 136 | "n_classes = len(label_binarizer.classes_)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": { 143 | "collapsed": true 144 | }, 145 | "outputs": [], 146 | "source": [ 147 | "print(label_binarizer.classes_)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": null, 153 | "metadata": { 154 | "collapsed": true 155 | }, 156 | "outputs": [], 157 | "source": [ 158 | "np_image_list = np.array(image_list, dtype=np.float16) / 225.0" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": null, 164 | "metadata": { 165 | "collapsed": true 166 | }, 167 | "outputs": [], 168 | "source": [ 169 | "print(\"[INFO] Spliting data to train, test\")\n", 170 | "x_train, x_test, y_train, y_test = train_test_split(np_image_list, image_labels, test_size=0.2, random_state = 42) " 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": { 177 | "collapsed": true 178 | }, 179 | "outputs": [], 180 | "source": [ 181 | "aug = ImageDataGenerator(\n", 182 | " rotation_range=25, width_shift_range=0.1,\n", 183 | " height_shift_range=0.1, shear_range=0.2, \n", 184 | " zoom_range=0.2,horizontal_flip=True, \n", 185 | " fill_mode=\"nearest\")" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "metadata": { 192 | "collapsed": true 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "model = Sequential()\n", 197 | "inputShape = (height, width, depth)\n", 198 | "chanDim = -1\n", 199 | "if K.image_data_format() == \"channels_first\":\n", 200 | " inputShape = (depth, height, width)\n", 201 | " chanDim = 1\n", 202 | "model.add(Conv2D(32, (3, 3), padding=\"same\",input_shape=inputShape))\n", 203 | "model.add(Activation(\"relu\"))\n", 204 | "model.add(BatchNormalization(axis=chanDim))\n", 205 | "model.add(MaxPooling2D(pool_size=(3, 3)))\n", 206 | "model.add(Dropout(0.25))\n", 207 | "model.add(Conv2D(64, (3, 3), padding=\"same\"))\n", 208 | "model.add(Activation(\"relu\"))\n", 209 | "model.add(BatchNormalization(axis=chanDim))\n", 210 | "model.add(Conv2D(64, (3, 3), padding=\"same\"))\n", 211 | "model.add(Activation(\"relu\"))\n", 212 | "model.add(BatchNormalization(axis=chanDim))\n", 213 | "model.add(MaxPooling2D(pool_size=(2, 2)))\n", 214 | "model.add(Dropout(0.25))\n", 215 | "model.add(Conv2D(128, (3, 3), padding=\"same\"))\n", 216 | "model.add(Activation(\"relu\"))\n", 217 | "model.add(BatchNormalization(axis=chanDim))\n", 218 | "model.add(Conv2D(128, (3, 3), padding=\"same\"))\n", 219 | "model.add(Activation(\"relu\"))\n", 220 | "model.add(BatchNormalization(axis=chanDim))\n", 221 | "model.add(MaxPooling2D(pool_size=(2, 2)))\n", 222 | "model.add(Dropout(0.25))\n", 223 | "model.add(Flatten())\n", 224 | "model.add(Dense(1024))\n", 225 | "model.add(Activation(\"relu\"))\n", 226 | "model.add(BatchNormalization())\n", 227 | "model.add(Dropout(0.5))\n", 228 | "model.add(Dense(n_classes))\n", 229 | "model.add(Activation(\"softmax\"))" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": null, 235 | "metadata": { 236 | "collapsed": true 237 | }, 238 | "outputs": [], 239 | "source": [ 240 | "model.summary()" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": { 247 | "collapsed": true 248 | }, 249 | "outputs": [], 250 | "source": [ 251 | "opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)\n", 252 | "# distribution\n", 253 | "model.compile(loss=\"binary_crossentropy\", optimizer=opt,metrics=[\"accuracy\"])\n", 254 | "# train the network\n", 255 | "print(\"[INFO] training network...\")" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": { 262 | "collapsed": true 263 | }, 264 | "outputs": [], 265 | "source": [ 266 | "history = model.fit_generator(\n", 267 | " aug.flow(x_train, y_train, batch_size=BS),\n", 268 | " validation_data=(x_test, y_test),\n", 269 | " steps_per_epoch=len(x_train) // BS,\n", 270 | " epochs=EPOCHS, verbose=1\n", 271 | " )" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": null, 277 | "metadata": { 278 | "collapsed": true 279 | }, 280 | "outputs": [], 281 | "source": [ 282 | "acc = history.history['acc']\n", 283 | "val_acc = history.history['val_acc']\n", 284 | "loss = history.history['loss']\n", 285 | "val_loss = history.history['val_loss']\n", 286 | "epochs = range(1, len(acc) + 1)\n", 287 | "#Train and validation accuracy\n", 288 | "plt.plot(epochs, acc, 'b', label='Training accurarcy')\n", 289 | "plt.plot(epochs, val_acc, 'r', label='Validation accurarcy')\n", 290 | "plt.title('Training and Validation accurarcy')\n", 291 | "plt.legend()\n", 292 | "\n", 293 | "plt.figure()\n", 294 | "#Train and validation loss\n", 295 | "plt.plot(epochs, loss, 'b', label='Training loss')\n", 296 | "plt.plot(epochs, val_loss, 'r', label='Validation loss')\n", 297 | "plt.title('Training and Validation loss')\n", 298 | "plt.legend()\n", 299 | "plt.show()" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": null, 305 | "metadata": { 306 | "collapsed": true 307 | }, 308 | "outputs": [], 309 | "source": [ 310 | "print(\"[INFO] Calculating model accuracy\")\n", 311 | "scores = model.evaluate(x_test, y_test)\n", 312 | "print(f\"Test Accuracy: {scores[1]*100}\")" 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": null, 318 | "metadata": { 319 | "collapsed": true 320 | }, 321 | "outputs": [], 322 | "source": [ 323 | "print(\"[INFO] Saving model...\")\n", 324 | "pickle.dump(model,open('cnn_model.pkl', 'wb'))" 325 | ] 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": null, 330 | "metadata": { 331 | "collapsed": true 332 | }, 333 | "outputs": [], 334 | "source": [ 335 | "loaded_model = pickle.load(open('cnn_model.pkl', 'rb'))" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": null, 341 | "metadata": { 342 | "collapsed": true 343 | }, 344 | "outputs": [], 345 | "source": [ 346 | "loaded_model = pickle.load(open('path\\\\cnn_model.pkl', 'rb'))" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": null, 352 | "metadata": { 353 | "collapsed": true 354 | }, 355 | "outputs": [], 356 | "source": [ 357 | "image_dir=\"path\\\\plantdisease_dataset\\\\PlantVillage\\\\Potato___Early_blight\"\n", 358 | "\n", 359 | "im=convert_image_to_array(image_dir)\n", 360 | "np_image_li = np.array(im, dtype=np.float16) / 225.0\n", 361 | "npp_image = np.expand_dims(np_image_li, axis=0)" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": null, 367 | "metadata": { 368 | "collapsed": true 369 | }, 370 | "outputs": [], 371 | "source": [ 372 | "result=model.predict(npp_image)\n", 373 | "\n", 374 | "print(result)" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": null, 380 | "metadata": { 381 | "collapsed": true 382 | }, 383 | "outputs": [], 384 | "source": [ 385 | "itemindex = np.where(result==np.max(result))\n", 386 | "print(\"probability:\"+str(np.max(result))+\"\\n\"+label_binarizer.classes_[itemindex[1][0]])" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": { 393 | "collapsed": true 394 | }, 395 | "outputs": [], 396 | "source": [] 397 | }, 398 | { 399 | "cell_type": "code", 400 | "execution_count": null, 401 | "metadata": { 402 | "collapsed": true 403 | }, 404 | "outputs": [], 405 | "source": [] 406 | }, 407 | { 408 | "cell_type": "code", 409 | "execution_count": null, 410 | "metadata": { 411 | "collapsed": true 412 | }, 413 | "outputs": [], 414 | "source": [] 415 | } 416 | ], 417 | "metadata": { 418 | "kernelspec": { 419 | "display_name": "Python 3", 420 | "language": "python", 421 | "name": "python3" 422 | }, 423 | "language_info": { 424 | "codemirror_mode": { 425 | "name": "ipython", 426 | "version": 3 427 | }, 428 | "file_extension": ".py", 429 | "mimetype": "text/x-python", 430 | "name": "python", 431 | "nbconvert_exporter": "python", 432 | "pygments_lexer": "ipython3", 433 | "version": "3.6.2" 434 | } 435 | }, 436 | "nbformat": 4, 437 | "nbformat_minor": 2 438 | } 439 | --------------------------------------------------------------------------------