{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"#Generating lists of masks and images.\nimport os\nimport cv2\nmask_list = []\nimage_list = []\n\n#Mask path \nfor (root,dirs,files) in os.walk('../input/256hubmap/masks'):\n    mask_list = files\nmask_list.sort()\nfor index,element in enumerate(mask_list):\n    mask_list[index] = os.path.join('../input/256hubmap/masks',element)\n\n#image path    \nfor (_,_,files) in os.walk('../input/256hubmap/train'):\n    image_list= files\nimage_list.sort()\nfor index,element in enumerate(image_list):\n    image_list[index] = os.path.join('../input/256hubmap/train',element)\n    \n    \nprint(len(mask_list))\nprint(len(image_list))\n#print(mask_list[:4])\n#print(image_list[:4])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#DATA\nimport numpy as np\nfrom sklearn.model_selection import train_test_split\nimport tensorflow as tf\nimport cv2\nimport multiprocessing\n\nH = 256\nW = 256\n\n#checking number of availabe CPU cores\nnum_cores = multiprocessing.cpu_count()\nprint(num_cores)\n\n    \ndef load_data():\n    '''Loads the data and creates training validation and test lists of paths.\n    '''\n    train_x, valid_x = train_test_split(image_list, test_size=0.1, random_state=42)\n    train_y, valid_y = train_test_split(mask_list, test_size=0.1, random_state=42)\n    \n    train_x ,test_x = train_test_split(image_list,test_size=0.125,random_state=42)\n    train_y ,test_y = train_test_split(mask_list,test_size=0.125,random_state=42)    \n    \n    return (train_x, train_y), (valid_x, valid_y), (test_x, test_y)\n\ndef read_image(x):\n    '''Function reads the image resizes , normalizes and converts into float32.'''\n    x = cv2.imread(x, cv2.IMREAD_COLOR)\n    #x = cv2.resize(x, (W, H))\n    x = x / 255.0\n    x = x.astype(np.float32)\n    return x\n\ndef read_mask(x):\n    '''Function reads the mask as a greyscale image , resizes n subtracts 1 from each pixel value to match the class.\n    '''\n    x = cv2.imread(x, cv2.IMREAD_GRAYSCALE)\n    #x = cv2.resize(x, (W, H))\n    #x = x - 1\n    x = x.astype(np.int32)\n    return x\n\ndef tf_dataset(x, y, batch=8):\n    '''Function creates a tfds dataset using method from_tensor_slices,\n    preprocesses the dataset by shuffling mapping the preprocess function and creating batches\n    '''\n    dataset = tf.data.Dataset.from_tensor_slices((x, y))\n    dataset = dataset.cache()\n    dataset = dataset.shuffle(buffer_size=1000)\n    dataset = dataset.map(preprocess,num_parallel_calls = tf.data.experimental.AUTOTUNE)\n    dataset = dataset.batch(batch)\n    dataset = dataset.repeat()\n    dataset = dataset.prefetch(buffer_size = tf.data.experimental.AUTOTUNE)\n    return dataset\n\ndef preprocess(x, y):\n    def f(x, y):\n        x = x.decode()\n        y = y.decode()\n\n        image = read_image(x)\n        mask = read_mask(y)\n\n        return image, mask\n\n    image, mask = tf.numpy_function(f, [x, y], [tf.float32, tf.int32])\n    #mask = tf.one_hot(mask,2, dtype=tf.int32)\n    mask = tf.reshape(mask,[256,256,1])\n    image.set_shape([H, W, 3])\n    #mask.set_shape([H, W, 1])\n\n    return image, mask\n\n\n(train_x, train_y), (valid_x, valid_y), (test_x, test_y) = load_data()\nprint(f\"Dataset: Train: {len(train_x)} - Valid: {len(valid_x)} - Test: {len(test_x)}\")\n\n#dataset = tf_dataset(train_x, train_y, batch=8)\n#dataset = tf_dataset(train_x, train_y,batch=16)\n# for x, y in dataset:\n#     print(x.shape, y.shape) ## (8, 256, 256, 3), (8, 256, 256, 2)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import tensorflow as tf\n\n\n# IMG_WIDTH = 256\n# IMG_HEIGHT = 256\n# IMG_CHANNELS = 3\n\n\n# #Build the model\n# inputs = tf.keras.layers.Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\n# s = tf.keras.layers.Lambda(lambda x: x / 255)(inputs)\n\n# #Contraction path\n# c1 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(s)\n# c1 = tf.keras.layers.Dropout(0.1)(c1)\n# c1 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c1)\n# p1 = tf.keras.layers.MaxPooling2D((2, 2))(c1)\n\n# c2 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p1)\n# c2 = tf.keras.layers.Dropout(0.1)(c2)\n# c2 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c2)\n# p2 = tf.keras.layers.MaxPooling2D((2, 2))(c2)\n \n# c3 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p2)\n# c3 = tf.keras.layers.Dropout(0.2)(c3)\n# c3 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c3)\n# p3 = tf.keras.layers.MaxPooling2D((2, 2))(c3)\n \n# c4 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p3)\n# c4 = tf.keras.layers.Dropout(0.2)(c4)\n# c4 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c4)\n# p4 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(c4)\n \n# c5 = tf.keras.layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p4)\n# c5 = tf.keras.layers.Dropout(0.3)(c5)\n# c5 = tf.keras.layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c5)\n\n# #Expansive path \n# u6 = tf.keras.layers.Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5)\n# u6 = tf.keras.layers.concatenate([u6, c4])\n# c6 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u6)\n# c6 = tf.keras.layers.Dropout(0.2)(c6)\n# c6 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c6)\n \n# u7 = tf.keras.layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c6)\n# u7 = tf.keras.layers.concatenate([u7, c3])\n# c7 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u7)\n# c7 = tf.keras.layers.Dropout(0.2)(c7)\n# c7 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c7)\n \n# u8 = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c7)\n# u8 = tf.keras.layers.concatenate([u8, c2])\n# c8 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u8)\n# c8 = tf.keras.layers.Dropout(0.1)(c8)\n# c8 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c8)\n \n# u9 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8)\n# u9 = tf.keras.layers.concatenate([u9, c1], axis=3)\n# c9 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u9)\n# c9 = tf.keras.layers.Dropout(0.1)(c9)\n# c9 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c9)\n \n# outputs = tf.keras.layers.Conv2D(2, (1, 1), activation='softmax')(c9)\n \n# model = tf.keras.Model(inputs=[inputs], outputs=[outputs])\n# model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n# model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n# # Encoder Utilities\n# from tensorflow.keras.models import *\n# from tensorflow.keras.layers import *\n# import tensorflow as tf \n# def conv2d_block(input_tensor, n_filters, kernel_size = 3):\n#     '''\n#     Adds 2 convolutional layers with the parameters passed to it\n\n#     Args:\n#     input_tensor (tensor) -- the input tensor\n#     n_filters (int) -- number of filters\n#     kernel_size (int) -- kernel size for the convolution\n\n#     Returns:\n#     tensor of output features\n#     '''\n#     # first layer\n#     x = input_tensor\n#     for i in range(2):\n#         x = tf.keras.layers.Conv2D(filters = n_filters, kernel_size = (kernel_size, kernel_size),kernel_initializer = 'he_normal', padding = 'same')(x)\n#         x = tf.keras.layers.Activation('relu')(x)\n\n#     return x\n\n\n# def encoder_block(inputs, n_filters=64, pool_size=(2,2), dropout=0.3):\n#     '''\n#     Adds two convolutional blocks and then perform down sampling on output of convolutions.\n\n#     Args:\n#     input_tensor (tensor) -- the input tensor\n#     n_filters (int) -- number of filters\n#     kernel_size (int) -- kernel size for the convolution\n\n#     Returns:\n#     f - the output features of the convolution block \n#     p - the maxpooled features with dropout\n#     '''\n\n#     f = conv2d_block(inputs, n_filters=n_filters)\n#     p = tf.keras.layers.MaxPooling2D(pool_size=(2,2))(f)\n#     p = tf.keras.layers.Dropout(0.3)(p)\n\n#     return f, p\n\n\n# def encoder(inputs):\n#     '''\n#     This function defines the encoder or downsampling path.\n\n#     Args:\n#     inputs (tensor) -- batch of input images\n\n#     Returns:\n#     p4 - the output maxpooled features of the last encoder block\n#     (f1, f2, f3, f4) - the output features of all the encoder blocks\n#     '''\n#     f1, p1 = encoder_block(inputs, n_filters=64, pool_size=(2,2), dropout=0.3)\n#     f2, p2 = encoder_block(p1, n_filters=128, pool_size=(2,2), dropout=0.3)\n#     f3, p3 = encoder_block(p2, n_filters=256, pool_size=(2,2), dropout=0.3)\n#     f4, p4 = encoder_block(p3, n_filters=512, pool_size=(2,2), dropout=0.3)\n\n#     return p4, (f1, f2, f3, f4)\n\n# def bottleneck(inputs):\n#     '''This function defines the bottleneck convolutions to extract more features before the upsampling layers.'''  \n#     bottle_neck = conv2d_block(inputs, n_filters=1024)\n\n#     return bottle_neck\n\n#   # Decoder Utilities\n\n# def decoder_block(inputs, conv_output, n_filters=64, kernel_size=3, strides=3, dropout=0.3):\n#     '''\n#     defines the one decoder block of the UNet\n\n#     Args:\n#     inputs (tensor) -- batch of input features\n#     conv_output (tensor) -- features from an encoder block\n#     n_filters (int) -- number of filters\n#     kernel_size (int) -- kernel size\n#     strides (int) -- strides for the deconvolution/upsampling\n#     padding (string) -- \"same\" or \"valid\", tells if shape will be preserved by zero padding\n\n#     Returns:\n#     c (tensor) -- output features of the decoder block\n#     '''\n#     u = tf.keras.layers.Conv2DTranspose(n_filters, kernel_size, strides = strides, padding = 'same')(inputs)\n#     c = tf.keras.layers.concatenate([u, conv_output])\n#     c = tf.keras.layers.Dropout(dropout)(c)\n#     c = conv2d_block(c, n_filters, kernel_size=3)\n\n#     return c\n\n\n# def decoder(inputs, convs, output_channels):\n#     '''\n#     Defines the decoder of the UNet chaining together 4 decoder blocks. \n\n#     Args:\n#     inputs (tensor) -- batch of input features\n#     convs (tuple) -- features from the encoder blocks\n#     output_channels (int) -- number of classes in the label map\n\n#     Returns:\n#     outputs (tensor) -- the pixel wise label map of the image\n#     '''\n\n#     f1, f2, f3, f4 = convs\n\n#     c6 = decoder_block(inputs, f4, n_filters=512, kernel_size=(3,3), strides=(2,2), dropout=0.3)\n#     c7 = decoder_block(c6, f3, n_filters=256, kernel_size=(3,3), strides=(2,2), dropout=0.3)\n#     c8 = decoder_block(c7, f2, n_filters=128, kernel_size=(3,3), strides=(2,2), dropout=0.3)\n#     c9 = decoder_block(c8, f1, n_filters=64, kernel_size=(3,3), strides=(2,2), dropout=0.3)\n\n#     outputs = tf.keras.layers.Conv2D(output_channels, (1, 1), activation='sigmoid')(c9)\n\n#     return outputs\n\n# OUTPUT_CHANNELS = 1\n\n# def unet():\n#     '''\n#     Defines the UNet by connecting the encoder, bottleneck and decoder.\n#     '''\n\n#     # specify the input shape\n#     inputs = tf.keras.layers.Input(shape=(256,256,3,))\n    \n#     # feed the inputs to the encoder\n#     encoder_output, convs = encoder(inputs)\n\n#     # feed the encoder output to the bottleneck\n#     bottle_neck = bottleneck(encoder_output)\n\n#     # feed the bottleneck and encoder block outputs to the decoder\n#     # specify the number of classes via the `output_channels` argument\n#     outputs = decoder(bottle_neck, convs, output_channels=OUTPUT_CHANNELS)\n\n#     # create the model\n#     model = tf.keras.Model(inputs=inputs, outputs=outputs)\n\n#     return model\n\n# # instantiate the model\n# model = unet()\n\n# # see the resulting model architecture\n# model.summary()\n# model.compile(optimizer=tf.keras.optimizers.Adam(), loss='binary_crossentropy',metrics=['accuracy'])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, concatenate, Conv2DTranspose, BatchNormalization, Dropout, Lambda\n\n################################################################\ndef simple_unet_model(IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS):\n#Build the model\n    inputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\n    #s = Lambda(lambda x: x / 255)(inputs)   #No need for this if we normalize our inputs beforehand\n    s = inputs\n\n    #Contraction path\n    c1 = Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(s)\n    c1 = Dropout(0.1)(c1)\n    c1 = Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c1)\n    p1 = MaxPooling2D((2, 2))(c1)\n    \n    c2 = Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p1)\n    c2 = Dropout(0.1)(c2)\n    c2 = Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c2)\n    p2 = MaxPooling2D((2, 2))(c2)\n     \n    c3 = Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p2)\n    c3 = Dropout(0.2)(c3)\n    c3 = Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c3)\n    p3 = MaxPooling2D((2, 2))(c3)\n     \n    c4 = Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p3)\n    c4 = Dropout(0.2)(c4)\n    c4 = Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c4)\n    p4 = MaxPooling2D(pool_size=(2, 2))(c4)\n     \n    c5 = Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p4)\n    c5 = Dropout(0.3)(c5)\n    c5 = Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c5)\n    \n    #Expansive path \n    u6 = Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5)\n    u6 = concatenate([u6, c4])\n    c6 = Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u6)\n    c6 = Dropout(0.2)(c6)\n    c6 = Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c6)\n     \n    u7 = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c6)\n    u7 = concatenate([u7, c3])\n    c7 = Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u7)\n    c7 = Dropout(0.2)(c7)\n    c7 = Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c7)\n     \n    u8 = Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c7)\n    u8 = concatenate([u8, c2])\n    c8 = Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u8)\n    c8 = Dropout(0.1)(c8)\n    c8 = Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c8)\n     \n    u9 = Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8)\n    u9 = concatenate([u9, c1], axis=3)\n    c9 = Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u9)\n    c9 = Dropout(0.1)(c9)\n    c9 = Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c9)\n     \n    outputs = Conv2D(1, (1, 1), activation='sigmoid')(c9)\n     \n    model = Model(inputs=[inputs], outputs=[outputs])\n    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n    #model.summary()\n    \n    return model\nmodel = simple_unet_model(256,256,3)\n ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.load_weights('../input/weights-file/my_model20ep.h5')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Training\n\nimport os\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping, CSVLogger\n\nprint(f\"Dataset: Train: {len(train_x)} - Valid: {len(valid_x)} - Test: {len(test_x)}\")\n\n#Hyperparameters\nepochs = 30\nbatch_size = 16\n\n\ntrain_dataset = tf_dataset(train_x, train_y, batch=batch_size)\nvalid_dataset = tf_dataset(valid_x, valid_y, batch=batch_size)\ntest_dataset = tf_dataset(test_x,test_y,batch=460)\n\ntrain_steps = len(train_x)//batch_size\nvalid_steps = len(valid_x)//batch_size\n\n\nmodel.fit(train_dataset,\nsteps_per_epoch=train_steps,\nvalidation_data=valid_dataset,\nvalidation_steps=valid_steps,\nepochs=epochs\n)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#model.save('./saved_model/')\nmodel.save('./my_model_50ep.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Infrencing\ni=320\nimport cv2\nimport matplotlib.pyplot as plt\n\nx = cv2.imread(test_x[i],cv2.IMREAD_COLOR)\nx = x/255.0\nx= x.astype(np.float32)\n\ny = cv2.imread(test_y[i], cv2.IMREAD_GRAYSCALE)\ny = y.astype(np.int32)\n\n\nplt.subplot(2, 2, 1)\nplt.imshow(x)\n\nplt.subplot(2, 2, 2)\nplt.imshow(y)\n\nmodel.load_weights('./my_model_50ep.h5')\noutput = model.predict(np.expand_dims(x,axis=0))\n\noutput = output[0]\noutput=np.resize(output,[256,256])\noutput = np.where(output >0.5, 1, 0)\n#output = np.argmax(output,axis=-1)\n\n\nplt.subplot(2,2,3)\nplt.imshow(output)\n\nplt.subplot(2,2,4)\nplt.imshow(x)\nplt.imshow(output,alpha=0.5)\n\n#IOU\nsmoothening_factor = 0.00001\nintersection = np.logical_and(y,output)\nunion = np.logical_or(y,output)\niou_score = (np.sum(intersection)+smoothening_factor) / (np.sum(union)+smoothening_factor)\ndice_score = (2*np.sum(intersection)+smoothening_factor)/(np.sum(y)+np.sum(output)+smoothening_factor)\nprint(\"IoU socre is: \", iou_score)\nprint(\"Dice score is:\",dice_score)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import tifffile as tiff\n# test_full=tiff.imread('../input/hubmap-kidney-segmentation/test/b2dc8411c.tiff')\n# test_full = np.resize(test_full,(14592,31232,3))\n# full_img = np.zeros((14592,31323)) \n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# n_H = 57\n# n_W = 122\n# stride = 256\n# f = 256\n# n_C = 3\n# for h in range(n_H):           # loop over vertical axis of the output volume\n#             # Find the vertical start and end of the current \"slice\" (≈2 lines)\n#             vert_start = h*stride\n#             vert_end = vert_start + f\n            \n#             for w in range(n_W):       # loop over horizontal axis of the output volume\n#                 # Find the horizontal start and end of the current \"slice\" (≈2 lines)\n#                 horiz_start = w*stride\n#                 horiz_end = horiz_start+f\n                \n                \n#                 # Use the corners to define the (3D) slice of a_prev_pad (See Hint above the cell). (≈1 line)\n#                 slice_prev = test_full[vert_start:vert_end,horiz_start:horiz_end,:]\n#                 output = slice_prev/255.0\n#                 output = model.predict(np.expand_dims(output,axis=0))\n#                 output = output[0]\n#                 output = np.resize(output,[256,256])\n#                 output = np.where(output >0.1, 1, 0)\n#                 full_img[vert_start:vert_end,horiz_start:horiz_end] = output","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(full_img)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":false,"_kg_hide-output":false,"trusted":true,"collapsed":true},"cell_type":"code","source":"# n_H = 57 \n# n_W = 122\n# stride = 256\n# f = 256\n\n# for h in range(n_H):           # loop over vertical axis of the output volume\n#             # Find the vertical start and end of the current \"slice\" (≈2 lines)\n#             vert_start = h*stride\n#             vert_end = vert_start + f\n            \n#             for w in range(n_W):       # loop over horizontal axis of the output volume\n#                 # Find the horizontal start and end of the current \"slice\" (≈2 lines)\n#                 horiz_start = w*stride\n#                 horiz_end = horiz_start+f\n                \n                \n#                 # Use the corners to define the (3D) slice of a_prev_pad (See Hint above the cell). (≈1 line)\n#                 print(test_full[vert_start:vert_end,horiz_start:horiz_end,:].shape)","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}