Ask Your Question

Revision history [back]

@Haris his solution to check the image is quite correct, however it seems that the topic starter is actually pointing at the fact the the image appear as grayscale images for him and not blue red and green coloured.

Let me explain. The signature and docs of split clearly states that a multi channel image is split into single channel arrays containing the identical pixel values of the original image.

HOWEVER, since you created single channel images, OpenCV imshow function will now think this is actually a grayscale images ranging from 0 - 255 in pixel values. In order to achieve the result you actually want, the code of Harris needs to be adapted and a workaround is needed to make the imshow believe you have again a 3 channel image but only with the right colour channel having pixel values.

Some code that should work:

// Load in image and check whether it is valid
Mat src = imread("t1.jpg",1);
if(src.empty()){ 
 cout<<"Cannot load image....!"<<endl;
 return -1;
}

// Create a vector for the channels and split the original image into B G R colour channels.
// Keep in mind that OpenCV uses BGR and not RGB images
vector<Mat> spl;
split(src,spl);

// Create an zero pixel image for filling purposes - will become clear later
// Also create container images for B G R channels as colour images
Mat empty_image = new Mat::zeros(src.rows, src.cols, 8UC1);
Mat result_blue(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
Mat result_green(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
Mat result_red(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!

// Create blue channel
Mat in1[] = { spl[0], empty_image, empty_image };
int from_to1[] = { 0,0, 1,1, 2,2 };
mixChannels( in1, 3, &result_blue, 1, from_to1, 3 );

// Create green channel
Mat in2[] = { empty_channel, spl[1], empty_image };
int from_to2[] = { 0,0, 1,1, 2,2 };
mixChannels( in2, 3, &result_green, 1, from_to2, 3 );

// Create red channel
Mat in3[] = { empty_channel, empty_channel, spl[2]};
int from_to3[] = { 0,0, 1,1, 2,2 };
mixChannels( in3, 3, &result_red, 1, from_to3, 3 );

imshow("blue channel",result_blue);
imshow("green channel",result_green);
imshow("red channel",result_red);

@Haris his solution to check the image is quite correct, however it seems that the topic starter is actually pointing at the fact the the image appear as grayscale images for him and not blue red and green coloured.

Let me explain. The signature and docs of split clearly states that a multi channel image is split into single channel arrays containing the identical pixel values of the original image.

HOWEVER, since you created single channel images, OpenCV imshow function will now think this is actually a grayscale images ranging from 0 - 255 in pixel values. In order to achieve the result you actually want, the code of Harris needs to be adapted and a workaround is needed to make the imshow believe you have again a 3 channel image but only with the right colour channel having pixel values.

Some code that should work:

// Load in image and check whether it is valid
Mat src = imread("t1.jpg",1);
if(src.empty()){ 
 cout<<"Cannot load image....!"<<endl;
 return -1;
}

// Create a vector for the channels and split the original image into B G R colour channels.
// Keep in mind that OpenCV uses BGR and not RGB images
vector<Mat> spl;
split(src,spl);

// Create an zero pixel image for filling purposes - will become clear later
// Also create container images for B G R channels as colour images
Mat empty_image = new Mat::zeros(src.rows, src.cols, 8UC1);
Mat result_blue(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
Mat result_green(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!
Mat result_red(src.rows, src.cols, CV_8UC3); // notice the 3 channels here!

// Create blue channel
Mat in1[] = { spl[0], empty_image, empty_image };
int from_to1[] = { 0,0, 1,1, 2,2 };
mixChannels( in1, 3, &result_blue, 1, from_to1, 3 );

// Create green channel
Mat in2[] = { empty_channel, spl[1], empty_image };
int from_to2[] = { 0,0, 1,1, 2,2 };
mixChannels( in2, 3, &result_green, 1, from_to2, 3 );

// Create red channel
Mat in3[] = { empty_channel, empty_channel, spl[2]};
int from_to3[] = { 0,0, 1,1, 2,2 };
mixChannels( in3, 3, &result_red, 1, from_to3, 3 );

imshow("blue channel",result_blue);
imshow("green channel",result_green);
imshow("red channel",result_red);

Something I came up with as an extra is this

Mat blue (src.rows, src.cols, CV_8UC3);
Mat green (src.rows, src.cols, CV_8UC3);
Mat red (src.rows, src.cols, CV_8UC3);
for (int i = 0; i < src.rows; i ++){
   for (int j = 0; j < src.cols; j ++){
    Scalar temp_blue = src.at<char>(i,j); temp_blue[1] = 0; temp_blue[2] = 0; 
    Scalar temp_green = src.at<char>(i,j); temp_green[0] = 0; temp_green[2] = 0; 
    Scalar temp_red = src.at<char>(i,j); temp_green[0] = 0; temp_green[1] = 0; 
        blue.at<char>(i,j) = temp_blue;
    green.at<char>(i,j) = temp_green;
    red.at<char>(i,j) = temp_red;
   }
}

Not sure if this is actually gonna work but the idea is quite equal, code is just more compact! Feel free to try out both solutions.