0

I'm trying to load a CIE Lab* image using openCV in C++. Online I can find only examples that load an RGB image and convert it into a LAB image but I already have the LAB image so how can I load it and than access to the values of L, a and b?

The only way I find is to load the LAB image considering it an RGB image and convert it into a Lab image using:

cvtColor(source, destination, CV_BGR2Lab);

But I think this is not a good way to solve the problem because if I do this, the converted image looks very different from the original.

With a test image and the following code:

    originalImage = imread(originalImagePath, CV_LOAD_IMAGE_UNCHANGED);
    cout << originalImage.type() << endl;
    Mat originalImageSplitted[3]; 
    split(originalImage, originalImageSplitted);
    cout << originalImageSplitted[0] << endl;
    cout << originalImageSplitted[1] << endl;
    cout << originalImageSplitted[2] << endl;

I get the result:

0
[]
[]
[]
Davide57
  • 49
  • 1
  • 7
  • What file format to start with? – Dan Mašek Oct 15 '18 at 17:53
  • @DanMašek The images are in .tif format. – Davide57 Oct 15 '18 at 17:54
  • 1
    Hmm. So if you just load it as is, and treat it as `Lab` (i.e. don't do any conversions), you get nonsense? What if you load and reverse the channels, and then treat it as `Lab`? (The reasoning here is that the channels may have been swapped due to OpenCV using BGR representation). – Dan Mašek Oct 15 '18 at 17:59
  • @DanMašek if I just load the image and than split it using split() function to check the 3 channels I get nonsense values. For example, I get L* values higher than 100 and this is not possible... – Davide57 Oct 15 '18 at 18:03
  • Could you upload the sample image, so we can trying some things out? – Dan Mašek Oct 15 '18 at 18:06
  • @DanMašek I can't upload the image but I can tell you that it's a Lab 8bit image in tif format... but loading with the imread I get values higher than 100 into all the three channels after splitting... – Davide57 Oct 15 '18 at 18:09
  • I believe you, unfortunately that doesn't really help me reproduce the problem here... and I'm sorry, but I don't feel like spending time to find or manufacture something I could use before I can dig into the issue. – Dan Mašek Oct 15 '18 at 18:18
  • @MarkSetchell added a sample and I added the result with it on the main topic – Davide57 Oct 15 '18 at 22:03

3 Answers3

2

Not really an answer, but too much for a comment.

You can make a Lab colourspace TIF file for testing like this with ImageMagick from the Terminal in Linux, macOS or Windows:

convert -depth 8 xc:black xc:white xc:red xc:lime xc:blue +append -colorspace Lab result.tif

That will look like this if I scale it up as it is currently only 5 pixels wide and 1 pixel tall:

enter image description here

You can then dump the pixels to see their values and hopefully work out what OpenCV is doing:

convert result.tif txt:

Sample Output

# ImageMagick pixel enumeration: 5,1,65535,cielab
0,0: (0,-0.5,-0.5)  #000000  cielab(0%,-0.000762951%,-0.000762951%)          <--- black pixel
1,0: (65535,-0.5,-0.5)  #FF0000  cielab(100%,-0.000762951%,-0.000762951%)    <--- white pixel
2,0: (34952,20559.5,17218.5)  #885043  cielab(53.3333%,31.3718%,26.2737%)    <--- red pixel
3,0: (57568,-22102.5,21330.5)  #E00053  cielab(87.8431%,-33.7263%,32.5483%)  <--- green pixel
4,0: (21074,20302.5,-27756.5)  #524F00  cielab(32.1569%,30.9796%,-42.3537%)  <--- blue pixel

Looking at the red pixel, you get:

  • L=53.33%
  • a=31.37% of 256, i.e. 80.3
  • b=26.27% of 256, i.e. 67.2
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • 1
    I understand. I am trying to give you, and anyone else trying to help you, a TIFF file with known content to test with because you have not been able to supply one for us. – Mark Setchell Oct 15 '18 at 21:37
  • Oh! Thank you, now I got it, really useful! @DanMašek can you try with this? – Davide57 Oct 15 '18 at 21:40
  • 1
    You now have a Lab TIFF file where you know the first pixel is white, the second is black, the third is red and so on. So open the file in C++ with OpenCV with `CV_LOAD_IMAGE_UNCHANGED` and see what you get for these 5 pixels. – Mark Setchell Oct 15 '18 at 21:41
  • I get a strange result, I add it on the main topic. @MarkSetchell – Davide57 Oct 15 '18 at 21:57
  • 1
    Thanks for the imagemagick wizardry, Mark :) | Interestingly enough, it seems that OpenCV will automagically convert this back to BGR on loading. | I just had a chat with OP, and it seems the rest of the issues stem from misreading the docs regarding ranges of the components in an 8bit Lab image, as well as trying to visualize a Lab image directly with `imshow`. – Dan Mašek Oct 15 '18 at 22:45
1

To keep the image unchanged you should read it into a Mat image similarly:

Mat image; image = imread(<path_of_image>, CV_LOAD_IMAGE_UNCHANGED)

In this case the second argument should preserve your image color channels as is.

Philip Bal
  • 23
  • 9
  • If I try to do that and than I split the image using split() function I get values in the first channel that are higher than 100 but the maximum value of L* channel is 100. – Davide57 Oct 15 '18 at 18:00
  • Are you sure that the L channel is indeed the 1st channel? If so, it is probably just an issue with the format, so if you scaled the values accordingly, perhaps it would give you the correct expected L value? Ie lets say its a channel similar to RGB with 255 max value, can you create a proportion for your specific use case to compare to a max value of 100. – Philip Bal Oct 15 '18 at 18:03
  • Even looking at the other channels I always get values higher than 100 (over 190 too!). How should I know the correct scale to convert it? – Davide57 Oct 15 '18 at 18:06
  • The first step would be to see what kind of image it is being read in as with img.type(); and then attempting to either convert to your desired type, or to try to scale channels accordingly, although the latter is not technically correct, but may work depending on your use case. – Philip Bal Oct 15 '18 at 18:29
  • So it consider the image as a 16bit instead of a 8bit. So should I divide the values by 2? – Davide57 Oct 15 '18 at 19:32
  • I'm not 100% of how Lab images work, so I would recommending checking to make sure – Philip Bal Oct 15 '18 at 19:47
1

With @DanMašek using @MarkSetchell image we solved the problem.

Using imread function the image is automatically converted into an RGB image so it's needed to convert it into a Lab image again. Another problem is releated to 8bit images. The resulted image has modified values of L,a and b following this rule:

L * 255/100 a as a+128 b as b+128

So I solved doing the following:

    originalImage = imread(originalImagePath, CV_LOAD_IMAGE_UNCHANGED);
    Mat originalImageLab;
    cvtColor(originalImage, originalImageLab, COLOR_RGB2Lab);
    Mat originalImageSplitted[3];
    split(originalImageLab, originalImageSplitted);

Thank you all!

Davide57
  • 49
  • 1
  • 7