'OpenCV Display Colored Cb Cr Channels
So I understand how to convert a BGR image to YCrCb format using cvtColor() and seperate different channels using split() or mixChannels() in OpenCV. However, these channels are displayed as grayscale images as they are CV_8UC1 Mats.
I would like to display Cb and Cr channels in color like Barns image on Wikipedia. I found this solution in Matlab, but how do I do it in OpenCV?
Furthermore, the mentioned solution displayed Cb and Cr channels by "fills the other channels with a constant value of 50%". My question is:
Is this the common way to display Cr Cb channels? Or is there any recommendations or specifications when displaying Cr Cb channels?
Solution 1:[1]
I made a code from scratch as described in answer. Looks like it's what you need.
Mat bgr_image = imread("lena.png");
Mat yCrCb_image;
cvtColor(bgr_image, yCrCb_image, CV_BGR2YCrCb);
Mat yCrCbChannels[3];
split(yCrCb_image, yCrCbChannels);
Mat half(yCrCbChannels[0].size(), yCrCbChannels[0].type(), 127);
vector<Mat> yChannels = { yCrCbChannels[0], half, half };
Mat yPlot;
merge(yChannels, yPlot);
cvtColor(yPlot, yPlot, CV_YCrCb2BGR);
imshow("y", yPlot);
vector<Mat> CrChannels = { half, yCrCbChannels[1], half };
Mat CrPlot;
merge(CrChannels, CrPlot);
cvtColor(CrPlot, CrPlot, CV_YCrCb2BGR);
imshow("Cr", CrPlot);
vector<Mat> CbChannels = { half, half, yCrCbChannels[2] };
Mat CbPlot;
merge(CbChannels, CbPlot);
cvtColor(CrPlot, CrPlot, CV_YCrCb2BGR);
imshow("Cb", CbPlot);
waitKey(0);

As for converting grayscale images to color format, usually in such case all color channels (B, G, R) set to one grayscale value. In OpenCV CV_GRAY2BGR mode implemented in that manner.
As for "fills the other channels with a constant value of 50%" I believe it's common way to visualize such color spaces as YCbCr and Lab. I did not find any articles and descriptions of this approach, but I think it's driven by visualization purposes. Indeed, if we fill the other channels with zero, fundamentally nothing has changed: we can also see the influence of each channel, but the picture does not look very nice:

So, the aim of this approach to make visualization more colorful.
Solution 2:[2]
For thoses who want the code in Python (which is the same as @akarsakov) here it is :
import cv2
import numpy as np
img = cv2.imread(r"lena.png")
imgYCC = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
Y,Cr,Cb = cv2.split(imgYCC)
half = np.array([[127]*Y.shape[1]]*Y.shape[0]).astype(Y.dtype)
merge_Y = cv2.merge([Y, half, half])
merge_Cb = cv2.merge([half, half, Cb])
merge_Cr = cv2.merge([half, Cr, half])
merge_Y = cv2.cvtColor(merge_Y, cv2.COLOR_YCrCb2BGR)
merge_Cb = cv2.cvtColor(merge_Cb, cv2.COLOR_YCrCb2BGR)
merge_Cr = cv2.cvtColor(merge_Cr, cv2.COLOR_YCrCb2BGR)
cv2.imwrite(r'Y.png', merge_Y)
cv2.imwrite(r'Cb.png', merge_Cb)
cv2.imwrite(r'Cr.png', merge_Cr)
The result isn't the same by the way and more look like what we could find on google when we write Y Cb Cr images. Or maybe I did a mistake with split and/or BGR.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |
| Solution 2 | Panda50 |
