Saturday, 30 April 2016

OpenCV C++ Code for Split and Merge

This tutorial gives a deep insight of splitting and merging function of opencv. Thus enabling us to split a color image into their respective RGB channels:

Here we want to split a color image into its three channels called "Red" ,"Green" and "Blue".

Splitting a color image into its respective RGB channels gives us an idea about the component of color which is present in an original image.

OpenCV provides built in function called “split()” for this purpose.


Syntax:
C++:void split(const Mat& src, Mat* mvbegin)

Parameters:
src input multi-channel array.
mv output array or vector of arrays.

In the first variant of the function the number of arrays must match src.channels();
the arrays themselves are reallocated, if needed.



The function “merge()” does just the opposite to that of split. It creates one multichannel array out of several single-channel ones.


Syntax: C++: void merge(const Mat* mv, size_t count, OutputArray dst)

Parameters:
mv – input array or vector of matrices to be merged; all the matrices in mv must have the same size and the same depth.
count – number of input matrices when mv is a plain C array; it must be greater than zero.
dst – output array of the same size and the same depth as mv[0]. The number of channels will be the total number of channels in the matrix array. The functions merge merge several arrays to make a single multi-channel array.


Here is the code below:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
 
using namespace cv;
using namespace std;
 
int main()
{
 
    Mat image;
    image = imread("C:\\Users\\arjun\\Desktop\\rgbimage.png", CV_LOAD_IMAGE_COLOR);   // Read the file
 
    if(! image.data )                              // Check for invalid input
    {
        cout <<  "Could not open or find the image" << std::endl ;
        return -1;
    }
 
    
 namedWindow( "Original Image", CV_WINDOW_AUTOSIZE );
 imshow( "Original Image", image );
 
    Mat rgbchannel[3];
    // The actual splitting.
    split(image, rgbchannel);
 
 namedWindow("Blue",CV_WINDOW_AUTOSIZE);
 imshow("Red", rgbchannel[0]);
 
 namedWindow("Green",CV_WINDOW_AUTOSIZE);
 imshow("Green", rgbchannel[1]);
 
 namedWindow("Red",CV_WINDOW_AUTOSIZE);
 imshow("Blue", rgbchannel[2]);
 
    waitKey(0);//Wait for a keystroke in the window
    return 0;
}



Input:
Output:





Note:
You might have observed that we obtain the grayscale images after splitting the color images into Red,Green and Blue colors.
Reason:
Split function splits the multichannel image into single channel arrays containing the identical pixel value of the original image.
So since we have created single channel images,opencv imshow function treats it as a grayscale image.
For a colour image, we need to create a three channel image.

The OpenCV C++ code is given below:-
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
 
using namespace std;
using namespace cv;
 
int main()
{
    Mat image=imread("C:\\Users\\arjun\\Desktop\\aaa.png",1);    
    namedWindow("Original Image",1);
 imshow("Original Image",image);
 
    // Split the image into different channels
    vector<Mat> rgbChannels(3);
    split(src, rgbChannels);
 
    // Show individual channels
    Mat g, fin_img;
    g = Mat::zeros(Size(image.cols, image.rows), CV_8UC1);
      
    // Showing Red Channel
    // G and B channels are kept as zero matrix for visual perception
    {
    vector<Mat> channels;
    channels.push_back(g);
    channels.push_back(g);
    channels.push_back(rgbChannels[2]);
 
    /// Merge the three channels
    merge(channels, fin_img);
    namedWindow("Red",1);
 imshow("Red", fin_img);
    }
 
    // Showing Green Channel
    {
    vector<Mat> channels;
    channels.push_back(g);
    channels.push_back(rgbChannels[1]);
    channels.push_back(g);    
    merge(channels, fin_img);
    namedWindow("Green",1);
 imshow("Green", fin_img);
    }
 
    // Showing Blue Channel
    {
    vector<Mat> channels;
    channels.push_back(rgbChannels[0]);
    channels.push_back(g);
    channels.push_back(g);
    merge(channels, fin_img);
    namedWindow("Blue",1);
    imshow("Blue", fin_img);
    }
 
    waitKey(0);
    return 0;
 
}


Input:

Output:





Here after splitting the image by split(image, rgbChannels)
We get three channels of which
  • Rgbchannel[0] corresponds to that of “Blue” color image.
  • Rgbchannel[1] corresponds to that of “Green” color image
  • Rgbchannel[2] corresponds to that of “Red” color image
Since the split function splits the multi-channel image into single channel ,if we display these channels directly we would get the gray-scale image of RGB channels.
Thus we need to create a matrix of zeros and push that into other channels.

Mat::zeros(Size(image.cols, image.rows), CV_8UC1) :
Creates a matrix of Zeros of single channel whose dimension is same as that of the original image.

Then we have initialized channels as the vector and push_back always puts a new element at the end of the vector.
Here the new element is a 8 bit single channel matrix of Zeros.


The BGR color ordering is the default order of OpenCV.
Refer:
http://opencv-code.blogspot.in/2016/12/how-to-access-extract-pixel-value-particular-location-image.html

Thus for displaying the red channels… we need to make the first two channels as Zeros and create a 3channel image with merge function to get the colored image.
Similar is the case with other channels of image.

1 comment: