aniket dhole
Published © GPL3+

Mango Plant Disease Detection

It helps in classifying the diseases of mango leaves for our Mango Farm in India using Tensorflow and OpenVino in Drones

IntermediateFull instructions provided4 hours4,607

Things used in this project

Software apps and online services

OpenVINO™ toolkit
Intel OpenVINO™ toolkit
TensorFlow
TensorFlow
Google Colab

Story

Read more

Code

Mango_Leaf_Disease_Detection.ipynb

Python
https://colab.research.google.com/drive/1THzBJ9F7IYKAlEfQacbOugkm6v83o1QI?usp=sharing

USe this link to access on Colab Directly. Contains all code for Downloading Dataset, Training Model and Inference of Model with OpenVino and Normal mode
{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Mango Leaf Disease Detection.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "x-iMA0iIXMYt",
        "colab_type": "text"
      },
      "source": [
        "# **Install Intel Distribution of OpenVINO Toolkit**\n",
        "Run the below cell to install OpenVino Directly to Colab (Takes 1 min)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3BPyuF_tMR5I",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!wget https://apt.repos.intel.com/openvino/2020/GPG-PUB-KEY-INTEL-OPENVINO-2020\n",
        "!apt-key add GPG-PUB-KEY-INTEL-OPENVINO-2020\n",
        "!touch /etc/apt/sources.list.d/intel-openvino-2020.list\n",
        "!echo \"deb https://apt.repos.intel.com/openvino/2020 all main\" >> /etc/apt/sources.list.d/intel-openvino-2020.list\n",
        "\n",
        "!apt update\n",
        "!apt install intel-openvino-dev-ubuntu18-2020.4.287\n",
        "\n",
        "!pip install test-generator==0.1.1\n",
        "!source /opt/intel/openvino/bin/setupvars.sh"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZG7hK1BI3II5",
        "colab_type": "text"
      },
      "source": [
        "# Download all Necessary files "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "G_sDnj7ciE_w",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!pip install gdown\n",
        "!gdown --id 1j9x9PX8YIrWXlv9GVE68c8jUiM8MexKA\n",
        "!unzip mangodetection.zip"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "C29v7siawvOl",
        "colab_type": "text"
      },
      "source": [
        "## Import Libraries"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9m-9bP62tjpe",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import tensorflow as tf\n",
        "import IPython.display as display\n",
        "import PIL\n",
        "import PIL.Image\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "import os\n",
        "import time\n",
        "import pathlib\n",
        "from tensorflow.keras.models import Sequential\n",
        "from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D\n",
        "import matplotlib.pyplot as plt\n",
        "from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint\n",
        "from tensorflow.keras.models import load_model\n",
        "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
        "from tensorflow.keras import layers\n",
        "from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint"
      ],
      "execution_count": 13,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "lbvyDYxWin8C",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "data_dir = pathlib.Path('mangodetection/train')\n",
        "test_dir = pathlib.Path('mangodetection/test')\n",
        "train_count = len(list(data_dir.glob('*/*.JPG')))\n",
        "test_count = len(list(test_dir.glob('*/*.JPG')))\n",
        "\n",
        "batch_size = 32\n",
        "img_height = 180\n",
        "img_width = 180\n",
        "\n",
        "#Generate More Data by Generator\n",
        "image_gen_train = ImageDataGenerator(rescale = 1./255,validation_split=0.2,rotation_range = 45,width_shift_range=.15,height_shift_range =.15,horizontal_flip=True,zoom_range=0.5)\n",
        "\n",
        "#Shuffle All Data \n",
        "train_data_gen = image_gen_train.flow_from_directory(batch_size=batch_size,subset = 'training',  directory= data_dir,shuffle=True,target_size=(img_height, img_width))  \n",
        "\n",
        "#Divide Data for Validation\n",
        "validation_data_gen = image_gen_train.flow_from_directory(batch_size=batch_size,subset = 'validation',  directory= data_dir,shuffle=True,target_size=(img_height, img_width)) \n",
        "\n",
        "CLASS_NAMES = np.array([item.name for item in data_dir.glob('*') if item.name != \"LICENSE.txt\"])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SLfCWC2IyXpY",
        "colab_type": "text"
      },
      "source": [
        "# Create Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bGMazEOcl5_T",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "num_classes = 2\n",
        "model = Sequential([\n",
        "  Conv2D(16, 3, padding='same', activation='relu',input_shape=(img_height, img_width ,3)),\n",
        "  MaxPooling2D(),\n",
        "  Conv2D(32, 3, padding='same', activation='relu'),\n",
        "  MaxPooling2D(),\n",
        "  Conv2D(64, 3, padding='same', activation='relu'),\n",
        "  MaxPooling2D(),\n",
        "  Dropout(0.2),\n",
        "  Flatten(),\n",
        "  Dense(128, activation='relu'),\n",
        "  Dense(num_classes)\n",
        "])\n",
        "model.compile(optimizer='adam',loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),metrics=['accuracy'])\n",
        "model.summary()"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dFWpk_8WyclO",
        "colab_type": "text"
      },
      "source": [
        "# Train Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qvYBJiznmPsY",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "rlr = ReduceLROnPlateau(patience=10, verbose=1)\n",
        "es = EarlyStopping(patience=24, restore_best_weights=True, verbose=1)\n",
        "mc = ModelCheckpoint('mangodetection/model.h5', save_best_only=True, verbose=1)\n",
        "\n",
        "epochs = 15\n",
        "history = model.fit(\n",
        "  train_data_gen,\n",
        "  callbacks=[rlr, es, mc],  \n",
        "  validation_data=validation_data_gen,\n",
        "  epochs=epochs\n",
        ")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LX8C12M4yz2c",
        "colab_type": "text"
      },
      "source": [
        "# Normal Inference of Trained Model\n",
        "\n",
        "Takes Around 10-15 Seconds for 23 Images"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SFkqePbJs0x1",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "model_mango = load_model('mangodetection/model.h5')\n",
        "\n",
        "image_gen_test = ImageDataGenerator(rescale = 1./255)\n",
        "test_data_gen = image_gen_test.flow_from_directory(batch_size=32,directory= test_dir,shuffle=True,target_size=(img_height, img_width))  \n",
        "\n",
        "start_time = time.time()\n",
        "predictions = model_mango.predict(test_data_gen)\n",
        "for i in range(len(predictions)):\n",
        "    if(predictions[i][0]<0):\n",
        "      print(\"Healthy     \"+str(abs(predictions[i][0]))+\"%\")\n",
        "    else:  \n",
        "      print(\"Diseased    \"+str(100-abs(predictions[i][0]))+\"%\")\n",
        "print(\"Total Time: \", time.time()-start_time)\n",
        "print(\"Average Time Per Image: \", (time.time()-start_time)/len(predictions))\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Rqq4Uh9J1RgZ",
        "colab_type": "text"
      },
      "source": [
        "# Inference with OPENVINO"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "n8WECRIf0tge",
        "colab_type": "text"
      },
      "source": [
        "#### Step 1: Converting .h5 to .pb (frozen model)\n",
        "##### This is required for OPENVINO to generate .xml and .bin from Frozen Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "AEemef7juEcI",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from tensorflow.python.framework import graph_io\n",
        "from tensorflow.keras.models import load_model\n",
        "import tensorflow.compat.v1 as tf\n",
        "#Using Tensorflow 1.0 due to Compatibility issues\n",
        "tf.disable_v2_behavior()\n",
        "\n",
        "# Clear any previous session.\n",
        "tf.keras.backend.clear_session()\n",
        "\n",
        "#Directory for Saving Model\n",
        "save_pb_dir = '/content/mangodetection'\n",
        "model_fname = '/content/mangodetection/model.h5'\n",
        "\n",
        "def freeze_graph(graph, session, output, save_pb_dir='/content/mangodetection', save_pb_name='frozen_model.pb', save_pb_as_text=False):\n",
        "    with graph.as_default():\n",
        "        graphdef_inf = tf.compat.v1.graph_util.remove_training_nodes(graph.as_graph_def())\n",
        "        graphdef_frozen = tf.compat.v1.graph_util.convert_variables_to_constants(session, graphdef_inf, output)\n",
        "        graph_io.write_graph(graphdef_frozen, save_pb_dir, save_pb_name, as_text=save_pb_as_text)\n",
        "        return graphdef_frozen\n",
        "\n",
        "\n",
        "tf.keras.backend.set_learning_phase(0) \n",
        "\n",
        "model = load_model(model_fname)\n",
        "session=tf.keras.backend.get_session()\n",
        "INPUT_NODE = [t.op.name for t in model.inputs]\n",
        "OUTPUT_NODE = [t.op.name for t in model.outputs]\n",
        "print(INPUT_NODE, OUTPUT_NODE)\n",
        "frozen_graph = freeze_graph(session.graph, session, [out.op.name for out in model.outputs], save_pb_dir=save_pb_dir)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Te0zjYfS1AA0",
        "colab_type": "text"
      },
      "source": [
        "#### Step:2 Converting .pb to .xml and .bin\n",
        "This is required for OPENVINO's Inference Engine <br>\n",
        "It is done using OpenVino's Model Optimizer mo_tf.py which converts .pb to .xml and .bin"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LjLsHG3x2foX",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\n",
        "mo_tf_path = '/opt/intel/openvino/deployment_tools/model_optimizer/mo_tf.py'\n",
        "\n",
        "pb_file = '/content/mangodetection/frozen_model.pb'\n",
        "output_dir = '/content/mangodetection'\n",
        "img_height = 180\n",
        "input_shape = [1, img_height, img_height, 3]\n",
        "input_shape_str = str(input_shape).replace(' ', '')\n",
        "\n",
        "#Running Commands to run OPENVINO's Model Optimiser Converter 'mo_tf.py'\n",
        "!source /opt/intel/openvino/bin/setupvars.sh\n",
        "!python {mo_tf_path} --input_model {pb_file} --output_dir {output_dir} --input_shape {input_shape_str} --data_type FP16"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9bQIFXsm2UXA",
        "colab_type": "text"
      },
      "source": [
        "#### Step 3: Running Inference\n",
        "\n",
        "This is done by using OpenVino's Library ,whch creates Plugin for the Environment and Network with CPU\n",
        "\n",
        "**The Code is Stored in inference.py because OPENVINO can't compile it directly on Colab**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vCcyQcrt8Skt",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!source /opt/intel/openvino/bin/setupvars.sh && \\\n",
        "python /content/mangodetection/inference.py"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NmhfSj-3C_-n",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#inference.py\n",
        "'''\n",
        "from PIL import Image\n",
        "import numpy as np\n",
        "import sys\n",
        "import pathlib\n",
        "import glob\n",
        "import time\n",
        "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
        "import random\n",
        "try:\n",
        "    from openvino import inference_engine as ie\n",
        "    from openvino.inference_engine import IENetwork, IEPlugin\n",
        "except Exception as e:\n",
        "    exception_type = type(e).__name__\n",
        "    print(\"The following error happened while importing Python API module:\\n[ {} ] {}\".format(exception_type, e))\n",
        "    sys.exit(1)\n",
        "\n",
        "def pre_process_image(imagePath, img_height=180):\n",
        "    # Model input format\n",
        "    n, c, h, w = [1, 3, img_height, img_height]\n",
        "    image = Image.open(imagePath)\n",
        "    processedImg = image.resize((h, w), resample=Image.BILINEAR)\n",
        "\n",
        "    # Normalize to keep data between 0 - 1\n",
        "    processedImg = (np.array(processedImg) - 0) / 255.0\n",
        "\n",
        "    # Change data layout from HWC to CHW\n",
        "    processedImg = processedImg.transpose((2, 0, 1))\n",
        "    processedImg = processedImg.reshape((n, c, h, w))\n",
        "\n",
        "    return processedImg\n",
        "\n",
        "# Plugin initialization for specified device and load extensions library if specified.\n",
        "plugin_dir = None\n",
        "model_xml = '/content/mangodetection/frozen_model.xml'\n",
        "model_bin = '/content/mangodetection/frozen_model.bin'\n",
        "# Devices: GPU (intel), CPU, MYRIAD\n",
        "plugin = IEPlugin(\"CPU\", plugin_dirs=plugin_dir)\n",
        "# Read IR\n",
        "net = IENetwork(model=model_xml, weights=model_bin)\n",
        "assert len(net.inputs.keys()) == 1\n",
        "assert len(net.outputs) == 1\n",
        "input_blob = next(iter(net.inputs))\n",
        "out_blob = next(iter(net.outputs))\n",
        "# Load network to the plugin\n",
        "exec_net = plugin.load(network=net)\n",
        "del net\n",
        "\n",
        "#Prepare Test Data\n",
        "test_data_gen=[]\n",
        "file_list=glob.glob(\"/content/mangodetection/test/diseased/*.JPG\")\n",
        "for i in file_list:\n",
        "  processedImg = pre_process_image(i)\n",
        "  test_data_gen.append(processedImg)\n",
        "file_list=glob.glob(\"/content/mangodetection/test/healthy/*.JPG\")\n",
        "for i in file_list:\n",
        "  processedImg = pre_process_image(i)\n",
        "  test_data_gen.append(processedImg)\n",
        "\n",
        "# Shuffle Data\n",
        "random.shuffle(test_data_gen)\n",
        "\n",
        "\n",
        "# Run inference\n",
        "start_time = time.time()\n",
        "for i in range(len(test_data_gen)):\n",
        "    predictions = exec_net.infer(inputs={input_blob: test_data_gen[i]})\n",
        "  \n",
        "    if(predictions['dense_1/BiasAdd/Add'][0][0]<0):\n",
        "      print(\"Healthy     \"+str(abs(predictions['dense_1/BiasAdd/Add'][0][0]))+\"%\")\n",
        "    else:  \n",
        "      print(\"Diseased    \"+str(100-abs(predictions['dense_1/BiasAdd/Add'][0][0]))+\"%\")\n",
        "    \n",
        "    #print(predictions['dense_1/BiasAdd/Add'][0])\n",
        "    \n",
        "print(\"Total Time: \", time.time()-start_time)\n",
        "print(\"Average Time Per Image: \", (time.time()-start_time)/len(test_data_gen))\n",
        "'''\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vST2gI0Z55Ft",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}

Credits

aniket dhole

aniket dhole

10 projects • 47 followers
20 Years Old ,Robotics and Embedded enthusiast Twitter: https://twitter.com/AniketDhole10 Linkedin: https://www.linkedin.com/in/aniketdhole/

Comments