Image Segmentation Using Composable Fully-Convolutional Networks in Keras

Image segmentation is a crucial task in computer vision, where the goal is to classify each pixel in an image into meaningful categories. Over the years, fully-convolutional networks (FCNs) have become the go-to architecture for this task. With over four years of experience working with Python and Keras, I’ve found composable FCNs to be a flexible and powerful way to build segmentation models.

In this tutorial, I’ll guide you through how to implement image segmentation using composable fully-convolutional networks in Keras. I’ll provide complete code examples for each step, making it easy to follow along and customize for your own projects.

What Are Composable Fully-Convolutional Networks in Keras?

Composable FCNs are networks built by combining smaller convolutional blocks to form a larger segmentation model. This modular approach allows you to easily experiment with different architectures by stacking or reusing blocks.

Using Keras, you can define these blocks as functions and compose them to create complex models. This method greatly simplifies building segmentation networks and enhances readability and maintainability.

Building Blocks: Convolutional Block in Keras

A convolutional block usually consists of convolution layers, batch normalization, and activation functions. Here’s a simple reusable convolutional block I use often:

from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation

def conv_block(x, filters, kernel_size=3, padding='same', strides=1):
    x = Conv2D(filters, kernel_size, strides=strides, padding=padding)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    return x

This block applies a convolution followed by normalization and ReLU activation. It’s the fundamental building unit for our composable FCN.

Encoder Module: Downsample with Composable FCN in Keras

The encoder reduces spatial dimensions while increasing feature depth, capturing context.

from tensorflow.keras.layers import MaxPooling2D

def encoder_block(x, filters):
    x = conv_block(x, filters)
    x = conv_block(x, filters)
    p = MaxPooling2D((2, 2))(x)
    return x, p

This block applies two convolutional blocks and then downsamples using max pooling. It returns both the feature map before pooling (for skip connections) and the pooled output.

Decoder Module: Upsample with Composable FCN in Keras

The decoder restores spatial resolution using upsampling and combines features from the encoder via skip connections.

from tensorflow.keras.layers import Conv2DTranspose, Concatenate

def decoder_block(x, skip_features, filters):
    x = Conv2DTranspose(filters, (2, 2), strides=2, padding='same')(x)
    x = Concatenate()([x, skip_features])
    x = conv_block(x, filters)
    x = conv_block(x, filters)
    return x

Here, we use transpose convolution for upsampling, concatenate the encoder features, and apply convolutional blocks to refine the output.

Compose the FCN Model in Keras

Now, let’s compose the encoder and decoder blocks into a full FCN model for segmentation.

from tensorflow.keras.layers import Input, Conv2D
from tensorflow.keras.models import Model

def build_fcn_model(input_shape, num_classes):
    inputs = Input(input_shape)

    # Encoder
    s1, p1 = encoder_block(inputs, 64)
    s2, p2 = encoder_block(p1, 128)
    s3, p3 = encoder_block(p2, 256)
    s4, p4 = encoder_block(p3, 512)

    # Bottleneck
    b1 = conv_block(p4, 1024)
    b1 = conv_block(b1, 1024)

    # Decoder
    d1 = decoder_block(b1, s4, 512)
    d2 = decoder_block(d1, s3, 256)
    d3 = decoder_block(d2, s2, 128)
    d4 = decoder_block(d3, s1, 64)

    # Output layer
    outputs = Conv2D(num_classes, 1, padding='same', activation='softmax')(d4)

    model = Model(inputs, outputs, name='Composable_FCN')
    return model

This model uses four encoder and decoder blocks with a bottleneck layer in between. The final output layer predicts the class for each pixel.

Train the Composable FCN Model in Keras

To train the model, compile it with an appropriate loss and optimizer. For multi-class segmentation, categorical cross-entropy is common.

model = build_fcn_model((256, 256, 3), num_classes=3)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()

You would then train the model on your labeled dataset using model.fit(). Make sure your labels are one-hot encoded for multi-class segmentation.

Use the Model for Prediction

After training, use the model to predict segmentation masks for new images.

import numpy as np
from tensorflow.keras.preprocessing.image import load_img, img_to_array

def preprocess_image(image_path, target_size=(256, 256)):
    image = load_img(image_path, target_size=target_size)
    image = img_to_array(image) / 255.0
    image = np.expand_dims(image, axis=0)
    return image

image = preprocess_image('sample_image.jpg')
pred_mask = model.predict(image)
pred_mask = np.argmax(pred_mask, axis=-1)[0]

I executed the above example code and added the screenshot below.

Image Segmentation Using Composable Fully-Convolutional Networks in Keras

This code loads and preprocesses an image, then uses the model to predict the segmentation mask.

Composable fully-convolutional networks in Keras provide a modular and intuitive way to build powerful segmentation models. The composable blocks make it easy to experiment and scale your models for complex tasks.

If you want to dive deeper, try adding dropout, experimenting with different activation functions, or integrating attention mechanisms. The modular nature of composable FCNs means you can build exactly what your project needs.

Other Python Keras tutorials you may like:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.