Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cvtColor for BGR to YUV 4:2:0 returns darker image #13066

Open
navid-mahmoudian opened this issue Nov 7, 2018 · 5 comments
Open

cvtColor for BGR to YUV 4:2:0 returns darker image #13066

navid-mahmoudian opened this issue Nov 7, 2018 · 5 comments

Comments

@navid-mahmoudian
Copy link

System information (version)
  • OpenCV => 3.1
  • Operating System / Platform => Ubuntu 16.04 64 bit
  • Compiler => gcc version 5.4.0
Detailed description

The grayscale image that comes from cvtColor function with COLOR_BGR2YUV_I420 (or COLOR_BGR2YUV_IYUV), which converts RGB to YUV 4:2:0 family, is darker than the grayscale image that comes from COLOR_BGR2GRAY. I think in theory they should be the same because the Y channel is actually the grayscale image. Here is a simple code that I used for testing:

Steps to reproduce
    cv::Mat inputImage=cv::imread("Lenna.png");
    cv::Mat gray_BGR2GRAY;
    cv::cvtColor(inputImage, gray_BGR2GRAY, cv::COLOR_BGR2GRAY);
    imshow("gray_BGR2GRAY", gray_BGR2GRAY);
    cv::Mat mat_BGR2YUV_I420;
    cv::cvtColor(inputImage, mat_BGR2YUV_I420, cv::COLOR_BGR2YUV_I420);
    cv::Mat grayPart_BGR2YUV_I420(mat_BGR2YUV_I420, cv::Rect(0, 0, inputImage.cols, inputImage.rows));
    imshow("grayPart_BGR2YUV_I420", grayPart_BGR2YUV_I420);
    cv::waitKey(0);

for reading the grayscale part I used the answer to the following question:
http://answers.opencv.org/question/100149/how-to-get-y-u-v-from-image/

@alalek
Copy link
Member

alalek commented Nov 7, 2018

In theory there are multiple color spaces and conversion formulas.
OpenCV uses some of them (currently it can't be configured).

OpenCV 3.1

It is too old (>2 years). Many changes have been applied since this release including YUV calculation updates.

@navid-mahmoudian
Copy link
Author

I installed opencv 3.4.1 and problem still exists.

@navid-mahmoudian
Copy link
Author

It is funny that when we use COLOR_BGR2GRAY opencv uses
Y <- 0.299 * R + 0.587 * G + 0.114 * B
which is in range [0-255], but when we use YUV420 opencv uses
Y = ((66 * R + 129 * G + 25 * B +128) >> 8) + 16
which makes Y value in range [16-235]. This inconsistency of computing Y channel between different options makes cvtColor for yuv420 useless.

@alalek
Copy link
Member

alalek commented Nov 7, 2018

There are multiple standards.
Some of them about the luma channel calculation/representation:

https://en.wikipedia.org/wiki/Rec._601

For each 8 bit luminance sample, the nominal value to represent black is 16 and the value for white is 235.

https://en.wikipedia.org/wiki/Rec._709

HDTV according to Rec. 709 forms luma (Y’) using R’G’B’ coefficients 0.2126, 0.7152, and 0.0722. This means that unlike Rec. 601, the coefficients match the primaries and white points, so luma corresponds more closely to luminance. Some experts feel that the advantages of correct matrix coefficients do not justify the change from Rec. 601 coefficients.[5]

https://en.wikipedia.org/wiki/Rec._2020

The luma (Y′) signal for YCbCr is calculated as the weighted average Y′ = KR⋅R′ + (1−KR−KB)⋅G′ + KB⋅B′, using the gamma-corrected RGB values (denoted R′G′B′) and the weighting coefficients KR = 0.2627, KG = 0.678 and KB = 0.0593.

https://en.wikipedia.org/wiki/YUV

defines 0.299 * R + 0.587 * G + 0.114 * B coefficients.

@navid-mahmoudian
Copy link
Author

Thanks a lot for your response.
So there is no implementation of yuv420 with 0.299 * R + 0.587 * G + 0.114 * B in OpenCV. right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants