Python OpenCV: Splitting image channels

In this tutorial we will learn how to split the color channels of an image, using Python and OpenCV.

Introduction

In this tutorial we will learn how to split the color channels of an image, using Python and OpenCV.

This tutorial was tested on Windows 8.1, using Python version 3.7.2 and OpenCV version 4.1.2.

Decomposing the channels of the image

We will start the code by importing the cv2 module, so we have access to image processing functionalities.

import cv2

Then we will read the original colored image from the file system with a call to the imread function. This function receives as input the path to the file and returns the image as a ndarray. The image is read in the BGR format.

We will be reading the image shown below at figure 1. It consists on 3 rectangles, one in Blue (B=255, G=0, R=0), one in Green (B=0, G=255, R=0) and another in Red (B=0, G=0, R=255). The background is black (B=0, G=0, R=0).

Image to be used to split the channels.
Figure 1 – Image to be used to split the channels.

The code to read the image can be seen below.

img = cv2.imread('C:/Users/N/Desktop/bgr.png') 

Now, to split the image into its three channels, we simply need to call the split function from the cv2 module, passing as input our original image.

This function will return a list with the three channels. Each channel is represented as a ndarray with two dimensions, which means that we can later display them as grayscale images.

We will unpack each element of the list in different variables.

blue, green, red = cv2.split(img)

To finalize, we will display each channel in a different window.

cv2.imshow('blue', blue)
cv2.imshow('green', green)
cv2.imshow('red', red)

cv2.waitKey(0)
cv2.destroyAllWindows()

The final code can be seen below.

import cv2 

img = cv2.imread('C:/Users/N/Desktop/bgr.png') 

blue, green, red = cv2.split(img)


cv2.imshow('blue', blue)
cv2.imshow('green', green)
cv2.imshow('red', red)

cv2.waitKey(0)
cv2.destroyAllWindows()

To test the code, simply run it in a tool of your choice. In my case I’ll be using IDLE, a Python IDE.

You should get an input similar to figure 1.

Output of the program with the 3 channels decomposed.
Figure 2 – Output of the program with the 3 channels decomposed.

The first thing that can be noticed is that, as mentioned before, the images are in grayscale.

Then, for each image of each channel, only the rectangle with the same color is displayed in full white. To understand the reason, let’s analyze the original image in more detail.

First we need to consider that the black background pixels have a value equal to 0 for all the channels: (B=0, G=0, R=0). So, when we decompose each pixel of this area in the three channels, it will have the value 0 in all, which corresponds to black in a grayscale image.

If we look to a pixel in the blue rectangle of the original colored image, it will have the value of the blue channel equal to 255 and the remaining ones equal to 0: (B=255, G=0, R=0).

So, if we display the blue channel image in a window, this pixel will be equal to 255 and since it is a grayscale image, it corresponds to white. For the Green and Red channel images, this pixel will be equal to 0 and since it is a grayscale image, it corresponds to black.

This is why, in the blue channel image, we see a white rectangle where on the original image was a Blue rectangle. In the other channel images, we see black in that area.

Naturally, this rational holds true for the pixels on the other rectangles and the corresponding channels.

Showing the channels colored

In the previous section we saw how to decompose the image in its three channels and then how to display each channel in a window. But, as seen, each channel corresponded to a two dimensions ndarray that, when shown, was interpreted as a gray scale image.

If we want to show each channel as a colored image, we can do the following:

  • Split the original image into three channels;
  • Create an “empty” grayscale image that will represent an “empty channel”;
  • For a given channel, create a BGR image that will contain that channel and have the two other empty.

We will start by importing the cv2 and the numpy modules. The numpy module will be needed to create the “empty channel”.

After that, we will read the original image and split it, like we did before.

import cv2 
import numpy

img = cv2.imread('C:/Users/N/Desktop/bgr.png') 

blue, green, red = cv2.split(img)

Then we will create the “empty channel” by calling the zeros function of the numpy module. This will return a new ndarray array with the specified shape and filled with zeros.

The shape of the new array (its dimensions) is specified as a tuple that is passed as first input of the zeros function.

Naturally, we want the height and width of this “empty channel” to match the one from the other channels. We can use the shape attribute of one of these channels to set the shape of our “empty channel”. You can learn more about this attribute here.

Besides setting the shape, we also need to set the type of the ndarray returned by the zeros function. It should be of type uint8.

You can check below how to call the function.

zeros = numpy.zeros(blue.shape, numpy.uint8)

To create a BGR image from three separate channels, we simply need to call the merge function, passing as input a tuple with the channels.

So, to create the BGR image from the Blue channel, the first element of the tuple should be the Blue channel and the remaining ones should be the “empty channel”.

blueBGR = cv2.merge((blue,zeros,zeros))

The procedure is the same for the other channels.

greenBGR = cv2.merge((zeros,green,zeros))
redBGR = cv2.merge((zeros,zeros,red))

To finalize, we will display the three resulting images.

cv2.imshow('blue BGR', blueBGR)
cv2.imshow('green BGR', greenBGR)
cv2.imshow('red BGR', redBGR)

cv2.waitKey(0)
cv2.destroyAllWindows()

The final code can be seen below.

import cv2 
import numpy

img = cv2.imread('C:/Users/N/Desktop/bgr.png') 

blue, green, red = cv2.split(img)


zeros = numpy.zeros(blue.shape, numpy.uint8)

blueBGR = cv2.merge((blue,zeros,zeros))
greenBGR = cv2.merge((zeros,green,zeros))
redBGR = cv2.merge((zeros,zeros,red))


cv2.imshow('blue BGR', blueBGR)
cv2.imshow('green BGR', greenBGR)
cv2.imshow('red BGR', redBGR)

cv2.waitKey(0)
cv2.destroyAllWindows()

Upon running the code, you should get a result similar to figure 3.

Showing the 3 channels colored.
Figure 3 – Showing the 3 channels colored.

Naturally, there are other approaches to achieve this result, such as copying the original image and zeroing two of the channels to get the third one colored. Nonetheless, since here we were covering the split procedure, we have seen how to get each colored channel by using the merge function.

Leave a Reply