Merging three grayscale [R, G, B] images into a single color image in opencv

c++, image, image-processing, opencv

Solution

I can't see anything wrong with your code. I suspect it may be the source data, or how it is being treated by the importer. After you load the images, can you print out the image metadata to see what attributes OpenCV is reading? They all must have the same dimensions and a single channel.

std::cout << "Red:   " << R.size().width << " x " << R.size().height << " x " << R.channels() << std::endl;
std::cout << "Green: " << G.size().width << " x " << G.size().height << " x " << G.channels() << std::endl;
std::cout << "Blue:  " << B.size().width << " x " << B.size().height << " x " << B.channels() << std::endl;

I just ran your program, just with the headers and main added. I made one small change, to merge in B,G,R order (the default). I compiled it on Mac OS X 10.8 with:

g++ -o merge merge.cpp -lopencv_core -lopencv_highgui

against OpenCV version 2.4.3.

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>

int main(int argc, char* argv[])
{
    cv::Mat R = cv::imread("chan_dest_red.png", 0);
    cv::Mat G = cv::imread("chan_dest_green.png", 0);
    cv::Mat B = cv::imread("chan_dest_blue.png", 0);

    std::vector<cv::Mat> array_to_merge;

    array_to_merge.push_back(B);
    array_to_merge.push_back(G);
    array_to_merge.push_back(R);

    cv::Mat color;

    cv::merge(array_to_merge, color);

    imwrite("merged.png", color);

    return 0;
}

I had some single channel images from another project already split into files, and I just merged those into a single colour image and it worked just fine. The source file info is as follows:

Red:   500 x 333 x 1
Green: 500 x 333 x 1
Blue:  500 x 333 x 1

Problem

I have 3 grayscale images that I created using the split function. Now I want to regenerate the color image back. I tried the following code but it did not work. The resultant image I got was still grayscale. ``` cv::Mat R = cv::imread("/home/r/secret_R.png",0); cv::Mat G = cv::imread("/home/r/secret_G.png",0); cv::Mat B = cv::imread("/home/r/secret_B.png",0); std::vector<cv::Mat> array_to_merge; array_to_merge.push_back(R); array_to_merge.push_back(G); array_to_merge.push_back(B); cv::Mat color; cv::merge(array_to_merge, color); ``` So then I tried the cvtColor function: ``` cv::Mat color_converted; cv::cvtColor(color, color_converted, CV_GRAY2BGR); cv::imwrite("/home/r/color_secret.png",color_converted); ``` But apparently, it only works for source images that have only a single channel. I passed it one of my grayscale images: ``` cv::cvtColor(R, color_converted, CV_GRAY2BGR); ``` But I still could not get a color image back. The resultant image was still grayscale What am I doing wrong ? How do I get my color image back ?

Original source