Ask Your Question
2

i want to split and show R B G pictures ,why does it not work?

asked 2014-07-14 23:05:24 -0600

Song gravatar image

updated 2015-10-20 10:11:19 -0600

namedWindow("dst");
//i want t show R B G pictures
vector<Mat> spl;

src = imread("t1.jpg");
imshow("SRC",src);
split(src,spl);
imshow("spl1",spl[0]);//b
imshow("spl2",spl[1]);//g
imshow("spl3",spl[2]);//r
edit retag flag offensive close merge delete

3 answers

Sort by » oldest newest most voted
2

answered 2014-07-15 02:55:29 -0600

updated 2014-07-15 04:22:30 -0600

@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.

edit flag offensive delete link more

Comments

thank you ,i know it.
cause my mother tongue is not English,I can not understand the point correctly.

Song gravatar imageSong ( 2014-07-15 04:25:23 -0600 )edit

Did it work?

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-15 04:30:10 -0600 )edit

yeah,pretty good! but blue.at<char>(i,j) = temp_blue;//cannot convert Scalar to char green.at<char>(i,j) = temp_green;//cannot convert Scalar to char red.at<char>(i,j) = temp_red;//cannot convert Scalar to char

Song gravatar imageSong ( 2014-07-15 04:45:36 -0600 )edit

Hmm I will look deeper into the second code snippet. It does the same as first. Will keep you up to date!

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-15 05:02:26 -0600 )edit
1

answered 2014-07-15 04:04:24 -0600

You are splitting each channel into a new image, but don't expect your pictures will be red, green or blue, they all will be in grayscale. It's because you are using a single channel to display them (which seems reasonable...). If you want to display the red channel as red, the blue as blue and the green as green, you have to create a 3-channels image, for each of them, and copy the single channel extracted into the right channel (the other channels remain at 0). See the function mixChannels for that.

    cv::Mat red = cv::Mat::zeros(im.rows, im.cols, CV_8UC3 );
    cv::Mat green = cv::Mat::zeros(im.rows, im.cols, CV_8UC3 );
    cv::Mat blue = cv::Mat::zeros(im.rows, im.cols, CV_8UC3 );

    cv::Mat channels[] = { red, green, blue };
    int from_to[] = {0,2, 1,4, 2,6 };

    cv::mixChannels( &im, 1, channels, 3, from_to, 3);

You create 3 new images (one for each channel), and you copy the origin image (called 'im') into each corresponding channel: im[0] -> red[2], im[1] -> green[1], im[2] -> blue[0]. Channels are continuous, so green[1] is (red.channels()-1) + 2

(red.channels() is the blue channel of green image, does it make sense? Have a look at the documentation, and make some tries...)

edit flag offensive delete link more

Comments

Didn't see my post? :D

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-15 04:10:05 -0600 )edit

Too late… ;-) I was editing my post to fix a channel id, and (doing something else in the same time, it took more than an hour to finally post the answer… ;-) )

Mathieu Barnachon gravatar imageMathieu Barnachon ( 2014-07-15 04:27:06 -0600 )edit

Hehe no problem!

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-15 04:29:43 -0600 )edit

Is it applicable for android programming in Java with openCv? if not then can you please suggest me the alternative for this code, Thank you.

khatri.kelash gravatar imagekhatri.kelash ( 2017-01-18 12:47:35 -0600 )edit

Yes it is, you just need to select the corresponding Java functions! Take a look at the Java docs.

StevenPuttemans gravatar imageStevenPuttemans ( 2017-01-19 06:09:23 -0600 )edit
1

answered 2014-07-14 23:21:26 -0600

Haris gravatar image

Check this code,

Mat src = imread("t1.jpg",1);
if(src.empty()){ 
 cout<<"Cannot load image....!"<<endl;
 return -1;
}

vector<Mat> spl;
split(src,spl);
imshow("spl1",spl[0]);//b
imshow("spl2",spl[1]);//g
imshow("spl3",spl[2]);//r

Important thing is check you are able to load image successfully using Mat::empty

edit flag offensive delete link more

Comments

why the split pictures are not red,green,blue?Did i still need something else to deal with?

Song gravatar imageSong ( 2014-07-15 01:41:03 -0600 )edit

@Song see my answer. In short, you are visualising grayscale channels and you need color channels.

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-15 02:57:12 -0600 )edit

Question Tools

Stats

Asked: 2014-07-14 23:05:24 -0600

Seen: 36,169 times

Last updated: Jul 15 '14