{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nimport os\nfrom zipfile import ZipFile  \nimport cv2 as cv\nimport numpy as np\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-19T13:39:08.116108Z","iopub.execute_input":"2022-07-19T13:39:08.116432Z","iopub.status.idle":"2022-07-19T13:39:14.203625Z","shell.execute_reply.started":"2022-07-19T13:39:08.116396Z","shell.execute_reply":"2022-07-19T13:39:14.202610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**The U-Net Block we will build**","metadata":{}},{"cell_type":"code","source":"from IPython.display import Image\nImage('../input/unet-block/Capture.PNG')","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:14.205250Z","iopub.execute_input":"2022-07-19T13:39:14.205496Z","iopub.status.idle":"2022-07-19T13:39:14.246734Z","shell.execute_reply.started":"2022-07-19T13:39:14.205466Z","shell.execute_reply":"2022-07-19T13:39:14.235291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Set Image Dimensions**","metadata":{}},{"cell_type":"code","source":"IMG_WIDTH, IMG_HEIGHT, IMG_DEPTH = 128,128,3","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:14.248111Z","iopub.execute_input":"2022-07-19T13:39:14.248356Z","iopub.status.idle":"2022-07-19T13:39:14.252852Z","shell.execute_reply.started":"2022-07-19T13:39:14.248327Z","shell.execute_reply":"2022-07-19T13:39:14.252262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Unzip files with path**","metadata":{}},{"cell_type":"code","source":"def Unzip(File_Path,Output_Directory ,File_Name):\n    with ZipFile(File_Path, 'r') as zip: \n        zip.extractall(Output_Directory)\n        print(File_Name + \" Unzipped Correctly!\")\n\nZipped_Train_Path = \"../input/data-science-bowl-2018/stage1_train.zip\"\nZipped_Test_Path = \"../input/data-science-bowl-2018/stage1_test.zip\"\n\nUnzip(Zipped_Train_Path,Output_Directory= \"stage1_train\",File_Name = \"Train Data\")\nUnzip(Zipped_Test_Path,Output_Directory = \"stage1_test\", File_Name = \"Test Data\")","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:14.254499Z","iopub.execute_input":"2022-07-19T13:39:14.255021Z","iopub.status.idle":"2022-07-19T13:39:20.843476Z","shell.execute_reply.started":"2022-07-19T13:39:14.254983Z","shell.execute_reply":"2022-07-19T13:39:20.842580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Let's Load our data**","metadata":{}},{"cell_type":"code","source":"def DataLoader(Split_Ratio=0.1): # Split ratio represent the ratio of validation set from the whole dataset\n    Train_Data_Folders = os.listdir('./stage1_train')\n    Test_Data_Folders = os.listdir('./stage1_test')\n\n    Train_Folder_Name = './stage1_train/'\n    Test_Folder_Name = './stage1_test/'\n\n    Train_Samples = []\n    Test_Samples = []\n    Targets = []\n    \n    # ===================== Loading Train Data ==========================#\n    for train_sample_folder in tqdm(Train_Data_Folders):\n        # ===================== Reading Train Images ==========================#\n        Img_Path = Train_Folder_Name + train_sample_folder + '/' + 'images/' + train_sample_folder + '.png' # we use train_sample_folder twice because the img name same as its folder name\n        New_Sample = cv.imread(Img_Path)[:,:,::-1] # opencv read the images in BGR format \n                                                # so we use [:,:,::-1] to convert from BGR to RGB\n        New_Sample = cv.resize(New_Sample, dsize=(IMG_HEIGHT, IMG_WIDTH), interpolation=cv.INTER_CUBIC)\n        Train_Samples.append(np.array(New_Sample))\n        # ===================== Reading Masks ==========================#\n        # Note that each img has different number of masks which represent each cell segmentation\n        # so we will concatenate the whole mask images into single img\n        Masks_Path = Train_Folder_Name + train_sample_folder + '/' + 'masks/' \n        Masks_Imgs = os.listdir(Masks_Path)\n        Accumulated_Mask = np.zeros((IMG_HEIGHT, IMG_WIDTH, 1)) # we will accumulate the masks to collect them in single img\n        for Img in Masks_Imgs:\n            Mask_Path = Masks_Path + Img\n            New_Mask = cv.imread(Mask_Path,0)\n            New_Mask = cv.resize(New_Mask, dsize=(IMG_HEIGHT, IMG_WIDTH))\n            New_Mask = New_Mask.reshape(IMG_HEIGHT, IMG_WIDTH, 1)\n            Accumulated_Mask += New_Mask\n        # After collecting all masks into one mask, we will add the final mask into targets list\n        Targets.append(Accumulated_Mask)\n        \n    # ===================== Loading Test Data ==========================#\n    for test_sample_folder in tqdm(Test_Data_Folders):\n        # ===================== Reading Test Images ==========================#\n        Img_Path = Test_Folder_Name + test_sample_folder + '/' + 'images/' + test_sample_folder + '.png' # we use train_sample_folder twice because the img name same as its folder name\n        New_Sample = cv.imread(Img_Path)[:,:,::-1] # opencv read the images in BGR format \n                                                # so we use [:,:,::-1] to convert from BGR to RGB\n        New_Sample = cv.resize(New_Sample, dsize=(IMG_HEIGHT, IMG_WIDTH), interpolation=cv.INTER_CUBIC)\n        Test_Samples.append(np.array(New_Sample))\n    \n    # ============= Split Data into Train and Validation ============== #\n    if (Split_Ratio >= 0 and Split_Ratio <= 1): # split ratio must be between 0,1\n        print(int(len(Train_Samples) * Split_Ratio))\n        print(int(len(Targets)* Split_Ratio))\n        Validation_Samples = Train_Samples[0:int(len(Train_Samples) * Split_Ratio)]\n        Validation_Targets = Targets[0:int(len(Targets)* Split_Ratio)]\n        Train_Samples = Train_Samples[int(len(Train_Samples)* Split_Ratio):]\n        Train_Targets = Targets[int(len(Targets)*Split_Ratio):]\n    else:\n        print(\"Split Ratio Must be between 0 and 1\")\n    \n    return Train_Samples, Train_Targets, Validation_Samples, Validation_Targets, Test_Samples\n\n\nTrain_Samples, Train_Targets, Validation_Samples, Validation_Targets, Test_Data = DataLoader()","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:20.845686Z","iopub.execute_input":"2022-07-19T13:39:20.846399Z","iopub.status.idle":"2022-07-19T13:39:47.809787Z","shell.execute_reply.started":"2022-07-19T13:39:20.846347Z","shell.execute_reply":"2022-07-19T13:39:47.808940Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Shape of Train, Validation and Test sets**","metadata":{}},{"cell_type":"code","source":"print(\"The Shape of Train set = \" , np.array(Train_Samples).shape)\nprint(\"The Shape of Train target = \", np.array(Train_Targets).shape)\nprint(\"The Shape of Validation set = \" , np.array(Validation_Samples).shape)\nprint(\"The Shape of Validation target = \", np.array(Validation_Targets).shape)\nprint(\"The Shape of Test set = \", np.array(Test_Data).shape)","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:47.811216Z","iopub.execute_input":"2022-07-19T13:39:47.811619Z","iopub.status.idle":"2022-07-19T13:39:47.870687Z","shell.execute_reply.started":"2022-07-19T13:39:47.811577Z","shell.execute_reply":"2022-07-19T13:39:47.869828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Draw a sample from Train and Validation sets**","metadata":{}},{"cell_type":"code","source":"def Draw_Random_Sample():\n    Train_Random_Sample = np.random.randint(0, len(Train_Samples))\n    Validation_Random_Sample = np.random.randint(0, len(Validation_Samples))\n    _, axarr = plt.subplots(2,2)\n    axarr[0,0].imshow(Train_Samples[Train_Random_Sample])\n    axarr[0,1].imshow(Train_Targets[Train_Random_Sample], cmap='gray')# Note that we use cmap='gray' because the targets list has depth shape of 1 and if we don't specify the cmap it will show it as color map\n    axarr[1,0].imshow(Validation_Samples[Validation_Random_Sample])\n    axarr[1,1].imshow(Validation_Targets[Validation_Random_Sample], cmap='gray') \n    plt.show()\n\nDraw_Random_Sample()","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:47.872652Z","iopub.execute_input":"2022-07-19T13:39:47.873039Z","iopub.status.idle":"2022-07-19T13:39:48.238392Z","shell.execute_reply.started":"2022-07-19T13:39:47.873000Z","shell.execute_reply":"2022-07-19T13:39:48.237556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Plot_Model_Graph(Model_History):\n    print(Model_History.history.keys())\n    #Plot the accuracy\n    plt.plot(Model_History.history['accuracy'])\n    plt.plot(Model_History.history['val_accuracy'])\n    plt.title('model accuracy')\n    plt.ylabel('accuracy')\n    plt.xlabel('epoch')\n    plt.legend(['train', 'validation'], loc='upper left')\n    plt.show()\n    #Plot the loss\n    plt.plot(Model_History.history['loss'])\n    plt.plot(Model_History.history['val_loss'])\n    plt.title('model loss')\n    plt.ylabel('loss')\n    plt.xlabel('epoch')\n    plt.legend(['train', 'validation'], loc='upper left')\n    plt.show()\n    return","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:52:00.946784Z","iopub.execute_input":"2022-07-19T13:52:00.947066Z","iopub.status.idle":"2022-07-19T13:52:00.955016Z","shell.execute_reply.started":"2022-07-19T13:52:00.947036Z","shell.execute_reply":"2022-07-19T13:52:00.954098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Build the main block for U-Net architecture**","metadata":{}},{"cell_type":"code","source":"def UNET_Block():\n    # Define The Input Layer\n    Input_Layer = tf.keras.layers.Input((IMG_WIDTH,IMG_HEIGHT, IMG_DEPTH))\n    \n    Normalized_Input = tf.keras.layers.Lambda(lambda Pixel: Pixel/255)(Input_Layer) # divide each image pixel over 255 to keep ranges of number the same\n    \n    # ***************************Start Build The Encoder Path***************************\n    \n    # Start First Layer\n    Contraction_Conv1_1 = tf.keras.layers.Conv2D(filters = 16, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Normalized_Input)\n    Contraction_Conv1_1 = tf.keras.layers.Dropout(0.1)(Contraction_Conv1_1)\n    Contraction_Conv1_2 = tf.keras.layers.Conv2D(filters = 16, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_Conv1_1)\n    Contraction_MaxPooling_1 = tf.keras.layers.MaxPool2D((2,2))(Contraction_Conv1_2)\n    # End First Layer\n    \n    # Start Second Layer 64\n    Contraction_Conv2_1 = tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_MaxPooling_1)\n    Contraction_Conv2_1 = tf.keras.layers.Dropout(0.1)(Contraction_Conv2_1)\n    Contraction_Conv2_2 = tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_Conv2_1)\n    Contraction_MaxPooling_2 = tf.keras.layers.MaxPool2D((2,2))(Contraction_Conv2_2)\n    # End Second Layer 32\n    \n    # Start Third Layer 32\n    Contraction_Conv3_1 = tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_MaxPooling_2)\n    Contraction_Conv3_1 = tf.keras.layers.Dropout(0.1)(Contraction_Conv3_1)\n    Contraction_Conv3_2 = tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_Conv3_1)\n    Contraction_MaxPooling_3 = tf.keras.layers.MaxPool2D((2,2))(Contraction_Conv3_2)\n    # End Third Layer 16\n    \n    # Start Fourth Layer 16\n    Contraction_Conv4_1 = tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_MaxPooling_3)\n    Contraction_Conv4_1 = tf.keras.layers.Dropout(0.1)(Contraction_Conv4_1)\n    Contraction_Conv4_2 = tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_Conv4_1)\n    Contraction_MaxPooling_4 = tf.keras.layers.MaxPool2D((2,2))(Contraction_Conv4_2)\n    # End Fourth Layer 8\n    \n    # Start Fifth Layer 8\n    Contraction_Conv5_1 = tf.keras.layers.Conv2D(filters = 256, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_MaxPooling_4)\n    Contraction_Conv5_1 = tf.keras.layers.Dropout(0.1)(Contraction_Conv5_1)\n    Contraction_Conv5_2 = tf.keras.layers.Conv2D(filters = 256, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Contraction_Conv5_1)\n    # End Fifth Layer 8\n    \n    # *******************************End Encoder Path********************************\n    \n    # *******************************Start Build The Decoder Path******************\n    \n    # Start First Layer 8\n    Expansive_DeConv_1 = tf.keras.layers.Conv2DTranspose(filters = 128, kernel_size = (2,2), strides = (2,2) , padding= 'same')(Contraction_Conv5_2)\n    Expansive_Concat_1 = tf.keras.layers.concatenate([Expansive_DeConv_1,  Contraction_Conv4_2])\n    Expansive_Conv1_1 = tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Concat_1)\n    Expansive_Conv1_1 = tf.keras.layers.Dropout(0.2)(Expansive_Conv1_1)\n    Expansive_Conv1_2 = tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Conv1_1)\n    # End First Layer 16\n    \n    # Start Second Layer 16\n    Expansive_DeConv_2 = tf.keras.layers.Conv2DTranspose(filters = 64, kernel_size = (2,2), strides = (2,2) , padding= 'same')(Expansive_Conv1_2)\n    Expansive_Concat_2 = tf.keras.layers.concatenate([Expansive_DeConv_2,  Contraction_Conv3_2])\n    Expansive_Conv2_1 = tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Concat_2)\n    Expansive_Conv2_1 = tf.keras.layers.Dropout(0.2)(Expansive_Conv2_1)\n    Expansive_Conv2_2 = tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Conv2_1)\n    print(tf.shape(Expansive_Conv2_2))\n    # End Second Layer 32\n    \n    # Start Third Layer 32\n    Expansive_DeConv_3 = tf.keras.layers.Conv2DTranspose(filters = 32, kernel_size = (2,2), strides = (2,2) , padding= 'same')(Expansive_Conv2_2)\n    Expansive_Concat_3 = tf.keras.layers.concatenate([Expansive_DeConv_3,  Contraction_Conv2_2])\n    Expansive_Conv3_1 = tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Concat_3)\n    Expansive_Conv3_1 = tf.keras.layers.Dropout(0.1)(Expansive_Conv3_1)\n    Expansive_Conv3_2 = tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Conv3_1)\n    # End Third Layer 64\n    \n    # Start Fourth Layer 64\n    Expansive_DeConv_4 = tf.keras.layers.Conv2DTranspose(filters = 16, kernel_size = (2,2), strides = (2,2) , padding= 'same')(Expansive_Conv3_2)\n    Expansive_Concat_4 = tf.keras.layers.concatenate([Expansive_DeConv_4,  Contraction_Conv1_2])\n    Expansive_Conv4_1 = tf.keras.layers.Conv2D(filters = 16, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Concat_4)\n    Expansive_Conv4_1 = tf.keras.layers.Dropout(0.1)(Expansive_Conv4_1)\n    Expansive_Conv4_2 = tf.keras.layers.Conv2D(filters = 16, kernel_size = (3,3), activation = 'relu',  kernel_initializer = 'he_normal', padding='same')(Expansive_Conv4_1)\n    # End Fourth Layer 128\n    \n    # *******************************End The Decoder Path******************\n   \n    # Identify Output Layer\n    Output_Layer = tf.keras.layers.Conv2D(filters = 1, kernel_size = (1,1), activation= 'sigmoid')(Expansive_Conv4_2)\n    \n    return Input_Layer, Output_Layer","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:48.248574Z","iopub.execute_input":"2022-07-19T13:39:48.249184Z","iopub.status.idle":"2022-07-19T13:39:48.283086Z","shell.execute_reply.started":"2022-07-19T13:39:48.249153Z","shell.execute_reply":"2022-07-19T13:39:48.281893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Model CheckPoints & Callbacks**","metadata":{}},{"cell_type":"code","source":"CheckPoints = tf.keras.callbacks.ModelCheckpoint('model_for_nuclei.h5', verbose=1, save_best_only=True)\nCallbacks = [tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3),\n            tf.keras.callbacks.TensorBoard(log_dir='logs')]","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:39:48.284435Z","iopub.execute_input":"2022-07-19T13:39:48.284827Z","iopub.status.idle":"2022-07-19T13:39:49.504079Z","shell.execute_reply.started":"2022-07-19T13:39:48.284798Z","shell.execute_reply":"2022-07-19T13:39:49.503344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Train the whole model**","metadata":{}},{"cell_type":"code","source":"def Model(Input, Output, Callbacks):\n    Model = tf.keras.Model(inputs=[Input], outputs= [Output])\n    Model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics= ['accuracy'])\n    Model_History = Model.fit(np.array(Train_Samples),np.array(Train_Targets),validation_split=0.1,\n              batch_size=16, epochs=120, callbacks=Callbacks)\n    Plot_Model_Graph(Model_History)","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:46:29.598655Z","iopub.execute_input":"2022-07-19T13:46:29.599083Z","iopub.status.idle":"2022-07-19T13:46:29.604065Z","shell.execute_reply.started":"2022-07-19T13:46:29.599051Z","shell.execute_reply":"2022-07-19T13:46:29.603446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Let's Connect each component of the model to see predictions**","metadata":{}},{"cell_type":"code","source":"Input_Layer, Output_Layer = UNET_Block()\nModel(Input_Layer, Output_Layer, Callbacks)\n","metadata":{"execution":{"iopub.status.busy":"2022-07-19T13:52:20.169093Z","iopub.execute_input":"2022-07-19T13:52:20.169821Z","iopub.status.idle":"2022-07-19T13:54:22.894888Z","shell.execute_reply.started":"2022-07-19T13:52:20.169773Z","shell.execute_reply":"2022-07-19T13:54:22.893954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}