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.
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:
YCrCb channels:
You can, however, apply a color effect:
You can blur the Y channel, and then merge the 3 single channels, and convert back to BGR:
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With