4

within the following code, I use a png image 4096*4096 pixels which includes every possible RGB colors (not twice the same pixel, can be found here http://allrgb.com/starry-night) Then I convert the RGB values to LAB values and I check the range of each of the channels

import cv2 as cv
import numpy as np

im=cv.imread('allrgb.png')


im=im.astype(np.uint8)

colors_lab=cv.cvtColor(im,cv.COLOR_BGR2LAB)

m=np.amin(colors_lab[...,...,0])    

The results are the following :

if the original image has type uint8, R[0,255],G[0,255],B[0,255] gives L[0,255],A[42,226],B[20,223]

if the original image has type float32, R[0,1],G[0,1],B[0,1] gives L[0,100],A[-86.1813,98.2351],B[-107.862,94.4758]

In any case, the Lab range is never the expected one, which is given by open CV documentation

Any idea how to explain that ?

abitbol
  • 53
  • 1
  • 3

1 Answers1

5

The LAB values returned from OpenCV will never lie outside the ranges 0 ≤ L ≤ 100, -127 ≤ a ≤ 127, -127 ≤ b ≤ 127 when converting float images (OpenCV color conversions). When converting 8-bit images, the range of L is multiplied by 255/100, and a and b get an offset of 128 to fill out the 8-bit range.

But no matter the image data type: the LAB color space's gamut exceeds the one of RGB color spaces, see for example the second paragraph in the wikipedia article on LAB.

Thus, when you convert from RGB/BGR to LAB, you will never get the full LAB range, as LAB contains colors that can't be represented in RGB.

w-m
  • 10,772
  • 1
  • 42
  • 49
  • I missed the point here. So what is the best way to convert BGR to CieLAB color space? As stated in the question, OpenCV returns values outside the range for `a` and `b` values that, instead, must be -127 to +127. – decadenza May 09 '20 at 10:30
  • @decadenza the OpenCV doc specifies different ranges for float and 8-bit image conversions, I've tried to clarify that in an edit to the answer. – w-m May 11 '20 at 10:43
  • 2
    Thanks. I've tested some code and the most straightforward way to get correct values from a classic BGR OpenCV image is to do `img.astype("float32") / 255` and then call `imgLab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)`. This because, as indicated in OpenCV documentation, if the input image is float, then the Lab values are not changed! – decadenza May 12 '20 at 11:18
  • @decadenza hello, i want to ask, why the float divide by 255 not 256? – KEZIA ANGELINE May 04 '23 at 14:10
  • @KEZIAANGELINE Because the maximum value for 8 bit color images is 255 = 2^8-1 and you want 255 to become exactly 1. – decadenza May 04 '23 at 14:16