# -*- coding: utf-8 -*-
"""FinalDenseNewUnet.ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1oJuJNSsjWBkLGYHabpmkRXWTxW2jECJr
"""

import tensorflow as tf
tf.test.gpu_device_name()

import tensorflow
import keras
import keras.applications
print(tensorflow.__version__)
print(keras.__version__)
#print(keras.applications__version__)

import tensorflow
import keras
#import keras_applications
print(tensorflow.__version__)
print(keras.__version__)
#print(keras_applications.__version__)

from __future__ import print_function

#import os
import numpy as np

import cv2
import pandas as pd
import sys
import os
import os.path
import string
import scipy.io
import pdb
import PIL.Image as Image
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.font_manager import FontProperties
import skimage
import skimage.measure
import glob
import imageio
from keras import backend as K
K.set_image_data_format('channels_last')
import tensorflow as tf
#from keras_tqdm import TQDMNotebookCallback
data_path = '/content/drive/My Drive/Augmented/Data/'
save_path = '/content/drive/My Drive/Augmented/Data/nypdata/'
image_rows = 256
image_cols = 256
from keras.callbacks import CSVLogger
csvlogger = CSVLogger('CSV1.csv', separator=',' , append=False)
from keras.callbacks import History
history = History()

!pip install git+https://github.com/qubvel/segmentation_models

from keras.models import Model, Sequential
from keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, Lambda, Dropout, Conv2DTranspose, concatenate, Multiply,Activation, Average,LSTM

from tensorflow.keras.applications.vgg16 import VGG16

import keras.backend as K
from keras.optimizers import Adam
from keras.losses import binary_crossentropy
from keras.layers import BatchNormalization

def conv_block(input_tensor, nb_filter, dropout_rate=None, weight_decay=1e-4):
    ''' Apply BatchNorm, Relu, 3x3 tf.keras.layers.Conv2D, optional bottleneck block and dropout
    Args:
        ip: Input keras tensor
        nb_filter: number of filters
        bottleneck: add bottleneck block
        dropout_rate: dropout rate
        weight_decay: weight decay factor
    Returns: keras tensor with batch_norm, relu and convolution2d added (optional bottleneck)
    '''
    #input_tensor
    #input_tensor=None
    concat_axis =-1
    #nb_filter=12
    x = BatchNormalization(axis=concat_axis, epsilon=1.1e-5)(input_tensor)
    x = Activation('relu')(x)


    x = Conv2D(nb_filter, (3, 3), kernel_initializer='he_normal', padding='same', use_bias=False)(x)
    if dropout_rate:
        x = Dropout(dropout_rate)(x)

    return x
#conv_block(input_tensor, nb_filter=12, bottleneck=False, dropout_rate=None, weight_decay=1e-4)

def dense_block(x, nb_layers, nb_filter, growth_rate, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False):
    ''' Build a dense_block where the output of each conv_block is fed to subsequent ones
    Args:
        x: keras tensor
        nb_layers: the number of layers of conv_block to append to the model.
        nb_filter: number of filters
        growth_rate: growth rate
        bottleneck: bottleneck block
        dropout_rate: dropout rate
        weight_decay: weight decay factor
        grow_nb_filters: flag to decide to allow number of filters to grow
        return_concat_list: return the list of feature maps along with the actual output
    Returns: keras tensor with nb_layers of conv_block appended
    '''
    concat_axis = 1 if K.image_data_format() == 'channels_first' else -1

    #nb_layers = 8
    x_list = [x]

    for i in range(nb_layers):
        cb = conv_block(x, growth_rate, dropout_rate, weight_decay)
        x_list.append(cb)

        x = concatenate([x, cb], axis=concat_axis)

        if grow_nb_filters:
            nb_filter += growth_rate

    if return_concat_list:
        return x, nb_filter, x_list
    else:
        return x
