{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# # Input data files are available in the read-only \"../input/\" directory\n# # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"#import required libraries\nimport os\nimport io\n\nimport pandas as pd\nimport numpy as np\nimport random\n\nimport matplotlib.pyplot as plt\nimport pydicom\nimport cv2\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport seaborn as sns\n\nimport skimage.io as io\nfrom sklearn.utils import shuffle\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.model_selection import train_test_split\nfrom skimage.transform import resize\nfrom skimage import measure\n\nimport tensorflow as tf\nfrom tensorflow.keras.losses import binary_crossentropy\nfrom tensorflow.keras.backend import log, epsilon\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import MaxPooling2D\nfrom tensorflow.keras.layers import Flatten\nfrom tensorflow.keras.layers import Dense, Dropout, InputLayer, BatchNormalization, Input\nfrom tensorflow.keras.layers import Concatenate, UpSampling2D, Conv2D, Reshape\nfrom tensorflow.keras.optimizers import Adam\n\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score  \n\n\ndef printConfusionMatrix(title, y_true, y_pred):\n    print (title)\n    print ('-------------------')\n    print ('Validation Accuracy: ', accuracy_score(y_true,y_pred))\n    print ('Validation Precision: ', precision_score(y_true,y_pred))\n    print ('Validation Recall: ', recall_score(y_true,y_pred))\n    print ('Validation F1-Score: ', f1_score(y_true,y_pred))\n    \n    cm=confusion_matrix(y_true, y_pred, labels=[1, 0])\n    df_cm = pd.DataFrame(cm, index = [i for i in [\"1\",\"0\"]],\n                      columns = [i for i in [\"Predict Yes\",\"Predict No\"]])\n    #Plot the heat map for the confusion matrix\n    plt.figure(figsize = (5,5))   \n    sns.heatmap(df_cm, annot=True, fmt=\"g\", yticklabels=[\"Actual Yes\", \"Actual No\"], cmap=\"YlGnBu_r\")\n    ax = plt.gca()\n    ax.set_title(title)    \n    plt.show()\n    return accuracy_score(y_true,y_pred), precision_score(y_true,y_pred),recall_score(y_true,y_pred),f1_score(y_true,y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def saveOrLoadWeights(model,fileName):\n    h5Path = os.path.join(root_dir, 'input', 'h5files',fileName)\n    if not loadweightsDirectlyToModel:\n        model.save_weights(fileName)\n    else:\n        model.load_weights(h5Path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plotGraphs(model):\n    if not loadweightsDirectlyToModel:\n        plt.figure(figsize=(12,4))\n        plt.subplot(131)\n        #history = model.history\n\n        plt.plot(history.epoch, history.history[\"loss\"], label=\"Train loss\")\n        plt.plot(history.epoch, history.history[\"val_loss\"], label=\"Valid loss\")\n        plt.xlabel('Epochs')\n        plt.ylabel('Loss')\n        plt.legend()\n\n        plt.subplot(132)\n        plt.plot(history.epoch, history.history[\"mean_iou\"], label=\"Mean IOU\")\n        plt.plot(history.epoch, history.history[\"val_mean_iou\"], label=\"Mean IOU\")\n        plt.legend()\n\n        plt.subplot(133)\n        plt.plot(history.epoch, history.history[\"accuracy\"], label=\"Accuracy\")\n        plt.plot(history.epoch, history.history[\"val_accuracy\"], label=\"Valid Accuracy\")\n        plt.legend()\n\n        plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def displayImagesWithBoundingBox(model):\n    for imgs, msks in val_gen:\n        # predict batch of images\n        preds = model.predict(imgs)\n        # create figure\n        f, axarr = plt.subplots(4, 8, figsize=(20,15))\n        axarr = axarr.ravel()\n        axidx = 0\n        # loop through batch\n        for img,msk, predm in zip(imgs,msks, preds):\n            # plot image\n            axarr[axidx].imshow(img[:, :, 0])\n            detectandMask(msk,False, axarr[axidx])\n            detectandMask(predm,True, axarr[axidx])\n            axidx += 1\n        plt.show()\n\n        # only plot one batch\n        break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def displayMetrics(modelName, model):\n    y_predval = []\n    y_trueval = []\n\n\n    for imgs, msks in val_gen:\n        # predict batch of images\n        preds = model.predict(imgs)\n\n        # loop through batch\n        for img, msk, pred in zip(imgs, msks, preds):\n            #  detect Pneumonia in mask actual & predicted\n            y_trueval.append(detectandMask(msk, False))\n            y_predval.append(detectandMask(pred))\n\n\n    return printConfusionMatrix(modelName, y_trueval, y_predval)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Initialize the variables\nprint(f'Current working directory: {os.getcwd()}')\nprint('Folder and Files in current directory: {}'.format(os.listdir()))\n\ndoProcessingFromDCMImages = False\nloadweightsDirectlyToModel = False\nroot_dir = '/kaggle/'\nif doProcessingFromDCMImages:\n    input_dir = os.path.join(root_dir, 'input/rsna-pneumonia-detection-challenge/')\n\n    #input_dir = 'input'\n    output_dir = os.path.join(root_dir, 'output', )\n    if not os.path.exists(output_dir):\n        os.makedirs(output_dir)\nelse:\n    input_dir = os.path.join(root_dir, 'input/rsna-pneumonia-detection-challenge/')\n    \n    processed_input_dir = os.path.join(root_dir, 'input', 'processed-rsna-image-files','output')\n    \n\ninput_train = 'stage_2_train_images'\ninput_test = 'stage_2_test_images'\nclass_file = 'stage_2_detailed_class_info.csv'\nlabel_file = 'stage_2_train_labels.csv'\noutput_train = 'train'\noutput_test = 'test'\noutput_val = 'val'\n\n\n\nIMAGE_HEIGHT = 224\nIMAGE_WIDTH = 224","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#     #read the classes to create folders as per the category. \n\n#     #Reading the class file to get the list of patients and shuffle them to create training and validation set\ndf_class = pd.read_csv(os.path.join( root_dir, input_dir, class_file))\n\ndf_class[\"class\"] = df_class[\"class\"].astype('category')\nprint(\"Mapped values for SMOKER column ====> %s\" %( dict(enumerate(df_class[\"class\"].cat.categories))))\ndf_class[\"class\"] = df_class[\"class\"].cat.codes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_class.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#shuffle the data and split the data as train and valid\n\ndf_class = shuffle(df_class)\n# stratify=y creates a balanced validation set.\ny = df_class['class']\n\ndf_train, df_val = train_test_split(df_class, test_size=0.10, random_state=101, stratify=y)\n\nprint('Train set size: ', df_train.shape)\nprint('Validation set size: ', df_val.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# read dicom files and resize them to 256 x 256 and save them as .png file in train, validation and test folder.\n\ndef preprocessimages(root_dir,input_images , outputpath, filenames , image_width= 256 ,image_height= 256):\n    \"\"\"\n    Args:\n    :param root_dir (string): Root Directory with all the images\n    :param input_images : Input image directory\n    :param outputpath: Output root directory\n    :param image_width (optional): Output Image width size, Default is 256\n    :param image_height (optional): Output Image width size, Default is 256\n    \"\"\"\n    dest_path = os.path.join(root_dir, output_dir)\n    if not os.path.exists(dest_path):\n        os.mkdir(dest_path)\n    dest_path = os.path.join(dest_path, outputpath)\n    if not os.path.exists(dest_path):\n        os.mkdir(dest_path)\n    \n    # Loop through all the DICOM files under the folder and collect the information from DICOM file\n    for file in filenames:\n        path = os.path.join(root_dir, input_dir, input_images, file)\n        dicom_data = pydicom.read_file(path)\n        \n        # Transform the image to smaller size and store it under data\\images\\train\\\n        dicom_img = dicom_data.pixel_array\n\n        img = cv2.resize(dicom_img, dsize=(image_height, image_width), interpolation=cv2.INTER_CUBIC)\n        cv2.imwrite(os.path.join(dest_path, dicom_data.PatientID + '.png'),img)\n        \ntrainfiles= list(map(lambda x: x + '.dcm' , df_train['patientId']))\nvalfiles= list(map(lambda x: x + '.dcm' , df_val['patientId']))\n\nif doProcessingFromDCMImages:\n    \n    #Convert the training images\n    preprocessimages(root_dir,input_train, output_train ,trainfiles ,image_height=IMAGE_HEIGHT, image_width=256)\n    #Convert the validation images\n    preprocessimages(root_dir,input_train, output_val,valfiles ,image_height=IMAGE_HEIGHT, image_width=256)\n    #Convert the test images\n    preprocessimages(root_dir,input_test, output_test,os.listdir(os.path.join(root_dir, input_dir,input_test)), image_height=IMAGE_HEIGHT, image_width=256)\nelse:\n    print(f'using preprocessed png images from dcm images')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if doProcessingFromDCMImages:\n    #initialize folders train, val , test, \n    output_dir = os.path.join(root_dir, output_dir)\n\n    train_dir = os.path.join(output_dir,output_train)\n\n    val_dir = os.path.join(output_dir,output_val)\n\n    test_dir = os.path.join(output_dir, output_test)\nelse:\n    output_dir = processed_input_dir\n    output_dir = os.path.join(root_dir, output_dir)\n\n    train_dir = os.path.join(output_dir,output_train)\n\n    val_dir = os.path.join(output_dir,output_val)\n\n    test_dir = os.path.join(output_dir, output_test)\nprint(f\"output_dir: {output_dir}\\ntrain_dir:{train_dir}\\nval_dir:{val_dir}\\ntest_dir:{test_dir}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get a list of train and val images to create a datagenerator\ntrain_list = (os.listdir(train_dir))\nval_list = (os.listdir(val_dir))\n\nnum_train_samples = len(os.listdir(train_dir))\nnum_val_samples = len(os.listdir(val_dir))\ntrain_batch_size = 10\nval_batch_size = 10\n\n#initialize the training and validation steps\ntrain_steps = np.ceil(num_train_samples / train_batch_size)\nval_steps = np.ceil(num_val_samples / val_batch_size)\n\nprint ('Training sample size: ', num_train_samples)\nprint ('Training steps: ', train_steps)\nprint ('Validation sample size: ', num_val_samples)\nprint ('Validation steps : ', val_steps)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Store the weights\nfileName = 'unet_model.h5'\nsaveOrLoadWeights(unet_model,fileName)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Generator class which handles large dataset and creates batches of images.\nclass generator(tf.keras.utils.Sequence):\n    \n    def __init__(self, img_dir,label_file,  batch_size=32, image_size=256, shuffle=True, augment=False, predict=False):\n        \"\"\"\n        Args:\n        :param img_dir (string): Directory with all the images(train, val or test)\n        :param batch_size (optional): Defines the batch size of the generator. when the value is increased memory usage will be more. default is 32.\n        :param image_size: Imagesize which will be input to the model. Images will be loaded to memory and resized them to this resize before inputting to model. default is 256\n        :param shuffle (optional): defult is True, when True the dataset is shuffled before each epoch.\n        :param augment (optional): defult is False, when True the dataset is flipped horizontally\n        :param predict (optional): defult is False, when True only the images are returned , When False, Images and its masks are returned\n        \"\"\"\n        self.folder = img_dir\n        self.filenames = os.listdir(img_dir)\n        self.batch_size = batch_size\n        self.image_size = image_size\n        self.shuffle = shuffle\n        self.augment = augment\n        self.predict = predict\n        self.on_epoch_end()\n        # read the label Label file which contains the bounding boxes\n        self.df_data = pd.read_csv(label_file)\n        # set Nan values to 0\n        self.df_data= self.df_data.fillna(0)\n        self.ratio = image_size / 1024 # Original size\n        \n    def __load__(self, filename):\n        # load input png image file as numpy array\n        img = cv2.imread(os.path.join(self.folder ,filename), 0) \n        # create empty mask\n        msk = np.zeros((self.image_size, self.image_size))\n        patient = self.df_data[self.df_data.patientId==filename[:-4]]\n\n        for i in range(len(patient)):\n            #Calculate the bounding box based on the resized image\n            x1 = int(self.ratio * patient['x'].iloc[i]  )\n            y1 = int(self.ratio * patient['y'].iloc[i] )\n            x2 = x1 + int(self.ratio * patient['width'].iloc[i] )\n            y2 = y1 + int(self.ratio * patient['height'].iloc[i])\n            msk[y1:y2, x1:x2] = 1\n        # resize both image and mask\n        img = resize(img, (self.image_size, self.image_size), mode='reflect')\n        msk = resize(msk, (self.image_size, self.image_size), mode='reflect') > 0.5\n        # if augment then horizontal flip half the time\n        if self.augment and random.random() > 0.5:\n            img = np.fliplr(img)\n            msk = np.fliplr(msk)\n        # add trailing channel dimension\n        img = np.expand_dims(img, -1)\n        msk = np.expand_dims(msk, -1)\n        return img, msk\n    \n    def __loadpredict__(self, filename):\n        # load png image file as numpy array\n        img = cv2.imread(os.path.join(self.folder ,filename), 0) \n        # resize image\n        img = resize(img, (self.image_size, self.image_size), mode='reflect')\n        # add trailing channel dimension\n        img = np.expand_dims(img, -1)\n        return img\n        \n    def __getitem__(self, index):\n        # select batches of files\n        filenames = self.filenames[index*self.batch_size:(index+1)*self.batch_size]\n        \n        # predict mode: return images and filenames\n        if self.predict:\n            # load files\n            imgs = [self.__loadpredict__(filename) for filename in filenames]\n            # create numpy batch\n            imgs = np.array(imgs)\n            return imgs#, filenames\n        # train mode: return images and masks\n        else:\n            # load files\n            items = [self.__load__( filename) for filename in filenames]\n            # unzip images and masks\n            imgs, msks = zip(*items)\n            # create numpy batch\n            imgs = np.array(imgs)\n            msks = np.array(msks)\n            return imgs, msks\n        \n    def on_epoch_end(self):\n        if self.shuffle:\n            shuffle(self.filenames)\n        \n    def __len__(self):\n        if self.predict:\n            # return everything\n            return int(np.ceil(len(self.filenames) / self.batch_size))\n        else:\n            # return full batches only\n            return int(len(self.filenames) / self.batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class generatorWithBoxType(tf.keras.utils.Sequence):\n    \n    def __init__(self, img_dir,label_file,  batch_size=32, image_size=256, shuffle=True, augment=False, predict=False, ytype=['box','lbl', 'both']):\n        \"\"\"\n        Args:\n        :param img_dir (string): Directory with all the images(train, val or test)\n        :param batch_size (optional): Defines the batch size of the generator. when the value is increased memory usage will be more. default is 32.\n        :param image_size: Imagesize which will be input to the model. Images will be loaded to memory and resized them to this resize before inputting to model. default is 256\n        :param shuffle (optional): defult is True, when True the dataset is shuffled before each epoch.\n        :param augment (optional): defult is False, when True the dataset is flipped horizontally\n        :param predict (optional): defult is False, when True only the images are returned , When False, Images and its masks are returned\n        :param ytype : List of possible values=['box','lbl', 'both']. box - returns only the boundarybox as ylable, lbl - returns only the classification lable, both - returns both.\n        \"\"\"\n        self.folder = img_dir\n        self.filenames = os.listdir(img_dir)\n        self.batch_size = batch_size\n        self.image_size = image_size\n        self.shuffle = shuffle\n        self.augment = augment\n        self.predict = predict\n        self.ytype = ytype\n        self.on_epoch_end()\n        # read the label Label file which contains the bounding boxes\n        self.df_data = pd.read_csv(label_file)\n        # set Nan values to 0\n        self.df_data= self.df_data.fillna(0)\n        self.ratio = image_size / 1024 # Original size\n        \n    def __load__(self, filename):\n        # load input png image file as numpy array\n        img = cv2.imread(os.path.join(self.folder ,filename), 0) \n        # create empty mask\n        msk = np.zeros((self.image_size, self.image_size))\n        patient = self.df_data[self.df_data.patientId==filename[:-4]]\n        #initialize the lable\n        lungopacity = [1,0] # Normal\n        for i in range(len(patient)):\n            #Calculate the bounding box based on the resized image\n            x1 = int(self.ratio * patient['x'].iloc[i]  )\n            y1 = int(self.ratio * patient['y'].iloc[i] )\n            x2 = x1 + int(self.ratio * patient['width'].iloc[i] )\n            y2 = y1 + int(self.ratio * patient['height'].iloc[i])\n            msk[y1:y2, x1:x2] = 1\n            if ((x2 - x1) > 0) & ((y2 - y1) >0):\n                lungopacity = [0,1] # update the labels to Pneumonia\n        # resize both image and mask\n        img = resize(img, (self.image_size, self.image_size, 1), mode='reflect')\n        msk = resize(msk, (self.image_size, self.image_size), mode='reflect') > 0.5\n        # if augment then horizontal flip half the time\n        if self.augment and random.random() > 0.5:\n            img = np.fliplr(img)\n            msk = np.fliplr(msk)\n        # add trailing channel dimension\n        #img = np.expand_dims(img, -1)\n        #msk = np.expand_dims(msk, -1)\n        return img, lungopacity,msk\n    \n    def __loadpredict__(self, filename):\n        # load png image file as numpy array\n        img = cv2.imread(os.path.join(self.folder ,filename), 0) \n        # resize image\n        img = resize(img, (self.image_size, self.image_size, 1), mode='reflect')\n        # add trailing channel dimension\n        #img = np.expand_dims(img, -1)\n        return img\n        \n    def __getitem__(self, index):\n        # select batches of files\n        filenames = self.filenames[index*self.batch_size:(index+1)*self.batch_size]\n        \n        # predict mode: return images and filenames\n        if self.predict:\n            # load files\n            imgs = [self.__loadpredict__(filename) for filename in filenames]\n            # create numpy batch\n            imgs = np.array(imgs)\n            return imgs#, filenames\n        # train mode: return images and masks\n        else:\n            # load files\n            items = [self.__load__( filename) for filename in filenames]\n            # unzip images and masks\n            imgs, lbls, msks = zip(*items)\n            # create numpy batch\n            imgs = np.array(imgs)\n            msks = np.array(msks)\n            lbls = np.array(lbls)\n            if self.ytype == 'box':\n                return imgs, msks\n            elif self.ytype == 'lbl':\n                return imgs, lbls\n            else:    \n                return imgs, [lbls, msks]\n            \n    def on_epoch_end(self):\n        if self.shuffle:\n            shuffle(self.filenames)\n        \n    def __len__(self):\n        if self.predict:\n            # return everything\n            return int(np.ceil(len(self.filenames) / self.batch_size))\n        else:\n            # return full batches only\n            return int(len(self.filenames) / self.batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # In the mask, find the bounding box, if there is one then the image consist of Pneumonia infection\n# def detectandMask(mask_img, pred = True, ax=None):\n#     comp = mask_img[:, :] > 0.5\n#     # apply connected components\n#     comp = measure.label(comp)\n#     regionFound_true = 0\n#     # apply bounding boxes\n#     for region in measure.regionprops(comp):\n#         color = 'b'\n#         if (pred == True):\n#             color = 'r'\n#             y, x, y2, x2 = region.bbox\n#         else:\n#             y, x,_, y2, x2 ,_= region.bbox\n            \n#         height = y2 - y\n#         width = x2 - x\n#         if ax != None:\n#             ax.add_patch(patches.Rectangle((x,y),width,height,linewidth=2,edgecolor=color,facecolor='none'))\n#         #Ignore small patches\n#         if (width > 10) & (height > 10):\n#             regionFound_true = 1\n\n#     return regionFound_true","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def detectandMask(mask_img, pred = True, ax=None):\n    comp = mask_img[:, :] > 0.5\n    # apply connected components\n    comp = measure.label(comp)\n    regionFound_true = 0\n    # apply bounding boxes\n    for region in measure.regionprops(comp):\n        color = 'b'\n        if (pred == True):\n            color = 'r'\n        try:\n            y, x, y2, x2 = region.bbox\n            \n        except:\n            y, x,_, y2, x2 ,_= region.bbox\n            \n        height = y2 - y\n        width = x2 - x\n        if ax != None:\n            ax.add_patch(patches.Rectangle((x,y),width,height,linewidth=2,edgecolor=color,facecolor='none'))\n        #Ignore small patches\n        if (width > 10) & (height > 10):\n            regionFound_true = 1\n\n    return regionFound_true","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Define Dice coefficient\ndef dice_coefficient(y_true, y_pred):\n    numerator = 2.0 *  tf.reduce_sum(y_true * y_pred) \n    denominator = tf.reduce_sum(y_true + y_pred)\n    return numerator / (denominator + tf.keras.backend.epsilon() ) \n\n# Combine Bce loss and dice coefficient\ndef loss(y_true, y_pred):\n    y_true = tf.dtypes.cast(y_true, tf.float32)\n    y_pred = tf.dtypes.cast(y_pred, tf.float32)\n    return binary_crossentropy(y_true, y_pred) - log(dice_coefficient(y_true, y_pred) + epsilon())\n\n# Iou loss\ndef iou_loss(y_true, y_pred):\n    y_true = tf.dtypes.cast(tf.reshape(y_true, [-1]), tf.float32)\n    y_pred = tf.dtypes.cast(tf.reshape(y_pred, [-1]), tf.float32)\n    intersection = tf.reduce_sum(y_true * y_pred)\n    score = (intersection + 1.) / (tf.reduce_sum(y_true) + tf.reduce_sum(y_pred) - intersection + 1.)\n    return 1 - score\n\n# combine bce loss and iou loss\ndef iou_bce_loss(y_true, y_pred):\n    return 0.5 * tf.keras.losses.binary_crossentropy(y_true, y_pred) + 0.5 * iou_loss(y_true, y_pred)\n\n# define mean iou \ndef mean_iou(y_true, y_pred):\n    y_pred = tf.round(y_pred)\n    intersect = tf.reduce_sum(y_true * y_pred, axis=[1, 2])\n    union = tf.reduce_sum(y_true, axis=[1, 2]) + tf.reduce_sum(y_pred, axis=[1, 2])\n    smooth = tf.ones(tf.shape(intersect))\n    return tf.reduce_mean((intersect + smooth) / (union - intersect + smooth))\n\n# Pixel accuracy\naccu = tf.keras.metrics.BinaryAccuracy(\n    name=\"binary_accuracy\", dtype=None, threshold=0.5\n)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nfilepath = \"epoch_{epoch:02d}-val_loss_{val_loss:.2f}.h5\" #\"model.h5\"\ncheckpoint = ModelCheckpoint(filepath, monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')\nstop = EarlyStopping(monitor=\"val_accuracy\", patience=5, mode=\"max\")\nreduce_lr = ReduceLROnPlateau(monitor='val_accuracy', factor=0.5, patience=2, verbose=1, mode='max', min_lr=0.00001)\ncallbacks_list = [checkpoint , reduce_lr, stop]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# create Image generator for train, validation and test images\nlabel_path = os.path.join(root_dir, input_dir, label_file)\nlabel_path","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Unet Architecure.\n* Input : takes 224 X 224 grayscale images\n\n* Output : predicts masked grayscale image of size 224 X 224 ."},{"metadata":{"trusted":true},"cell_type":"code","source":"No_OfFiles = 100\ntrain_gen = generator(train_dir, label_path[0:500], batch_size=32, image_size=IMAGE_HEIGHT, shuffle=True, augment=True, predict=False)\nval_gen = generator(val_dir,label_path[0:100],  batch_size=32, image_size=IMAGE_HEIGHT, shuffle=False, predict=False)\ntest_gen = generator(test_dir, label_path[0:100], batch_size=32, image_size=IMAGE_HEIGHT, shuffle=False, predict=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def createUnetModel():\n    input_l = Input((IMAGE_HEIGHT, IMAGE_WIDTH, 1))\n    layer0 =Conv2D(16, (3, 3), activation='relu', padding=\"same\")(input_l)\n    b0 = BatchNormalization()(layer0)\n    mp0 = MaxPooling2D(pool_size=(2, 2))(b0)\n\n    layer1 =Conv2D(32, (3, 3), activation='relu', padding=\"same\")(mp0)\n    b1 = BatchNormalization()(layer1)\n    mp1 = MaxPooling2D(pool_size=(2, 2))(b1)\n\n    layer2 = Conv2D(64, (3, 3), activation='relu', padding=\"same\")(mp1)\n    b2 = BatchNormalization()(layer2)\n    mp2 = MaxPooling2D(pool_size=(2, 2))(b2)\n\n    layer3 = Conv2D(96, (3, 3), dilation_rate=(2, 2), activation='relu', padding=\"same\")(mp2)\n    b3 = BatchNormalization()(layer3)\n    mp3 = MaxPooling2D(pool_size=(2, 2))(b3)\n\n    layer4 = Conv2D(128, (3, 3), dilation_rate=(2, 2), activation='relu', padding=\"same\")(mp3)\n    b4 = BatchNormalization()(layer4)\n    mp4 = MaxPooling2D(pool_size=(2, 2))(b4)    \n    \n    layer5 = Conv2D(256, (3, 3), dilation_rate=(2, 2), activation='relu', padding=\"same\")(mp4)\n    \n    up4 = Conv2D(128, (3, 3), dilation_rate=(2, 2), activation = 'relu', padding = 'same')(UpSampling2D()(layer5))\n    merge4 = Concatenate()([layer4,up4])\n    \n    up3 = Conv2D(96, (3, 3), dilation_rate=(2, 2), activation = 'relu', padding = 'same')(UpSampling2D()(merge4))\n    merge3 = Concatenate()([layer3,up3])\n    \n    up2 = Conv2D(64, (3, 3),  activation = 'relu', padding = 'same')(UpSampling2D()(merge3))\n    merge2 = Concatenate()([layer2,up2])\n    \n    up1= Conv2D(32, (3, 3), activation = 'relu', padding = 'same')(UpSampling2D()(merge2))\n    merge1 = Concatenate()([layer1,up1])\n    \n    up0 = Conv2D(16, (3, 3), activation = 'relu', padding = 'same')(UpSampling2D()(merge1))\n    merge0 = Concatenate()([layer0,up0])\n   \n    conv = Conv2D(1, kernel_size=1, activation='sigmoid') (merge0)\n    \n    outputs = Reshape((IMAGE_HEIGHT, IMAGE_WIDTH))(conv)\n    \n    return  Model(inputs=[input_l], outputs=[outputs]) \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unet_model = createUnetModel()\nunet_model.summary()\n\nunet_model.compile(optimizer='adam',\n              loss=iou_bce_loss,\n              metrics=[accu, mean_iou])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not loadweightsDirectlyToModel:\n    numberofEpochs=1,\n    unet_History = unet_model.fit(train_gen,\n                           validation_data=val_gen,\n                           epochs=5,\n                           verbose=1,\n              callbacks=callbacks_list\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not loadweightsDirectlyToModel:\n    print('List of metrics available: ', unet_model.metrics_names)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#plotGraphs(unet_History) #unet_model.history)\nif not loadweightsDirectlyToModel:\n    plt.figure(figsize=(12,4))\n    plt.subplot(131)\n    history = unet_model.history\n\n    plt.plot(history.epoch, history.history[\"loss\"], label=\"Train loss\")\n    plt.plot(history.epoch, history.history[\"val_loss\"], label=\"Valid loss\")\n    plt.xlabel('Epochs')\n    plt.ylabel('Loss')\n    plt.legend()\n\n    plt.subplot(132)\n    plt.plot(history.epoch, history.history[\"mean_iou\"], label=\"Mean IOU\")\n    plt.plot(history.epoch, history.history[\"val_mean_iou\"], label=\"Mean IOU\")\n    plt.legend()\n\n    plt.subplot(133)\n    plt.plot(history.epoch, history.history[\"binary_accuracy\"], label=\"Accuracy\")\n    plt.plot(history.epoch, history.history[\"val_binary_accuracy\"], label=\"Valid Accuracy\")\n    plt.legend()\n\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"displayImagesWithBoundingBox(unet_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unet_accuracy_score, unet_precision_score,unet_recall_score,unet_f1_score=  displayMetrics('Unet Model',unet_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Generate train, val and test data"},{"metadata":{"trusted":true},"cell_type":"code","source":"# No_OfFiles = 100\n# train_gen = generatorWithBoxType(train_dir, label_path, batch_size=32, image_size=IMAGE_HEIGHT, shuffle=True, augment=True, predict=False, ytype='box')\n# val_gen = generatorWithBoxType(val_dir,label_path,  batch_size=32, image_size=IMAGE_HEIGHT, shuffle=False, predict=False,ytype='box')\n# test_gen = generatorWithBoxType(test_dir, label_path, batch_size=32, image_size=IMAGE_HEIGHT, shuffle=False, predict=True,ytype='box')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### A complex Unet"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create the following block of layers\n# Convolution layer with given kernal size and filter. \n# If requested adds Batch norm layer \n# ReLu activation layer\n# These convolution locks ared added 'ndeeplayer' times to create a deepConvolution layer.\ndef convolutionBlock(input_tensor,ndeeplayer, nfilters, kernelsize=3, batchnorm=True):\n    layer = input_tensor\n    \n    for n in np.arange(ndeeplayer):\n        # first layer\n        layer = Conv2D(filters=nfilters, kernel_size=(kernelsize, kernelsize), kernel_initializer=\"he_normal\",\n                   padding=\"same\")(layer)\n        if batchnorm:\n            layer = BatchNormalization()(layer)\n        layer = Activation(\"relu\")(layer)\n    \n    return layer","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nfrom tensorflow.keras.layers import  Activation\n\n#This function creates Unet model with deep convolution layer.\ndef createDeepUNETModel():\n    input_img = Input((IMAGE_HEIGHT, IMAGE_WIDTH, 1), name = 'input_1')\n    ndeeplayer=8\n    nfilters=16\n    dropout=0.5\n    batchnorm=True\n    # contracting path\n    layer0 = convolutionBlock(input_img, ndeeplayer=ndeeplayer, nfilters=16, kernelsize=3, batchnorm=batchnorm)\n    tmplayer = MaxPooling2D((2, 2)) (layer0)\n    tmplayer = Dropout(dropout*0.5)(tmplayer)\n    \n    layer1 = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=32, kernelsize=3, batchnorm=batchnorm)\n    tmplayer = MaxPooling2D((2, 2)) (layer1)\n    tmplayer = Dropout(dropout*0.5)(tmplayer)\n\n    layer2 = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=64, kernelsize=3, batchnorm=batchnorm)\n    tmplayer = MaxPooling2D((2, 2)) (layer2)\n    tmplayer = Dropout(dropout)(tmplayer)\n\n    layer3 = convolutionBlock(tmplayer,ndeeplayer=ndeeplayer, nfilters=96, kernelsize=3, batchnorm=batchnorm)\n    tmplayer = MaxPooling2D((2, 2)) (layer3)\n    tmplayer = Dropout(dropout)(tmplayer)\n\n    layer4 = convolutionBlock(tmplayer,ndeeplayer=ndeeplayer, nfilters=128, kernelsize=3, batchnorm=batchnorm)\n    tmplayer = MaxPooling2D(pool_size=(2, 2)) (layer4)\n    tmplayer = Dropout(dropout)(tmplayer)\n    \n    layer5 = convolutionBlock(tmplayer, ndeeplayer= ndeeplayer, nfilters=256, kernelsize=3, batchnorm=batchnorm)\n    \n    # expansive path\n    tmplayer = Conv2D(128, (3, 3), dilation_rate=(2, 2), activation = 'relu', padding = 'same')(UpSampling2D()(layer5))\n    tmplayer = Concatenate()([layer4,tmplayer])\n    tmplayer = Dropout(dropout)(tmplayer)\n    tmplayer = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=128, kernelsize=3, batchnorm=batchnorm)\n\n    tmplayer = Conv2D(96, (3, 3), dilation_rate=(2, 2), activation = 'relu', padding = 'same')(UpSampling2D()(tmplayer))\n    tmplayer = Concatenate()([layer3,tmplayer])\n    tmplayer = Dropout(dropout)(tmplayer)\n    tmplayer = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=96, kernelsize=3, batchnorm=batchnorm)\n\n    tmplayer = Conv2D(64, (3, 3),  activation = 'relu', padding = 'same')(UpSampling2D()(tmplayer))\n    tmplayer = Concatenate()([layer2,tmplayer])\n    tmplayer = Dropout(dropout)(tmplayer)\n    tmplayer = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=64, kernelsize=3, batchnorm=batchnorm)\n\n    \n    tmplayer= Conv2D(32, (3, 3), activation = 'relu', padding = 'same')(UpSampling2D()(tmplayer))\n    tmplayer = Concatenate()([layer1,tmplayer])\n    tmplayer = Dropout(dropout)(tmplayer)\n    tmplayer = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=32, kernelsize=3, batchnorm=batchnorm)\n\n    \n    tmplayer = Conv2D(16, (3, 3), activation = 'relu', padding = 'same')(UpSampling2D()(tmplayer))\n    tmplayer = Concatenate(name ='concat_last')([layer0,tmplayer])\n    tmplayer = Dropout(dropout)(tmplayer)\n    tmplayer = convolutionBlock(tmplayer, ndeeplayer=ndeeplayer, nfilters=16, kernelsize=3, batchnorm=batchnorm)\n\n    outputs = Conv2D(1, (1, 1), activation='sigmoid') (tmplayer)\n    model = Model(inputs=[input_img], outputs=[outputs])\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"deepunet_model = createDeepUNETModel()\ndeepunet_model.summary()\ndeepunet_model.compile(optimizer='adam',\n           loss=iou_loss,\n           metrics=['accuracy', mean_iou])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer in deepunet_model.layers:\n    layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not loadweightsDirectlyToModel:\n    numberofEpochs=1,\n    history = deepunet_model.fit(train_gen,\n                           validation_data=val_gen,\n                           epochs=5,\n                           verbose=1,\n              callbacks=callbacks_list\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fileName = 'deepunet_model.h5'\nsaveOrLoadWeights(deepunet_model,fileName)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not loadweightsDirectlyToModel:\n    print('List of metrics available: ', deepunet_model.metrics_names)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plotGraphs(deepunet_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#mask_pred = deepunetmodel.predict(test_gen, steps=300)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"displayImagesWithBoundingBox(deepunet_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"deepunet_accuracy_score, deepunet_precision_score,deepunet_recall_score,deepunet_f1_score=  displayMetrics('Deep UNet Model',deepunet_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"CNN"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow import keras\ndef create_downsample(channels, inputs):\n    x = keras.layers.BatchNormalization(momentum=0.9)(inputs)\n    x = keras.layers.LeakyReLU(0)(x)\n    x = keras.layers.Conv2D(channels, 1, padding='same', use_bias=False)(x)\n    x = keras.layers.MaxPool2D(2)(x)\n    return x\n\n\ndef create_resblock(channels, inputs):\n    x = keras.layers.BatchNormalization(momentum=0.9)(inputs)\n    x = keras.layers.LeakyReLU(0)(x)\n    x = keras.layers.Conv2D(channels, 3, padding='same', use_bias=False)(x)\n    x = keras.layers.BatchNormalization(momentum=0.9)(x)\n    x = keras.layers.LeakyReLU(0)(x)\n    x = keras.layers.Conv2D(channels, 3, padding='same', use_bias=False)(x)\n    return keras.layers.add([x, inputs])\n\ndef create_network(input_size, channels, n_blocks=2, depth=4):\n    # input\n    inputs = keras.Input(shape=(input_size, input_size, 1))\n    x = keras.layers.Conv2D(channels, 3, padding='same', use_bias=False)(inputs)\n    # residual blocks\n    for d in range(depth):\n        channels = channels * 2\n        x = create_downsample(channels, x)\n        for b in range(n_blocks):\n            x = create_resblock(channels, x)\n    # output\n    x = keras.layers.BatchNormalization(momentum=0.9)(x)\n    x = keras.layers.LeakyReLU(0)(x)\n    x = keras.layers.Conv2D(1, 1, activation='sigmoid')(x)\n    outputs = keras.layers.UpSampling2D(2**depth)(x)\n    model = keras.Model(inputs=inputs, outputs=outputs)\n    return model\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cnn_model = create_network(input_size=128, channels=32, n_blocks=2, depth=4)\ncnn_model.compile(loss='binary_crossentropy', optimizer=\"adam\", metrics=['accuracy', mean_iou])\n\nprint(\"model summary:\", cnn_model.summary())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not loadweightsDirectlyToModel:\n#fit the model for 5 epoch.\n    cnn_history = cnn_model.fit(train_gen,\n                           validation_data=val_gen,\n                           epochs=5,\n                           verbose=1,\n              callbacks=callbacks_list\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fileName = \"cnn_model.h5\"\nsaveOrLoadWeights(cnn_model,fileName)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plotGraphs(cnn_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"displayImagesWithBoundingBox(cnn_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cnn_accuracy_score, cnn_precision_score,cnn_recall_score,cnn_f1_score= displayMetrics('CNN Model',cnn_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### ResNet"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.layers import add\nfrom tensorflow.keras.layers import LeakyReLU, SpatialDropout2D, MaxPool2D\nfrom tensorflow.keras import regularizers\nfrom tensorflow.keras.layers import Conv2DTranspose, Activation\n\ndef create_downsample(channels, inputs):\n    layer = BatchNormalization(momentum=0.9)(inputs)\n    layer = LeakyReLU(0)(layer)\n    layer = Conv2D(channels, 1, padding='same', use_bias=False)(layer)\n    layer = MaxPool2D(2)(layer)\n    return layer\n\ndef create_resblock(channels, inputs):\n    layer = BatchNormalization(momentum=0.9)(inputs)\n    layer = LeakyReLU(0)(layer)\n    layer = Conv2D(channels, 3, padding='same', use_bias=False,activity_regularizer=regularizers.l2(0.001))(layer)\n    layer = BatchNormalization(momentum=0.9)(layer)\n    layer = LeakyReLU(0)(layer)\n    layer = Conv2D(channels, 3, padding='same', use_bias=False,activity_regularizer=regularizers.l2(0.001))(layer)\n    return add([layer, inputs])\n\ndef createResnetModel():\n    # input\n    channels= 32\n    depth = 4\n    n_blocks = 2\n    # Input layer\n    inputs = Input(shape=(224, 224, 1))\n    layer = Conv2D(channels, 3, padding='same', use_bias=False)(inputs)\n    # residual blocks\n    for d in range(depth):\n        channels = channels * 2\n        layer = create_downsample(channels, layer)\n        for b in range(n_blocks):\n            layer = create_resblock(channels, layer)\n    # output\n    layer = BatchNormalization(momentum=0.9)(layer)\n    layer = LeakyReLU(0)(layer)\n    layer = Conv2D(256, 1, activation=None)(layer)\n    layer = SpatialDropout2D(0.25)(layer)\n    layer = BatchNormalization(momentum=0.9)(layer)\n    layer = LeakyReLU(0)(layer)\n    layer = Conv2DTranspose(128, (8,8), (4,4), padding=\"same\", activation=None)(layer)\n    layer = SpatialDropout2D(0.25)(layer)\n    layer = BatchNormalization(momentum=0.9)(layer)\n    layer = LeakyReLU(0)(layer)\n    layer = Conv2D(1, 1, activation='sigmoid')(layer)\n    outputs = UpSampling2D(2**(depth-2))(layer)\n    model = Model(inputs=inputs, outputs=outputs)\n    model.summary()\n    return model\n\nresnet_model = createResnetModel()\nresnet_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"resnet_model.compile(optimizer='adam',\n              loss=loss,\n              metrics=['accuracy', mean_iou])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not loadweightsDirectlyToModel:\n#fit the model for 5 epoch.\n    resnet_history = resnet_model.fit(train_gen,\n                           validation_data=val_gen,\n                           epochs=5,\n                           verbose=1,\n              callbacks=callbacks_list\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fileName = \"resnet_model.h5\"\nsaveOrLoadWeights(resnet_model,fileName)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plotGraphs(resnet_history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"displayImagesWithBoundingBox(resnet_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nresnet_accuracy_score, resnet_precision_score,resnet_recall_score,resnet_f1_score=  displayMetrics('Resnet Model',resnet_model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f\"Resnet: accuracy: {resnet_accuracy_score}, precision: {resnet_precision_score}, recall: {resnet_recall_score},f1: {resnet_f1_score}\")\nprint(f\"CNN: accuracy: {cnn_accuracy_score}, precision: {cnn_precision_score}, recall: {cnn_recall_score},f1: {cnn_f1_score}\")\n\nprint(f\"Deep UNet: accuracy: {deepunet_accuracy_score}, precision: {deepunet_precision_score}, recall: {deepunet_recall_score},f1: {deepunet_f1_score}\")\n\nprint(f\"Unet: accuracy: {unet_accuracy_score}, precision: {unet_precision_score}, recall: {unet_recall_score},f1: {unet_f1_score}\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}