{"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":"markdown","source":"<h2 style='color:green'> Imports </h2>\n","metadata":{}},{"cell_type":"code","source":"\n\nimport os\nimport pathlib\nimport time\nimport datetime\nimport imageio\nfrom glob import glob\n\n\n\nimport tensorflow as tf\nimport numpy as np \nimport tensorflow.keras.backend as K\nimport tensorflow_addons as tfa\n\n\nfrom matplotlib import pyplot as plt\nfrom IPython import display\nfrom termcolor import colored\nfrom tqdm import tqdm\nfrom IPython.display import Image\nimport PIL\nfrom PIL import ImageDraw\nfrom IPython import display\n\ndef color_print(print_str,\n                 print_color='green'):\n    \n    '''print in given  color (default green)'''\n    print(colored(print_str,print_color))\n\n","metadata":{"execution":{"iopub.status.busy":"2023-04-27T14:07:37.021249Z","iopub.execute_input":"2023-04-27T14:07:37.021561Z","iopub.status.idle":"2023-04-27T14:07:43.261896Z","shell.execute_reply.started":"2023-04-27T14:07:37.021486Z","shell.execute_reply":"2023-04-27T14:07:43.26095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef set_seed(seed):\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\n    print(f'setting seed to {seed}')\n    \n\nclass CFG:\n    \n    # Dimension of image\n    IMG_WIDTH =  512\n    IMG_HEIGHT = 512\n    \n    #resize image \n    resize_height = 700\n    resize_width = 1200\n    \n    #the lambda param in loss\n    LAMBDA = 10\n    #--------train pipe-------------\n    BUFFER_SIZE = 100\n    # The batch size of 1 produced better results for the U-Net in the original pix2pix experiment\n    BATCH_SIZE = 2\n    \n    #cache \n    cache= 50\n    \n    #learning rate \n    learning_rate = 0.00025\n    \n    \n    seed = 7 \n    \n\nset_seed(CFG.seed)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:08:57.140084Z","iopub.execute_input":"2023-04-27T14:08:57.140708Z","iopub.status.idle":"2023-04-27T14:08:57.149009Z","shell.execute_reply.started":"2023-04-27T14:08:57.140673Z","shell.execute_reply":"2023-04-27T14:08:57.148026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:green'> Data directories </h2>\n","metadata":{}},{"cell_type":"code","source":"day_dir = '../input/daynight-cityview/day'\nnight_dir = '../input/daynight-cityview/night'\n\n\n#plotting a sample image \nplt.figure(figsize=(16,8))\n\nimg = plt.imread(day_dir + '/' + os.listdir(day_dir)[0])\nplt.imshow(img)\nplt.axis('off')\nplt.title('sample image')\nprint(f'Image dimensions {img.shape}')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:11:13.429995Z","iopub.execute_input":"2023-04-27T14:11:13.430732Z","iopub.status.idle":"2023-04-27T14:11:14.201001Z","shell.execute_reply.started":"2023-04-27T14:11:13.430695Z","shell.execute_reply":"2023-04-27T14:11:14.200131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:green'> building data loading pipeline </h2>\n","metadata":{}},{"cell_type":"code","source":"def load_image(image_file):\n    '''load a image file'''\n    image = tf.io.read_file(image_file)\n    image = tf.io.decode_jpeg(image)\n    \n    return image\n\n\ndef random_crop(image):\n    '''randomly crop image into defined size '''\n    cropped_image = tf.image.random_crop(image, size=[CFG.IMG_HEIGHT, CFG.IMG_WIDTH, 3])\n\n    return cropped_image\n\n\ndef normalize(image):\n    '''normalizing the images to [-1, 1]'''\n    image = tf.cast(image, tf.float32)\n    image = (image / 127.5) - 1\n    return image\n\n\ndef de_normalize(image):\n    '''De normalize the image to be in range (0,1)'''\n    \n    return (image * 0.5) + 0.5\n    ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:11:21.062858Z","iopub.execute_input":"2023-04-27T14:11:21.063227Z","iopub.status.idle":"2023-04-27T14:11:21.070984Z","shell.execute_reply.started":"2023-04-27T14:11:21.063195Z","shell.execute_reply":"2023-04-27T14:11:21.070019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def image_augmentations(image):\n    '''perform spatial augmentations (rotation and flips) on input image\n    \n    from : https://www.kaggle.com/code/dimitreoliveira/improving-cyclegan-monet-paintings'''\n    \n    \n    # --------------------rotations----------\n    #rotation probabliity\n    p_rotate = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n    \n    if p_rotate > .8:\n        image = tf.image.rot90(image, k=3) # rotate 270º\n    elif p_rotate > .6:\n        image = tf.image.rot90(image, k=2) # rotate 180º\n    elif p_rotate > .4:\n        image = tf.image.rot90(image, k=1) # rotate 90º\n    \n    \n    \n    # ----------------------Flips---------------------\n    p_flip = tf.random.uniform([], 0, 1.0, dtype=tf.float32)\n    \n    if p_flip > 0.7:    \n        image = tf.image.random_flip_left_right(image)\n    elif p_flip < 0.3:\n        image = tf.image.random_flip_up_down(image)\n    \n    return image","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:15:03.845345Z","iopub.execute_input":"2023-04-27T14:15:03.845707Z","iopub.status.idle":"2023-04-27T14:15:03.852829Z","shell.execute_reply.started":"2023-04-27T14:15:03.845675Z","shell.execute_reply":"2023-04-27T14:15:03.85191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def random_jitter(image):\n    '''resize and randommly crop the input image'''\n    \n#     # resizing image\n    image = tf.image.resize(image, size=(CFG.resize_height, CFG.resize_width),\n                          method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)\n\n    # randomly cropping to 512,512\n    image = random_crop(image)\n    \n    return image\n\n\ndef preprocess_image_train(image):\n    image = load_image(image)\n    image = random_jitter(image)\n    image= image_augmentations(image)\n    image = normalize(image)\n    return image\n\n\n#same function, withou the augemntation\ndef preprocess_image_eval(image):\n    image = load_image(image)\n    image = random_jitter(image)\n    image = normalize(image)\n    return image\n\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:16:08.761613Z","iopub.execute_input":"2023-04-27T14:16:08.762215Z","iopub.status.idle":"2023-04-27T14:16:08.770742Z","shell.execute_reply.started":"2023-04-27T14:16:08.762176Z","shell.execute_reply":"2023-04-27T14:16:08.768058Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\ndef create_img_dataset(directory,\n                       image_preprocess_fn,\n                       image_extension = 'jpg',         \n                       repeat=True\n                      ):\n    '''create a tf dataset object from a directory of images'''\n    img_list = glob(directory+f'/*{image_extension}')\n    \n    dataset = tf.data.Dataset.list_files(img_list)\n    \n    dataset = dataset.map(image_preprocess_fn,\n                          num_parallel_calls=tf.data.AUTOTUNE)\n    \n    if repeat :\n        dataset = dataset.repeat()\n              \n    dataset = dataset.shuffle(CFG.BUFFER_SIZE) \n    dataset = dataset.batch(CFG.BATCH_SIZE)\n    return dataset\n\n\nDay_Dataset = create_img_dataset(directory = day_dir,image_preprocess_fn = preprocess_image_train)\n\n#without augmentation\nDay_eval = create_img_dataset(directory = day_dir,\n                            image_preprocess_fn = preprocess_image_eval)\n\n\n\nfig,ax = plt.subplots(figsize=(16,8))\n    \ninp_img = next(iter(Day_Dataset))\nplt.imshow(de_normalize(inp_img[0]))\nplt.title('Sample Day image')\nplt.axis('off')\n\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:16:12.615774Z","iopub.execute_input":"2023-04-27T14:16:12.616146Z","iopub.status.idle":"2023-04-27T14:16:27.408805Z","shell.execute_reply.started":"2023-04-27T14:16:12.616114Z","shell.execute_reply":"2023-04-27T14:16:27.407945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Night_Dataset = create_img_dataset(directory = night_dir,image_preprocess_fn = preprocess_image_train)\nNight_eval = create_img_dataset(directory = night_dir,\n                                image_preprocess_fn = preprocess_image_eval)\nfig,ax = plt.subplots(figsize=(16,8))\n\n\ninp_img = next(iter(Night_Dataset))\nplt.imshow(de_normalize(inp_img[0]))\nplt.title('Sample Night image')\nplt.axis('off')\n\nplt.show()\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:16:32.851003Z","iopub.execute_input":"2023-04-27T14:16:32.85199Z","iopub.status.idle":"2023-04-27T14:16:39.057241Z","shell.execute_reply.started":"2023-04-27T14:16:32.851952Z","shell.execute_reply":"2023-04-27T14:16:39.056349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train data set \n\nTrain_Dataset = tf.data.Dataset.zip((Day_Dataset,Night_Dataset))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:16:43.647035Z","iopub.execute_input":"2023-04-27T14:16:43.647972Z","iopub.status.idle":"2023-04-27T14:16:43.654919Z","shell.execute_reply.started":"2023-04-27T14:16:43.647923Z","shell.execute_reply":"2023-04-27T14:16:43.653985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:green'> Building Model</h2>\n","metadata":{}},{"cell_type":"markdown","source":"**Upsampling and downsampling blocks**","metadata":{}},{"cell_type":"code","source":"\n#conv weights initilaizer\nconv_initializer = tf.random_normal_initializer(mean=0.0,\n                                                stddev=0.02)\n\n#init for intance normalization\ngamma_initializer = tf.keras.initializers.RandomNormal(mean=0.0, \n                                                       stddev=0.02)\n    \n    \n    \n    \ndef downsample(input_layer,\n               filters,\n               name,\n               size=3, \n               strides=2, \n               activation=tf.keras.layers.ReLU(), \n               ):\n    \n    '''perform a downsampling by applying a convolution,followed by instance norm and activation'''\n    conv = tf.keras.layers.Conv2D(filters, \n                                  size, \n                                  strides=strides, \n                                  padding='same', \n                                  use_bias=False, \n                                  kernel_initializer=conv_initializer, \n                                  name=f'encoder_{name}')(input_layer)\n\n    \n    conv = tfa.layers.InstanceNormalization(axis=-1,gamma_initializer=gamma_initializer)(conv)\n        \n    conv = activation(conv)\n\n    return conv\n\n\ndef upsample(input_layer,\n             filters,\n             name,\n             size=3,\n             strides=2,\n             activation='relu'):\n    \n    res = tf.keras.layers.Conv2DTranspose(filters, size, \n                                          strides=strides, \n                                          padding='same', \n                                          use_bias=False, \n                                          kernel_initializer=conv_initializer, \n                                          name=f'decoder_{name}')(input_layer)\n\n    res = tfa.layers.InstanceNormalization(gamma_initializer=gamma_initializer)(res)\n\n    res =  tf.keras.layers.Activation(activation)(res)\n    \n    return res","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:18.461786Z","iopub.execute_input":"2023-04-27T14:17:18.462178Z","iopub.status.idle":"2023-04-27T14:17:18.488567Z","shell.execute_reply.started":"2023-04-27T14:17:18.462143Z","shell.execute_reply":"2023-04-27T14:17:18.487403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Residual block**","metadata":{}},{"cell_type":"code","source":"\ndef residual_block(input_layer, \n                   size=3, \n                   strides=1, \n                   name='block_x'):\n    '''performs 2 convolutions followed by an added skip connection with the input'''\n    \n    \n    filters = input_layer.shape[-1]\n    block = tf.keras.layers.Conv2D(filters, \n                     size,\n                     strides=strides,\n                     padding='same',\n                     use_bias=False, \n                     kernel_initializer=conv_initializer,\n                     name=f'residual_{name}')(input_layer)\n    \n    block = tf.keras.layers.Activation('relu')(block)\n    block = tf.keras.layers.Conv2D(filters, size, strides=strides, padding='same', use_bias=False, \n                     kernel_initializer=conv_initializer, name=f'transformer_{name}_2')(block)    \n    \n    #skip connection\n    res = tf.keras.layers.Add()([block, input_layer])\n\n    return res\n\n\ndef concat_layer(layer_1,layer_2,name):\n    '''concatenation of layers for skip connections'''\n    return tf.keras.layers.Concatenate(name=name)([layer_1,layer_2])\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:26.874286Z","iopub.execute_input":"2023-04-27T14:17:26.874647Z","iopub.status.idle":"2023-04-27T14:17:26.882535Z","shell.execute_reply.started":"2023-04-27T14:17:26.874615Z","shell.execute_reply":"2023-04-27T14:17:26.881432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3 style='color:lightgreen'> Building Generator</h3>\n","metadata":{}},{"cell_type":"code","source":"def get_generator(num_residual_connections=6):\n    \n    input_ = tf.keras.layers.Input(shape=(CFG.IMG_WIDTH,CFG.IMG_HEIGHT,3), \n                                   name='input_layer')\n    \n    #-----------------------ENCODER-------------------------------\n    #downsample images \n    enc1 = downsample(input_layer = input_, filters=64,  strides =  1, size=7, name='dwn_1')    # (bs, 512,512, 64)\n    enc2 = downsample(input_layer=enc1,filters= 128,size =  3, strides =  2, name='dwn_2')      # (bs, 256, 256, 128)\n    enc3 = downsample(input_layer=enc2, filters=256,size =  3, strides =2, name='dwn_3')        # (bs, 128,128,256)\n    enc4 = downsample(input_layer=enc3, filters=256,size =  3, strides =2, name='dwn_4')        # (bs, 64,64,256)\n    \n    \n    #-----------------------Residual connections-------------------------------\n    x = enc4\n    for n in range(num_residual_connections):\n        x = residual_block(input_layer=x, name=f'res_block_{n+1}')     # (bs, 64, 64, 256)\n\n    #-----------------------DECODER-------------------------------\n    #UNET like skip connection \n    #upsample 1\n    x_skip = concat_layer(layer_1=x,layer_2=enc4,name='skip_1')               \n    dec1 = upsample(x_skip,filters=256 ,name='upsam_1')  # (bs, 128, 128, 256)\n    \n    #upsample 2\n    x_skip = concat_layer(layer_1=dec1,layer_2=enc3,name='skip_2')               \n    dec_2 = upsample(x_skip, filters=128,name='upsam_2') # (bs, 256, 256, 128)\n       \n    #upsample 3\n    x_skip = concat_layer(layer_1=dec_2,layer_2=enc2,name='skip_3')               \n    dec_3 = upsample(x_skip, filters= 64,name='upsam_3') # (bs, 512, 512, 64)\n    \n    #penultimate\n    x_skip = concat_layer(layer_1=dec_3,\n                          layer_2=enc1,\n                          name='skip_final')\n\n    output = tf.keras.layers.Conv2D(filters = 3,kernel_size = 7, strides=1, padding='same', \n                                  kernel_initializer=conv_initializer, use_bias=False, activation='tanh', \n                                  name='output_layer')(x_skip) \n\n    \n    return tf.keras.models.Model(inputs=input_,outputs=output)\n\n\n\n\n# day images -> night images \nday2night_gen = get_generator()\n\n# night images -> day images  \nnight2day_gen = get_generator()\n\n\n#plot model\n# tf.keras.utils.plot_model(day2night_gen)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:33.563135Z","iopub.execute_input":"2023-04-27T14:17:33.563495Z","iopub.status.idle":"2023-04-27T14:17:34.536993Z","shell.execute_reply.started":"2023-04-27T14:17:33.563464Z","shell.execute_reply":"2023-04-27T14:17:34.536059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#passing in a input to generator for check \n#plot a sample output\ngen_output = night2day_gen(inp_img, training=False)[0]\nplt.subplots(1,2,figsize=(16,8))\n\n\nplt.subplot(1,2,1)\nplt.imshow(gen_output.numpy().squeeze())\nplt.title('Untrained Night2Day Generator output')\nplt.axis('off')\n\n\nplt.subplot(1,2,2)\nplt.imshow(de_normalize(inp_img[0]))\nplt.title('Original Night image')\nplt.axis('off')\n\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:36.413947Z","iopub.execute_input":"2023-04-27T14:17:36.414651Z","iopub.status.idle":"2023-04-27T14:17:44.226714Z","shell.execute_reply.started":"2023-04-27T14:17:36.414614Z","shell.execute_reply":"2023-04-27T14:17:44.225882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3 style='color:green'> Building Discriminator</h3>\n","metadata":{}},{"cell_type":"code","source":"\n\ndef PATCH_discriminator(leak_rate = 0.2):\n    '''PATCH discriminator network'''\n    leaky_relu = tf.keras.layers.LeakyReLU(leak_rate)\n\n    \n    input_ = tf.keras.layers.Input(shape=(CFG.IMG_WIDTH,CFG.IMG_HEIGHT,3), \n                               name='input_layer')\n    # Encoder    \n    # Input image 512,512\n    x = downsample(input_layer = input_, filters=64,  strides =  2, size=4, name='dwn_1',activation = leaky_relu)    #h,w =256\n    x = downsample(input_layer = x, filters=128,  strides =  2, size=4, name='dwn_2',activation = leaky_relu)        #h,w =128\n    x = downsample(input_layer = x, filters=256,  strides =  2, size=4, name='dwn_3',activation = leaky_relu)        #h,w = 64\n    x = downsample(input_layer = x, filters=512,  strides =  2, size=4, name='dwn_4',activation = leaky_relu)        #h,w = 32\n    x = downsample(input_layer = x, filters=512,  strides =  1, size=4, name='dwn_5',activation = leaky_relu)        #h,w = 32\n    \n    \n    output = tf.keras.layers.Conv2D(1, 4, strides=1, padding='valid', kernel_initializer=conv_initializer)(x)         #(29, 29, 1)\n    \n    return tf.keras.models.Model(inputs=input_,outputs=output)\n\n\n\n#create instance of discriminators \nday2night_disc = PATCH_discriminator()  # identify night images\nnight2day_disc = PATCH_discriminator()  # identify day images\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:44.228716Z","iopub.execute_input":"2023-04-27T14:17:44.22932Z","iopub.status.idle":"2023-04-27T14:17:44.512866Z","shell.execute_reply.started":"2023-04-27T14:17:44.229286Z","shell.execute_reply":"2023-04-27T14:17:44.511943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#check on dicriminator \n\ndisc_output = day2night_disc(inp_img, training=False)\nplt.subplots(1,1,figsize=(8,8))\n\nplt.imshow(disc_output.numpy().mean(axis=0),cmap='gray')\nplt.title('Untrained Night2Day disc output')\nplt.axis('off')\n\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:44.51446Z","iopub.execute_input":"2023-04-27T14:17:44.514818Z","iopub.status.idle":"2023-04-27T14:17:44.771425Z","shell.execute_reply.started":"2023-04-27T14:17:44.514784Z","shell.execute_reply":"2023-04-27T14:17:44.770398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generate_cycle(gen_1,gen_2,input_image):\n    '''generate a full cycle of images using given generators'''\n    gen_img_1 = gen_1(input_image,training=True)\n    gen_img_2 = gen_2(gen_img_1,training=True)\n    \n    return gen_img_1,gen_img_2\n\n\ndef calc_and_apply_gradients(tape,\n                             model,\n                             loss,\n                             optimizer):\n    '''Apply gradients for a given model using given optimizer'''\n    \n    #calculate gradients of loss function\n    gradients = tape.gradient(loss,model.trainable_variables)\n    \n    #apply gradients \n    optimizer.apply_gradients(zip(gradients,model.trainable_variables))\n    return ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:44.773639Z","iopub.execute_input":"2023-04-27T14:17:44.774567Z","iopub.status.idle":"2023-04-27T14:17:44.783778Z","shell.execute_reply.started":"2023-04-27T14:17:44.774529Z","shell.execute_reply":"2023-04-27T14:17:44.782467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3 style='color:green' >losses </h3>","metadata":{}},{"cell_type":"code","source":"def discriminator_loss(real, generated):\n    '''discriminator Binary CrossEntropy loss'''\n    real_loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)(tf.ones_like(real), real)\n\n    generated_loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)(tf.zeros_like(generated), generated)\n\n    total_disc_loss = real_loss + generated_loss\n\n    return total_disc_loss * 0.5\n\n# Generator Adverserial loss\ndef generator_loss(generated):\n    '''adverserial generator loss (BCE)'''\n    return tf.keras.losses.BinaryCrossentropy(from_logits=True)(tf.ones_like(generated), generated)\n\n    \n# Cycle consistency loss \n    \ndef calc_cycle_loss(real_image, cycled_image, LAMBDA):\n    '''pixel wise cycle loss between original image and cycled image'''\n    mae_loss = tf.reduce_mean(tf.abs(real_image - cycled_image))\n\n    return LAMBDA * mae_loss\n\n\n# identity loss\ndef identity_loss(real_image, same_image, LAMBDA):    \n    mae_loss = tf.reduce_mean(tf.abs(real_image - same_image))\n    return LAMBDA * 0.5 * mae_loss","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:17:57.21163Z","iopub.execute_input":"2023-04-27T14:17:57.211994Z","iopub.status.idle":"2023-04-27T14:17:57.220118Z","shell.execute_reply.started":"2023-04-27T14:17:57.211961Z","shell.execute_reply":"2023-04-27T14:17:57.21891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:green'>Cycle GAN</h2>\n","metadata":{}},{"cell_type":"code","source":"class CycleGAN(tf.keras.models.Model):\n    def __init__(self,\n                 lambda_cycle=10):\n        super(CycleGAN, self).__init__()\n        self.gen_d2n = day2night_gen # Day -> Night \n        self.gen_n2d = night2day_gen # Night -> Day\n        self.disc_d2n = day2night_disc # Classifies Night Images\n        self.disc_n2d = night2day_disc # Classifier Day Images \n        self.lambda_cycle = lambda_cycle #lambda in cycle consistancy loss\n        \n        \n    \n    def compile(self,\n                gen_loss_fn,\n                disc_loss_fn,\n                cycle_loss_fn,\n                identity_loss_fn,\n                common_opt = tf.keras.optimizers.Adam(learning_rate = CFG.learning_rate,beta_1 = 0.5)):\n        \n        super(CycleGAN, self).compile()\n        \n        # -------optimizers ---------\n        self.opt_gen_d2n = common_opt\n        self.opt_gen_n2d = common_opt\n        self.opt_disc_d2n = common_opt\n        self.opt_disc_n2d = common_opt\n        \n        \n        # -------losses ---------\n        self.gen_loss_fn = gen_loss_fn\n        self.disc_loss_fn = disc_loss_fn\n        self.cycle_loss_fn = cycle_loss_fn\n        self.identity_loss_fn = identity_loss_fn\n        \n        \n    def train_step(self, batch_data):\n        day_image, night_image = batch_data\n        \n        with tf.GradientTape(persistent=True) as tape:\n            \n            #-----day->night->day\n            fake_night,cycled_day = generate_cycle(self.gen_d2n,\n                                                     self.gen_n2d,\n                                                     day_image)\n                 \n\n            # --------night -> day- > night\n            fake_day,cycled_night = generate_cycle(self.gen_n2d,\n                                                   self.gen_d2n,\n                                                   night_image)\n            \n            #---------- generating itself (for identity loss)\n            iden_day = self.gen_d2n(night_image, training=True)\n            iden_night = self.gen_n2d(day_image, training=True)\n\n            # -----------discriminator on real images\n            disc_night = self.disc_d2n(night_image, training=True)\n            disc_day = self.disc_n2d(day_image, training=True)\n\n            # -----------discriminator on fake images-----------------\n            disc_fake_night   = self.disc_d2n(fake_night, training=True)\n            disc_fake_day = self.disc_n2d(fake_day, training=True)\n\n            # -------------------------generator loss-------------\n               #---1)adverserial loss\n            night_gen_loss = self.gen_loss_fn(disc_fake_night) \n            day_gen_loss = self.gen_loss_fn(disc_fake_day)\n\n                #---2)Cycle loss loss\n            total_cycle_loss = self.cycle_loss_fn(night_image, cycled_night, self.lambda_cycle) + self.cycle_loss_fn(day_image, cycled_day, self.lambda_cycle)\n\n                # +++++3) Total Gen loss (day gen and night gen)\n            total_gen_d2n_loss = night_gen_loss + total_cycle_loss + self.identity_loss_fn(night_image, iden_night,self.lambda_cycle)\n            total_gen_n2d_loss = day_gen_loss + total_cycle_loss + self.identity_loss_fn(day_image, iden_day, self.lambda_cycle)\n            \n            \n            # -------------------------Discriminator loss-------------\n            night_disc_loss = self.disc_loss_fn(disc_night, disc_fake_night)  # check classifying generated and real night\n            day_disc_loss = self.disc_loss_fn(disc_day, disc_fake_day)        # check  classifying generated and real day\n\n        ## ------------------------- Calculating and Updating gradients------------------\n        \n        # day->night gen gradeints\n        _ = calc_and_apply_gradients(tape=tape,\n                                     model= self.gen_d2n,\n                                     loss = total_gen_d2n_loss,\n                                     optimizer = self.opt_gen_d2n)\n        \n        # night - >day  gen gradeints\n        _ = calc_and_apply_gradients(tape=tape,\n                                     model= self.gen_n2d,\n                                     loss = total_gen_n2d_loss,\n                                     optimizer = self.opt_gen_n2d)\n        \n        #  discrim gradients (classifies night images)\n        _ = calc_and_apply_gradients(tape=tape,\n                                     model= self.disc_d2n,\n                                     loss = night_disc_loss,\n                                     optimizer = self.opt_disc_d2n)\n        \n        # Day discrim gradients (classifies day images)\n        _ = calc_and_apply_gradients(tape=tape,\n                                     model= self.disc_n2d,\n                                     loss = day_disc_loss,\n                                     optimizer = self.opt_disc_n2d)\n        \n        \n        return {'gen_D2N_loss': total_gen_d2n_loss,\n                'gen_N2D_loss': total_gen_n2d_loss,\n                'disc_day_loss': day_disc_loss,\n                'disc_night_loss': night_disc_loss\n               }\n        \n    \n        ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:18:05.123685Z","iopub.execute_input":"2023-04-27T14:18:05.124077Z","iopub.status.idle":"2023-04-27T14:18:05.141437Z","shell.execute_reply.started":"2023-04-27T14:18:05.124022Z","shell.execute_reply":"2023-04-27T14:18:05.140499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#creat a instance of Cycle gan \ngan = CycleGAN()\n\n\n#complie with the losses \ngan.compile(gen_loss_fn=generator_loss,\n            disc_loss_fn=discriminator_loss,\n            cycle_loss_fn=calc_cycle_loss,\n            identity_loss_fn=identity_loss)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:18:06.621785Z","iopub.execute_input":"2023-04-27T14:18:06.622164Z","iopub.status.idle":"2023-04-27T14:18:06.642321Z","shell.execute_reply.started":"2023-04-27T14:18:06.622129Z","shell.execute_reply":"2023-04-27T14:18:06.641383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3 style='color:green'>Callbacks</h3>\n\n        For reducing Learning Rate,stopping training and Visulization","metadata":{}},{"cell_type":"code","source":"#learning rate schedule \n\ndef scheduler(epoch, \n              lr,\n              decay_rate = 0.05,\n              warm_up_period = 10):\n    \n    if epoch < warm_up_period:\n        return lr\n    elif (epoch > warm_up_period and epoch<40):\n        return lr * tf.math.exp(decay_rate)\n    else:\n        return lr * tf.math.exp(decay_rate*2)\n        \n    \n    \n    \nlr_scheduler = tf.keras.callbacks.LearningRateScheduler(scheduler,\n                                                        verbose = 0)\n\n\n#early stopping \n\n# early_stop = tf.keras.callbacks.EarlyStopping(monitor = 'gen_N2D_loss',\n#                                               mode = 'min',\n#                                               patience = 10,\n#                                              restore_best_weights = True)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:18:16.418725Z","iopub.execute_input":"2023-04-27T14:18:16.419111Z","iopub.status.idle":"2023-04-27T14:18:16.426085Z","shell.execute_reply.started":"2023-04-27T14:18:16.419073Z","shell.execute_reply":"2023-04-27T14:18:16.424916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# early stopping : from https://stackoverflow.com/questions/64556120/early-stopping-with-multiple-conditions\n\nclass CustomEarlyStopping(tf.keras.callbacks.Callback):\n    def __init__(self, patience=0):\n        super(CustomEarlyStopping, self).__init__()\n        self.patience = patience\n        self.best_weights = None\n        \n    def on_train_begin(self, logs=None):\n        \n        # The number of epoch it has waited when loss is no longer minimum.\n        self.wait = 0\n        # The epoch the training stops at.\n        self.stopped_epoch = 0\n        # Initialize the best as infinity.\n        self.n2d_loss = np.Inf\n        self.d2n_loss = np.Inf\n\n    def on_epoch_end(self, epoch, logs=None): \n        n2d_loss=logs.get('gen_N2D_loss')\n        d2n_loss=logs.get('gen_D2N_loss')\n\n        # If both the conditions are met, continue training\n        if (np.less(n2d_loss, self.n2d_loss) and np.less(d2n_loss, self.d2n_loss)):\n            self.d2n_loss = d2n_loss\n            self.n2d_loss = n2d_loss\n            self.wait = 0\n            # Record the best weights if current results is better (less).\n            self.best_weights = self.model.get_weights()\n            \n        # if above xondition not met, continue training till patiance epochs\n        else:\n            self.wait += 1\n            if self.wait >= self.patience:\n                self.stopped_epoch = epoch\n                self.model.stop_training = True\n                print(\"Restoring model weights from the end of the best epoch.\")\n                self.model.set_weights(self.best_weights)\n                \n    def on_train_end(self, logs=None):\n        if self.stopped_epoch > 0:\n            print(\"Epoch %05d: early stopping\" % (self.stopped_epoch + 1))\n","metadata":{"execution":{"iopub.status.busy":"2023-04-27T14:18:17.747306Z","iopub.execute_input":"2023-04-27T14:18:17.747671Z","iopub.status.idle":"2023-04-27T14:18:17.758675Z","shell.execute_reply.started":"2023-04-27T14:18:17.747639Z","shell.execute_reply":"2023-04-27T14:18:17.757524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#--------------------------------------Viz Callbacks : from https://www.kaggle.com/code/dimitreoliveira/improving-cyclegan-monet-paintings -----------------------------------------\ndef display_samples(ds, n_samples):\n    ds_iter = iter(ds)\n    for n_sample in range(n_samples):\n        example_sample = next(ds_iter)\n        plt.subplot(121)\n        plt.imshow(example_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        plt.show()\n        \ndef display_generated_samples(ds, model, n_samples):\n    ds_iter = iter(ds)\n    for n_sample in range(n_samples):\n        example_sample = next(ds_iter)\n        generated_sample = model.predict(example_sample)\n        \n        f = plt.figure(figsize=(16,8))\n        \n        plt.subplot(121)\n        plt.title('Input image')\n        plt.imshow(example_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        \n        plt.subplot(122)\n        plt.title('Generated image')\n        plt.imshow(generated_sample[0] * 0.5 + 0.5)\n        plt.axis('off')\n        plt.show()\n        \ndef evaluate_cycle(ds, generator_a, generator_b, n_samples=1):\n    fig, axes = plt.subplots(n_samples, 3, figsize=(22, (n_samples*6)))\n    axes = axes.flatten()\n    \n    ds_iter = iter(ds)\n    for n_sample in range(n_samples):\n        idx = n_sample*3\n        example_sample = next(ds_iter)\n        generated_a_sample = generator_a.predict(example_sample)\n        generated_b_sample = generator_b.predict(generated_a_sample)\n        \n        axes[idx].set_title('Input image', fontsize=18)\n        axes[idx].imshow(example_sample[0] * 0.5 + 0.5)\n        axes[idx].axis('off')\n        \n        axes[idx+1].set_title('Generated image', fontsize=18)\n        axes[idx+1].imshow(generated_a_sample[0] * 0.5 + 0.5)\n        axes[idx+1].axis('off')\n        \n        axes[idx+2].set_title('Cycled image', fontsize=18)\n        axes[idx+2].imshow(generated_b_sample[0] * 0.5 + 0.5)\n        axes[idx+2].axis('off')\n        \n    plt.show()\n        \ndef predict_and_save(input_ds, generator_model, output_path):\n    i = 1\n    for img in input_ds:\n        prediction = generator_model(img, training=False)[0].numpy() # make predition\n        prediction = (prediction * 127.5 + 127.5).astype(np.uint8)   # re-scale\n        im = PIL.Image.fromarray(prediction)\n        im.save(f'{output_path}{str(i)}.jpg')\n        i += 1\n\n# Callback\nclass GANMonitor(tf.keras.callbacks.Callback):\n    \"\"\"A callback to generate and save images after each epoch\"\"\"\n\n    def __init__(self, \n                 num_img=1, \n                 day_paths='generated_day', \n                 night_paths='generated_night'):\n        self.num_img = num_img\n        self.day_paths = day_paths\n        self.night_paths = night_paths\n        \n        # dir to save genereated day images\n        if not os.path.exists(self.day_paths):\n            os.makedirs(self.day_paths)\n            \n            \n        # dir to save genereated night images\n        if not os.path.exists(self.night_paths):\n            os.makedirs(self.night_paths)\n\n            \n            \n    def on_epoch_end(self, epoch, logs=None):\n        #generated night \n        for i, img in enumerate(Day_eval.take(self.num_img)):\n            \n            \n            prediction = day2night_gen(img, training=False)[0].numpy()\n            prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n            prediction = PIL.Image.fromarray(prediction)\n            prediction.save(f'{self.night_paths}/generated_{i}_{epoch+1}.png')\n            \n        # generated day images \n        for i, img in enumerate(Night_eval.take(self.num_img)):\n            prediction = night2day_gen(img, training=False)[0].numpy()\n            prediction = (prediction * 127.5 + 127.5).astype(np.uint8)\n            prediction = PIL.Image.fromarray(prediction)\n            prediction.save(f'{self.day_paths}/generated_{i}_{epoch+1}.png')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T14:18:19.20883Z","iopub.execute_input":"2023-04-27T14:18:19.20921Z","iopub.status.idle":"2023-04-27T14:18:19.2286Z","shell.execute_reply.started":"2023-04-27T14:18:19.209176Z","shell.execute_reply":"2023-04-27T14:18:19.227639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:green'>Fitting the model</h2>\n","metadata":{}},{"cell_type":"code","source":"EPOCHS = 10\ncallbacks = [lr_scheduler,GANMonitor(),CustomEarlyStopping(patience = 10)]\nsteps_per_epoch = 200\n\n\nhistory = gan.fit(Train_Dataset,\n                epochs = EPOCHS,\n                steps_per_epoch=steps_per_epoch,\n                callbacks = callbacks)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T14:18:36.911847Z","iopub.execute_input":"2023-04-27T14:18:36.912227Z","iopub.status.idle":"2023-04-27T15:36:35.152993Z","shell.execute_reply.started":"2023-04-27T14:18:36.912193Z","shell.execute_reply":"2023-04-27T15:36:35.151956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:green'>Visualizing Training Progress</h2>","metadata":{}},{"cell_type":"markdown","source":"<h3 style='color:lightgreen'> Visualizing Training Progress for Night -> Day generator</h3>\n\n","metadata":{}},{"cell_type":"code","source":"\n\n# from https://www.kaggle.com/code/dimitreoliveira/improving-cyclegan-monet-paintings\ndef create_gif(images_path, gif_path):\n    images = []\n    filenames = glob(images_path)\n    filenames.sort(key=lambda x: int(''.join(filter(str.isdigit, x))))\n    for epoch, filename in enumerate(filenames):\n        img = PIL.ImageDraw.Image.open(filename)\n        ImageDraw.Draw(img).text((0, 0),  # Coordinates\n                                 f'Epoch {epoch+1}')\n        images.append(img)\n    imageio.mimsave(gif_path, images, fps=2) # Save gif\n    \n    \n    \ncreate_gif('./generated_day/*.png', 'day.gif')\n\nprint('Training progress for Night -> Day Generator')\ndisplay.Image('./day.gif')","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:04:51.418885Z","iopub.execute_input":"2023-04-27T16:04:51.419273Z","iopub.status.idle":"2023-04-27T16:05:26.312027Z","shell.execute_reply.started":"2023-04-27T16:04:51.419239Z","shell.execute_reply":"2023-04-27T16:05:26.311096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<iframe src=\"./day.gif\" height=\"300\" \n        style=\"margin: 0 auto; width: 100%; max-width: 950px;\" frameborder=\"0\" scrolling=\"auto\" title=\"Training Progress - Day\"></iframe>","metadata":{}},{"cell_type":"markdown","source":"<h3 style='color:lightgreen'> Visualizing Training Progress for Day -> Night generator</h3>\n","metadata":{}},{"cell_type":"code","source":"create_gif('./generated_night/*.png', 'night.gif')\n\n\nprint('Training progress for Day-> Generator')\ndisplay.Image('./night.gif')","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:05:42.611079Z","iopub.execute_input":"2023-04-27T16:05:42.611459Z","iopub.status.idle":"2023-04-27T16:05:45.159925Z","shell.execute_reply.started":"2023-04-27T16:05:42.611427Z","shell.execute_reply":"2023-04-27T16:05:45.158492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h1 style='color:green'>Results</h1>\n","metadata":{}},{"cell_type":"markdown","source":"<h2 style='color:lightgreen'>Evaluating Day -> Night Generator</h2>\n","metadata":{}},{"cell_type":"code","source":"display_generated_samples(Day_eval.take(2), day2night_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:06:09.858645Z","iopub.execute_input":"2023-04-27T16:06:09.859033Z","iopub.status.idle":"2023-04-27T16:06:15.960313Z","shell.execute_reply.started":"2023-04-27T16:06:09.858997Z","shell.execute_reply":"2023-04-27T16:06:15.959094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Day_eval.take(2), day2night_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:06:20.911673Z","iopub.execute_input":"2023-04-27T16:06:20.912034Z","iopub.status.idle":"2023-04-27T16:06:27.483991Z","shell.execute_reply.started":"2023-04-27T16:06:20.912002Z","shell.execute_reply":"2023-04-27T16:06:27.483078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Day_eval.take(2), day2night_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:06:31.407145Z","iopub.execute_input":"2023-04-27T16:06:31.40751Z","iopub.status.idle":"2023-04-27T16:06:37.213807Z","shell.execute_reply.started":"2023-04-27T16:06:31.407479Z","shell.execute_reply":"2023-04-27T16:06:37.212858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:lightgreen'>Evaluating Night -> Day Generator</h2>\n","metadata":{}},{"cell_type":"code","source":"display_generated_samples(Night_eval.take(2), night2day_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:06:45.749836Z","iopub.execute_input":"2023-04-27T16:06:45.750223Z","iopub.status.idle":"2023-04-27T16:06:55.99516Z","shell.execute_reply.started":"2023-04-27T16:06:45.750187Z","shell.execute_reply":"2023-04-27T16:06:55.994076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Night_eval.take(2), night2day_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:07:02.276117Z","iopub.execute_input":"2023-04-27T16:07:02.277307Z","iopub.status.idle":"2023-04-27T16:07:12.521556Z","shell.execute_reply.started":"2023-04-27T16:07:02.277259Z","shell.execute_reply":"2023-04-27T16:07:12.520561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Night_eval.take(2), night2day_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:07:12.524294Z","iopub.execute_input":"2023-04-27T16:07:12.524756Z","iopub.status.idle":"2023-04-27T16:07:22.769726Z","shell.execute_reply.started":"2023-04-27T16:07:12.524714Z","shell.execute_reply":"2023-04-27T16:07:22.76872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:lightgreen'>Evaluating Identity for Day to Night Generator so that Night -> Night </h2>\n","metadata":{}},{"cell_type":"code","source":"display_generated_samples(Night_eval.take(2), day2night_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:08:20.773243Z","iopub.execute_input":"2023-04-27T16:08:20.773615Z","iopub.status.idle":"2023-04-27T16:08:26.777848Z","shell.execute_reply.started":"2023-04-27T16:08:20.773585Z","shell.execute_reply":"2023-04-27T16:08:26.776883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Night_eval.take(2), day2night_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:08:34.478566Z","iopub.execute_input":"2023-04-27T16:08:34.478937Z","iopub.status.idle":"2023-04-27T16:08:44.723Z","shell.execute_reply.started":"2023-04-27T16:08:34.478905Z","shell.execute_reply":"2023-04-27T16:08:44.721918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Night_eval.take(2), day2night_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:09:12.302557Z","iopub.execute_input":"2023-04-27T16:09:12.303078Z","iopub.status.idle":"2023-04-27T16:09:22.547743Z","shell.execute_reply.started":"2023-04-27T16:09:12.303014Z","shell.execute_reply":"2023-04-27T16:09:22.546672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:lightgreen'>Evaluating Identity for Night to Day Generator so that Day -> Day </h2>\n","metadata":{}},{"cell_type":"code","source":"display_generated_samples(Day_eval.take(2), night2day_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:09:26.114581Z","iopub.execute_input":"2023-04-27T16:09:26.114942Z","iopub.status.idle":"2023-04-27T16:09:31.842706Z","shell.execute_reply.started":"2023-04-27T16:09:26.114908Z","shell.execute_reply":"2023-04-27T16:09:31.841866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Day_eval.take(2), night2day_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:09:37.725116Z","iopub.execute_input":"2023-04-27T16:09:37.725485Z","iopub.status.idle":"2023-04-27T16:09:47.971481Z","shell.execute_reply.started":"2023-04-27T16:09:37.725447Z","shell.execute_reply":"2023-04-27T16:09:47.970442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_generated_samples(Day_eval.take(2), night2day_gen, 2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:09:47.973981Z","iopub.execute_input":"2023-04-27T16:09:47.974656Z","iopub.status.idle":"2023-04-27T16:09:58.223679Z","shell.execute_reply.started":"2023-04-27T16:09:47.974614Z","shell.execute_reply":"2023-04-27T16:09:58.222662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:lightgreen'>Cycle : Day(real image) -> Night -> Day</h2>\n","metadata":{}},{"cell_type":"code","source":"evaluate_cycle(Day_eval.take(2),\n               day2night_gen, \n               night2day_gen, \n               n_samples=2)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-04-27T16:09:58.228195Z","iopub.execute_input":"2023-04-27T16:09:58.228516Z","iopub.status.idle":"2023-04-27T16:10:04.366132Z","shell.execute_reply.started":"2023-04-27T16:09:58.228488Z","shell.execute_reply":"2023-04-27T16:10:04.365186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_cycle(Day_eval.take(2),\n               day2night_gen, \n               night2day_gen, \n               n_samples=2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:10:04.367821Z","iopub.execute_input":"2023-04-27T16:10:04.368744Z","iopub.status.idle":"2023-04-27T16:10:10.549342Z","shell.execute_reply.started":"2023-04-27T16:10:04.368707Z","shell.execute_reply":"2023-04-27T16:10:10.548221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 style='color:lightgreen'>Cycle : Day(real image) -> Night -> Day</h2>\n","metadata":{}},{"cell_type":"code","source":"evaluate_cycle(Night_eval.take(2),\n               night2day_gen, \n               day2night_gen, \n               n_samples=2)\n","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:10:35.117237Z","iopub.execute_input":"2023-04-27T16:10:35.117699Z","iopub.status.idle":"2023-04-27T16:10:41.748325Z","shell.execute_reply.started":"2023-04-27T16:10:35.117659Z","shell.execute_reply":"2023-04-27T16:10:41.747408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_cycle(Night_eval.take(2),\n               night2day_gen, \n               day2night_gen, \n               n_samples=2)","metadata":{"execution":{"iopub.status.busy":"2023-04-27T16:10:41.750301Z","iopub.execute_input":"2023-04-27T16:10:41.750875Z","iopub.status.idle":"2023-04-27T16:10:47.562374Z","shell.execute_reply.started":"2023-04-27T16:10:41.750841Z","shell.execute_reply":"2023-04-27T16:10:47.561455Z"},"trusted":true},"execution_count":null,"outputs":[]}]}