#dense_block(Input, nb_layers, nb_filter, growth_rate, bottleneck=False, dropout_rate=None, weight_decay=1e-4,grow_nb_filters=True, return_concat_list=False)

def AttnBlock2D(x, g, inter_channel, data_format='channels_first'):

    theta_x = Conv2D(inter_channel, [1, 1], strides=[1, 1], data_format=data_format)(x)

    phi_g = Conv2D(inter_channel, [1, 1], strides=[1, 1], data_format=data_format)(g)

    f = Activation('relu')(add([theta_x, phi_g]))

    psi_f = Conv2D(1, [1, 1], strides=[1, 1], data_format=data_format)(f)

    rate = Activation('sigmoid')(psi_f)

    att_x = multiply([x, rate])
    return att_x


def attention_up_and_concate(down_layer, layer, data_format='channels_first'):
    if data_format == 'channels_first':
        in_channel = down_layer.get_shape().as_list()[1]
    else:
        in_channel = down_layer.get_shape().as_list()[3]

    up = UpSampling2D(size=(2, 2), data_format=data_format)(down_layer)
    layer = AttnBlock2D(x=layer, g=up, inter_channel=in_channel // 4, data_format=data_format)

    if data_format == 'channels_first':
        my_concat = Lambda(lambda x: K.concatenate([x[0], x[1]], axis=1))
    else:
        my_concat = Lambda(lambda x: K.concatenate([x[0], x[3]], axis=3))
    concate = my_concat([up, layer])
    return concate

### for attention gates
def get_deepthyunet():
  base_pretrained_model = VGG16(input_shape = (256,256,3), include_top = False, weights = 'imagenet')
  for layer in base_pretrained_model.layers:
    layer.trainable = False
  #base_pretrained_model.summary()
  inp = base_pretrained_model.input
  output_vgg16_conv = base_pretrained_model.output
  print(output_vgg16_conv.shape)


  conv_1  = Conv2D(512, (3,3),dilation_rate=32, activation='relu', padding='same')(output_vgg16_conv)
  #print(conv_1.shape)
  up_conv = Conv2DTranspose(256, (3,3), strides=(2,2), activation='relu', padding='same')(conv_1)

  ### Boundary Regression##
  Dconv_1 = Conv2D(1, (1, 1), activation='relu',padding='same')(conv_1)
  #print(Dconv_1)
  Dconv_2 = Conv2D(128, (5, 5), activation='relu',padding='same')(conv_1)
  #print(Dconv_2)
  #Dconv_3 = Conv2D(112, (5, 5), dilation_rate=16, activation='relu',padding='same')(Dconv_2)
  #print(Dconv_3)
  Tconv_1 = Conv2DTranspose(96, (5,5), strides=(2,2), activation='relu', padding='same')(Dconv_2)
  #print(Tconv_1)
  Tconv_2 = Conv2DTranspose(80, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_1)
  #print(Tconv_2)
  Tconv_3 = Conv2DTranspose(64, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_2)
  #print(Tconv_3)
  Tconv_4 = Conv2DTranspose(48, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_3)
  #print(Tconv_4)
  Tconv_5 = Conv2DTranspose(32, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_4)
  print(Tconv_5)
  Tconv_6 = Conv2DTranspose(1, (1,1), strides=(2,2), activation='relu', padding='same')(Tconv_4)
  #print(Tconv_6)

  # first concatenation block


  Atten_1 = dense_block(base_pretrained_model.get_layer('block5_conv3').output, base_pretrained_model.get_layer('block4_conv3').output ,3, data_format='channels_first')
  #Dense_1_Out = concatenate([base_pretrained_model.get_layer('block5_conv3').output, Dense_1])
  #print(Dense_1.shape)

  Dense_1_Out = Conv2D(512, (1, 1), activation='relu',padding='same')(Dense_1)
  #print(Dense_1_Out.shape)
  concat_1 = concatenate([base_pretrained_model.get_layer('block5_conv3').output, up_conv,Dense_1_Out], axis=-1, name='concat_1')
  conv_2 = Conv2D(512, (3,3), activation='relu', padding='same')(concat_1)
  up_conv_2 = Conv2DTranspose(256, (3,3), strides=(2,2), activation='relu', padding='same')(conv_2)

  # second concatenation block
  Dense_2 = dense_block(base_pretrained_model.get_layer('block4_conv3').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_2_Out=Conv2D(256, (1, 1), activation='relu')(Dense_2)
  concat_2 = concatenate([up_conv_2, base_pretrained_model.get_layer('block4_conv3').output,Dense_2_Out])
  conv_3 = Conv2D(512, (3,3), activation='relu', padding='same')(concat_2)
  up_conv_3 = Conv2DTranspose(128, (3,3), strides=(2,2), activation='relu', padding='same')(conv_3)

  # third concatenation block
  Dense_3 = dense_block(base_pretrained_model.get_layer('block3_conv3').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_3_Out=Conv2D(256, (1, 1), activation='relu')(Dense_3)
  concat_3 = concatenate([up_conv_3, base_pretrained_model.get_layer('block3_conv3').output,Dense_3_Out])
  conv_4 = Conv2D(256, (3,3), activation='relu', padding='same')(concat_3)
  up_conv_4 = Conv2DTranspose(64, (3,3), strides=(2,2), activation='relu', padding='same')(conv_4)

  # fourth concatenation block
  Dense_4 = dense_block(base_pretrained_model.get_layer('block2_conv2').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_4_Out=Conv2D(256, (1, 1), activation='relu')(Dense_4)
  concat_4 = concatenate([up_conv_4, base_pretrained_model.get_layer('block2_conv2').output,Dense_4_Out])
  conv_5 = Conv2D(128, (3,3), activation='relu', padding='same')(concat_4)
  up_conv_5 = Conv2DTranspose(32, (3,3), strides=(2,2), activation='relu', padding='same')(conv_5)

  # fifth concatenation block
  Dense_5 = dense_block(base_pretrained_model.get_layer('block1_conv2').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_5_Out=Conv2D(256, (1, 1), activation='relu')(Dense_5)
  concat_4 = concatenate([up_conv_5, base_pretrained_model.get_layer('block1_conv2').output,Dense_5_Out])
  conv_6 = Conv2D(128, (3,3), activation='relu', padding='same')(concat_4)
  #conv_final=Conv2D(1, (1, 1), activation='sigmoid')(conv_6)
  print(conv_6)
  final_out = concatenate([conv_6, Tconv_5])
  print(final_out.shape)
  conv_final2=Conv2D(1, (1, 1), activation='sigmoid')(final_out)
  print(conv_final2.shape)
  #image_2 = Multiply()([inp, conv_final1])
  finalModel = Model(inp, conv_final2)
  #for layer in finalModel1 .layers:
    #layer.name = layer.name + str('_1')
  #finalModel.summary()


  return finalModel
#get_deepthyunet()

def get_deepthyunet():
  base_pretrained_model = VGG16(input_shape = (256,256,3), include_top = False, weights = 'imagenet')
  for layer in base_pretrained_model.layers:
    layer.trainable = False
  #base_pretrained_model.summary()
  inp = base_pretrained_model.input
  output_vgg16_conv = base_pretrained_model.output
  print(output_vgg16_conv.shape)


  conv_1  = Conv2D(512, (3,3),dilation_rate=32, activation='relu', padding='same')(output_vgg16_conv)
  #print(conv_1.shape)
  up_conv = Conv2DTranspose(256, (3,3), strides=(2,2), activation='relu', padding='same')(conv_1)

  ### Boundary Regression##
  Dconv_1 = Conv2D(1, (1, 1), activation='relu',padding='same')(conv_1)
  #print(Dconv_1)
  Dconv_2 = Conv2D(128, (5, 5), activation='relu',padding='same')(conv_1)
  #print(Dconv_2)
  #Dconv_3 = Conv2D(112, (5, 5), dilation_rate=16, activation='relu',padding='same')(Dconv_2)
  #print(Dconv_3)
  Tconv_1 = Conv2DTranspose(96, (5,5), strides=(2,2), activation='relu', padding='same')(Dconv_2)
  #print(Tconv_1)
  Tconv_2 = Conv2DTranspose(80, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_1)
  #print(Tconv_2)
  Tconv_3 = Conv2DTranspose(64, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_2)
  #print(Tconv_3)
  Tconv_4 = Conv2DTranspose(48, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_3)
  #print(Tconv_4)
  Tconv_5 = Conv2DTranspose(32, (5,5), strides=(2,2), activation='relu', padding='same')(Tconv_4)
  print(Tconv_5)
  Tconv_6 = Conv2DTranspose(1, (1,1), strides=(2,2), activation='relu', padding='same')(Tconv_4)
  #print(Tconv_6)

  # first concatenation block
  Dense_1 = dense_block(base_pretrained_model.get_layer('block5_conv3').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  #Dense_1_Out = concatenate([base_pretrained_model.get_layer('block5_conv3').output, Dense_1])
  #print(Dense_1.shape)

  Dense_1_Out = Conv2D(512, (1, 1), activation='relu',padding='same')(Dense_1)
  #print(Dense_1_Out.shape)
  concat_1 = concatenate([base_pretrained_model.get_layer('block5_conv3').output, up_conv,Dense_1_Out], axis=-1, name='concat_1')
  conv_2 = Conv2D(512, (3,3), activation='relu', padding='same')(concat_1)
  up_conv_2 = Conv2DTranspose(256, (3,3), strides=(2,2), activation='relu', padding='same')(conv_2)

  # second concatenation block
  Dense_2 = dense_block(base_pretrained_model.get_layer('block4_conv3').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_2_Out=Conv2D(256, (1, 1), activation='relu')(Dense_2)
  concat_2 = concatenate([up_conv_2, base_pretrained_model.get_layer('block4_conv3').output,Dense_2_Out])
  conv_3 = Conv2D(512, (3,3), activation='relu', padding='same')(concat_2)
  up_conv_3 = Conv2DTranspose(128, (3,3), strides=(2,2), activation='relu', padding='same')(conv_3)

  # third concatenation block
  Dense_3 = dense_block(base_pretrained_model.get_layer('block3_conv3').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_3_Out=Conv2D(256, (1, 1), activation='relu')(Dense_3)
  concat_3 = concatenate([up_conv_3, base_pretrained_model.get_layer('block3_conv3').output,Dense_3_Out])
  conv_4 = Conv2D(256, (3,3), activation='relu', padding='same')(concat_3)
  up_conv_4 = Conv2DTranspose(64, (3,3), strides=(2,2), activation='relu', padding='same')(conv_4)

  # fourth concatenation block
  Dense_4 = dense_block(base_pretrained_model.get_layer('block2_conv2').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_4_Out=Conv2D(256, (1, 1), activation='relu')(Dense_4)
  concat_4 = concatenate([up_conv_4, base_pretrained_model.get_layer('block2_conv2').output,Dense_4_Out])
  conv_5 = Conv2D(128, (3,3), activation='relu', padding='same')(concat_4)
  up_conv_5 = Conv2DTranspose(32, (3,3), strides=(2,2), activation='relu', padding='same')(conv_5)

  # fifth concatenation block
  Dense_5 = dense_block(base_pretrained_model.get_layer('block1_conv2').output, nb_layers=3, nb_filter=3, growth_rate=12, dropout_rate=None, weight_decay=1e-4,
                  grow_nb_filters=True, return_concat_list=False)
  Dense_5_Out=Conv2D(256, (1, 1), activation='relu')(Dense_5)
  concat_4 = concatenate([up_conv_5, base_pretrained_model.get_layer('block1_conv2').output,Dense_5_Out])
  conv_6 = Conv2D(128, (3,3), activation='relu', padding='same')(concat_4)
  #conv_final=Conv2D(1, (1, 1), activation='sigmoid')(conv_6)
  print(conv_6)
  final_out = concatenate([conv_6, Tconv_5])
  print(final_out.shape)
  conv_final2=Conv2D(1, (1, 1), activation='sigmoid')(final_out)
  print(conv_final2.shape)
  #image_2 = Multiply()([inp, conv_final1])
  finalModel = Model(inp, conv_final2)
  #for layer in finalModel1 .layers:
    #layer.name = layer.name + str('_1')
  #finalModel.summary()


  return finalModel
#get_deepthyunet()

def train_and_predict():
    img_rows = 256
    img_cols = 256
    print('-'*30)
    print('Loading and preprocessing train data...')
    print('-'*30)
    imgs_train=np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_train_data2.npy')
    #print(imgs_train)
    imgs_mask_train=np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_train_mask_grayscale2.npy')
    #imgs_train = preprocess(imgs_train)
    #imgs_mask_train = preprocess(imgs_mask_train)
    imgs_train = imgs_train.astype('float32')
    mean = np.mean(imgs_train)  # mean for data centering
    std = np.std(imgs_train)  # std for data normalization
    imgs_train -= mean
    imgs_train /= std
    #print(imgs_train.shape)
    #print(imgs_test.shape)
    imgs_train = imgs_train.reshape(imgs_train.shape[0], img_rows, img_cols, 3)
    print(imgs_train.shape)
    imgs_mask_train = imgs_mask_train.astype('float32')
    imgs_mask_train = imgs_mask_train.reshape(imgs_train.shape[0], img_rows, img_cols, 1)
    print(imgs_mask_train.shape)
    imgs_mask_train /= 255.  # scale masks to [0, 1]

    #imgs_train1 = imgs_train[0:422]
    #imgs_mask_train1 = imgs_mask_train[0:422]
    #x_val = imgs_train[422:528]
    #y_val = imgs_mask_train[422:528]

    #print(imgs_train1.shape)
    #print(imgs_mask_train1.shape)
    #print(x_val.shape)
    #print(y_val.shape)



    #imgs_mask_train = to_categorical(imgs_mask_train,num_classes=1)
    #imgs_mask_train = imgs_mask_train.reshape(imgs_train.shape[0], img_rows, img_cols, 1)
    #print(imgs_mask_train.shape)
    #validation_labels = np_utils.to_categorical(validation_labels, 3)
    print('-'*30)
    print('Creating and compiling model...')
    print('-'*30)
    model = get_deepthyunet()
    #finalModel.summary()
    #model.compile('Adam', loss = 'dice_coef_loss',metrics=['iou_score', 'f1_score', 'precision', 'recall'])
    model.compile('Adam', 'binary_crossentropy', ['binary_accuracy'])
    #finalModel.compile('Adam', 'binary_crossentropy', ['binary_accuracy'])
    #model.fit(imgs_train1, imgs_mask_train1, batch_size=8, epochs=50, verbose=1, shuffle=False, callbacks=[csvlogger], validation_data=(x_val, y_val))
    model.fit(imgs_train, imgs_mask_train, batch_size=8, epochs=15, verbose=1, shuffle=True, callbacks=[csvlogger], validation_split=0.2)
    #print(hist.history.keys())
    print('-'*30)
    print('Loading and preprocessing test data...')
    print('-'*30)
    imgs_test = np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_test_data2.npy')
    imgs_id = np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_id_test_data2.npy')
    #imgs_test = preprocess(imgs_test)
    imgs_test = imgs_test.astype('float32')
    imgs_test -= mean
    imgs_test /= std
    imgs_test = imgs_test.reshape(imgs_test.shape[0], img_rows, img_cols,3)
    print('-'*30)
    #print('Loading saved weights...')
    #print('-'*30)
    #model.load_weights('unet.hdf5')
    #model.load_weights('weights.h5')


    pred_dir = '/content/drive/My Drive/Augmented/Data/DeepthyModels'
    if not os.path.exists(pred_dir):
      os.mkdir(pred_dir)
    model.save(os.path.join(pred_dir, ('Deepthy_Final_illustrationAtten.tf')))

    print('-'*30)
    print('Predicting masks on test data...')
    print('-'*30)
    imgs_mask_test = model.predict(imgs_test, verbose=1)
    np.save(save_path+'imgs_mask_predicted_Deepthy_Final.npy', imgs_mask_test)
    print('-' * 30)
    print('Saving predicted masks to files...')
    print('-' * 30)
    pred_dir = '/content/drive/My Drive/Augmented/Data/Results/AttenYSegNetModel'
    if not os.path.exists(pred_dir):
      os.mkdir(pred_dir)
    for image, image_id in zip(imgs_mask_test, imgs_id):
      image = (image[:,:,0] * 255.).astype(np.uint8)
      imageio.imwrite(os.path.join(pred_dir, str(image_id) + '_pred.png'), image)


#if __name__ == '__main__':
train_and_predict()

import numpy as np
import tensorflow as tf
from tensorflow import keras

#print(hist.history)
import matplotlib.pyplot as plt
#from keras.callbacks import History
#history = History()
#print(history)
plt.plot(hist.History['binary_accuracy'])
plt.plot(hist.history['val_binary_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

img_rows = 256
img_cols = 256
model = keras.models.load_model('/content/drive/My Drive/Augmented/Data/DeepthyModels/Deepthy_Final_illustrationAtten.tf')
x_test = np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_test_data2.npy')
y_test = np.load('/content/drive/MyDrive/Augmented/Data/nypdata/imgs_mask_predicted_Deepthy_Final.npy')
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols,3)
x_test = x_test.astype('float32')
print(y_test.shape)

y_test = y_test.reshape(y_test.shape[0], img_rows, img_cols, 1)/255
y_test = y_test.astype('float32')
print(y_test.shape)
print("Evaluate on test data")
#y_test = ('/content/drive/My Drive/Augmented/Data/nypdata/imgs_test_data_groundtruth_mask2.npy')
results = model.evaluate(x_test, y_test,batch_size=8, verbose=1,)
print("test loss, test acc:", results)

img_rows = 256
img_cols = 256
model = keras.models.load_model('/content/drive/My Drive/Augmented/Data/DeepthyModels/Deepthy_Final_illustration.tf')
imgs_test = np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_test_data2.npy')
imgs_id = np.load('/content/drive/My Drive/Augmented/Data/nypdata/imgs_id_test_data2.npy')
#imgs_test = preprocess(imgs_test)
mean = np.mean(imgs_test)  # mean for data centering
std = np.std(imgs_test)
imgs_test = imgs_test.astype('float32')
imgs_test -= mean
imgs_test /= std
imgs_test = imgs_test.reshape(imgs_test.shape[0], img_rows, img_cols,3)
print('-'*30)
print('Predicting masks on test data...')
print('-'*30)
imgs_mask_test = model.predict(imgs_test, verbose=1)
np.save(save_path+'imgs_mask_predicted_Deepthy_Final_illustration.npy', imgs_mask_test)
print('-' * 30)
print('Saving predicted masks to files...')
print('-' * 30)
pred_dir = '/content/drive/My Drive/Augmented/Data/Results/Deepthy_Final_illustration'
if not os.path.exists(pred_dir):
  os.mkdir(pred_dir)
for image, image_id in zip(imgs_mask_test, imgs_id):
  image = (image[:,:,0] * 255.).astype(np.uint8)
  imageio.imwrite(os.path.join(pred_dir, str(image_id) + '_pred.png'), image)

model.summary()

print(history.history.keys())