Pixel values differ between opencv and matlab

790 Views Asked by At

When I am displaying the pixel values of an image (a RGB image converted to grayscale) using "display" function in matlab, I found that the pixel values are less than 1 (all values are between 0 and 1). Whereas when I do the same in opencv, I am getting higher values. Why the change in values happen ? Open CV code and matlab code is as follows:

for (int i = 0; i < img1.rows; i++)
{
    for (int j = 0; j < img1.cols; j++)
    {
        cout << (unsigned int)img1.at<uchar>(i, j) << endl;
    }
}

Matlab code:

gI=rgb2gray(I);
imshow(gI);
2

There are 2 best solutions below

3
On BEST ANSWER

Sorry to disappoint you. No one guarantees that the conversion of RGB to gray-scale will yield the same result. There are 2 reasons

  1. The conversion is not a mathematical correct formula but rather subjective issue. Over the course of the last 50 years a few different standards (mainly for color television supporting greyscale signals) were written of how to convert RGB to gray level. Different standards lead to almost identical visible results, though the actual values of the pixels differ a bit (~roughly 0.2%). You can read more about the standards in Wikipedia. For example: One standard defines the conversion of RGB to gray while another defines conversion of RGB to YUV and taking Y channel as the gray scale. There are few other standards as well (preserving luminosity, intensity, contrast, etc). Since the preference of the standards change over time, it is hard to know how exactly the RGB to gray is implemented. Here is an example of 3 different methods. Open CV uses completely different method (0.299f*RED + 0.587f*GREEN + 0.114f*BLUE Here) while Matlab uses another method (0.2989*RED + 0.587*GREEN + 0.1140*BLUE. Here). Note the difference between openCV 0.299 and Matlabs 0.2989. More information can be found in this answer (here)
  2. Second reason - different floating point representation across hardware and software. Floating point computation (regardless whether it is double or float) is not precise and depends on the specific hardware you use, type of compiler with witch you build a software and specific compiler directives. Same mathematical calculation can yield slightly different results on different computers or even on the same computer in 2 different programs. So unfortunately you will not get exactly the same results for RGB to gray conversion but if you round the values to range of [0..255] you will typically get a discrepancy of no more than 2 levels. I would say that in 99.9% pixels you will get the same value and in the others difference of 1. 2 is very rare and I have never seen a difference of 3, unless you do few sequential conversions like RGB->XYZ->HSV->YUV
0
On

My Mat is of type 8UC3. How to convert normalised double value of MATLAB to 8UC3 ? Multipying by 255 alone is enough?


In the case of 8UC3 bytes then yes its enough to just multiply by 255. They are designed to work that way. The 3 in 8UC3 means the three channels Red, Green and Blue

Anyway, converting between 0 to 255 range values and 0.0 to 1.0 range values

//Psuedo-code formula:

col_val = 210; //range 0-255
normalised = col_val / 255; //always divide by 255 for a normalised to "1.0" version

normal_reverse_to255 = normalised * 255; //make it back into "0 to 255" range

expected result :
col_val = 210 //original value before normalised
normalised = 0.8235 //...294117647058 etc etc //after normalised to 0.0 to 1.0 range
normal_reverse_to255 = 210; //multiply result is same as original value

Hope that's helpful to you.

Edit:
I just realised you are using gI=rgb2gray(I); to get your grayscale image.

try something like:
cvtColor(src,dst,CV_GRAY2RGB); as hijacked from this answer