def fcn8_decoder(convs, n_classes): f1, f2, f3, f4, p5 = convs n = 4096 c6 = tf.keras.layers.Conv2D( n, (7, 7), activation='relu', padding='same', name="conv6")(p5) c7 = tf.keras.layers.Conv2D( n, (1, 1), activation='relu', padding='same', name="conv7")(c6) f5 = c7 # upsample the output of the encoder # then crop extra pixels that were introduced o = tf.keras.layers.Conv2DTranspose(n_classes, kernel_size=( 4, 4), strides=(2, 2), use_bias=False)(f5) o = tf.keras.layers.Cropping2D(cropping=(1, 1))(o) # load the pool 4 prediction and do a 1x1 # convolution to reshape it to the same shape of `o` above o2 = f4 o2 = (tf.keras.layers.Conv2D(n_classes, (1, 1), activation='relu', padding='same'))(o2) # add the results of the upsampling and pool 4 prediction o = tf.keras.layers.Add()([o, o2]) # upsample the resulting tensor of the operation you just did o = (tf.keras.layers.Conv2DTranspose( n_classes, kernel_size=(4, 4), strides=(2, 2), use_bias=False))(o) o = tf.keras.layers.Cropping2D(cropping=(1, 1))(o) # load the pool 3 prediction and do a 1x1 # convolution to reshape it to the same shape of `o` above o2 = f3 o2 = (tf.keras.layers.Conv2D(n_classes, (1, 1), activation='relu', padding='same'))(o2) # add the results of the upsampling and pool 3 prediction o = tf.keras.layers.Add()([o, o2]) # upsample up to the size of the original image o = tf.keras.layers.Conv2DTranspose( n_classes, kernel_size=(8, 8), strides=(8, 8), use_bias=False)(o) # append a softmax to get the class probabilities o = tf.keras.layers.Activation('softmax')(o) return o