Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting YCrCb image to its intensity channels

I want to split YCrCb to Y, Cr, and Cb channels.

Code works well but when I show the channels with imshow("Y", y) for each Y, Cr, Cb, all channels look grey.

Only Y channel must be grey the others are supposed to be colorful. Am I right? Or what is the problem with code?

    Mat RGBImage;
    RGBImage = imread("xx.jpg");    
    cvtColor(RGBImage, YCrCb, CV_RGB2YCrCb);

    vector<Mat> ycc_planes;
    split(YCrCb, ycc_planes);

    Mat y = ycc_planes[0];
    Mat Cr = ycc_planes[1];
    Mat Cb = ycc_planes[2];

My final goal is to apply mean filter to image's Y component and then to change it back to RGB with merging other components (Cr and Cb) . Finally I am going to get a blurry version of original RGB image. However my mean filter returns always grey blurry image. I though it may be so because of my Cr, Cb components are grey.

like image 531
Blu Avatar asked Oct 14 '15 18:10

Blu


2 Answers

When you split a 3 channel image into 3 single channel image, each image is grayscale. The fact that they represent color information is irrelevant.

Original image:

enter image description here

YCrCb channels:

enter image description here

You can, however, apply a color effect:

enter image description here


You can blur the Y channel, and then merge the 3 single channels, and convert back to BGR:

enter image description here

Here the full code for reference:

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;

int main()
{
    Mat3b bgr = imread("path_to_image");

    Mat3b ycrcb;
    cvtColor(bgr, ycrcb, COLOR_BGR2YCrCb);

    vector<Mat1b> planes;
    split(ycrcb, planes);

    // Collage planes
    Mat1b collagePlanes(bgr.rows, bgr.cols*3);
    for (int i = 0; i < 3; ++i)
    {
        planes[i].copyTo(collagePlanes(Rect(i*bgr.cols, 0, bgr.cols, bgr.rows)));
    }

    Mat1b gray(bgr.rows, bgr.cols, uchar(128));

    // Y
    vector<Mat1b> vy(3);
    vy[0] = planes[0];
    vy[1] = gray.clone();
    vy[2] = gray.clone();
    Mat3b my;
    merge(vy, my);

    // Cr
    vector<Mat1b> vcr(3);
    vcr[0] = gray.clone();
    vcr[1] = planes[1];
    vcr[2] = gray.clone();
    Mat3b mcr;
    merge(vcr, mcr);

    // Cb
    vector<Mat1b> vcb(3);
    vcb[0] = gray.clone();
    vcb[1] = gray.clone();
    vcb[2] = planes[2];
    Mat3b mcb;
    merge(vcb, mcb);



    // Collage planes
    Mat3b collageColor(bgr.rows, bgr.cols * 3);
    my.copyTo(collageColor(Rect(0, 0, bgr.cols, bgr.rows)));
    mcr.copyTo(collageColor(Rect(bgr.cols, 0, bgr.cols, bgr.rows)));
    mcb.copyTo(collageColor(Rect(2 * bgr.cols, 0, bgr.cols, bgr.rows)));

    cvtColor(collageColor, collageColor, COLOR_YCrCb2BGR);


    ////////////////////////////

    // Blur Y
    boxFilter(planes[0], planes[0], CV_8U, Size(7,7));

    Mat3b blurred;
    merge(planes, blurred);
    cvtColor(blurred, blurred, COLOR_YCrCb2BGR);


    imshow("Original", bgr);
    imshow("YCrCb planes", collagePlanes);
    imshow("YCrCb planes colored", collageColor);
    imshow("Blurred", blurred);
    waitKey();


    return 0;
}
like image 151
Miki Avatar answered Nov 01 '22 00:11

Miki


As @Miki said in the comments, splitting a 3-channel image will give you 3 1-channel images, and 1-channel images are grayscale! Also, @sturkmen pointed out an important thing: OpenCV images are stored as BGR, so you need to use CV_BGR2YCrCb instead of CV_RGB2YCrCb in the cvtColor.

However, I see a lot of materials showing them (the individual channels) in a colorful manner, like this from Professor Hays.

If you want to see them that way, you need to set a fixed value to the other channels and merge them back. This way you can achieve the first row of the image below. The second row are the individual channels. For more info you can read this post or watch this video.

YCrCb sample

like image 45
Berriel Avatar answered Nov 01 '22 01:11

Berriel