matlabopencvrgbcolor-conversion

Why OpenCV RGB to YCbCr conversion doesn't give the same result as conversion in matlab using ycbcr2rgb function?


I am trying to replicate my matlab code into C with OpenCV. Here I have a step where I need to convert the image from rgb to ycbcr and do histogram equalization. But the results of both in matlab and C are very different.

I am using Matlab R2016b and OpenCV 4.0.0

Which one is the correct way to do and why I am seeing this difference?

Steps I am following in MATLAB and C are stated below:

C Steps:

  1. Read an Image frame in RGB using imread()

  2. Converted the RGB image to YCBCr using cv::cvtColor()

  3. Checked the values of Y channel

    cv::Mat image, ycbcr; vector splitted; image = imread("image_name.jpg"); cv::cvtColor(image, ycbcr, COLOR_BGR2YCrCb); cv::split(ycbcr, splitted) cv::equalizeHist(splitted[0],splitted[0]); cv::merge(dst_host,ycbcr); cv::cvtColor(ycbcr, image, COLOR_YCrCb2BGR); imshow("Equalized", image);

MATLAB steps:

  1. Read an Image frame in RGB using imread()

  2. Converted the RGB image to YCBCr using rgb2ycbcr()

  3. Checked the values of Y channel

    im = imread('image_name.jpg'); ycbcr_im = rgb2ycbcr(im); ycbcr_im(:,:,1) = histeq(ycbcr_im(:,:,1)); im = ycbcr2rgb(ycbcr_im); imshow(im);

So I checked the results after converting from rgb to ycbcr in OpenCV and MATLAB and the result are different in the conversion itself.


Solution

  • By looking at the documentation of OpenCV and Matlab color conversion. I found the following. In my observation, there is a major difference in the algorithm and implementation.

    In Matlab, the rgb2ycbcr() function converts the color in digital formula which is

    Y = 16+ (65.481 * R + 128.553 * G + 24.966 * B)
    Cb = 128+ (-37.797 * R - 74.203 * G + 112.0 * B)
    Cr = 128+ (112.0 * R - 93.786 * G - 18.214 * B)
    

    If the input is uint8, then YCBCR is uint8 where Y is in the range [16 235], and Cb and Cr are in the range [16 240].

    But in OpenCV, the conversion is done in analog formula which is,

    Y = 0.299 * R+ 0.587 * G+ 0.114 * B
    Cb = -0.168736 * R - 0.331264 * G + 0.5 * B
    Cr = 0.5 * R - 0.418688 * G - 0.081312 * B
    

    If the input is uint8, then YCBCR is uint8 where Y and Cb and Cr are in the range [0 255]. This is the reason why you are getting a different result.