cs0815
cs0815

Reputation: 17388

color space transformation in opencv (RGB -> LAB) - red does not produce expected values

The following creates a red image using the RGB color 255,0,0

import numpy as np
import matplotlib.pyplot as plt
import cv2

width = 5
height = 2

array = np.zeros([height, width, 3], dtype=np.uint8)
array[:,:] = [255, 0, 0] # make it red

print(array)

plt.imshow(array)
plt.show()

Outputs:

[[[255   0   0]
  [255   0   0]
  [255   0   0]
  [255   0   0]
  [255   0   0]]

 [[255   0   0]
  [255   0   0]
  [255   0   0]
  [255   0   0]
  [255   0   0]]]

enter image description here

If I transform the array into the LAB space:

array = cv2.cvtColor(array, cv2.COLOR_BGR2LAB)

print(array)

The results look like this:

[[[ 82 207  20]
  [ 82 207  20]
  [ 82 207  20]
  [ 82 207  20]
  [ 82 207  20]]

 [[ 82 207  20]
  [ 82 207  20]
  [ 82 207  20]
  [ 82 207  20]
  [ 82 207  20]]]

According to http://colorizer.org/ the value of red should be:

lab(53.23, 80.11, 67.22)

Why is opencv producing different values? Am I missing something? Is there a site where I can lookup, for example, red in Lab color numbers for opebcv? Thanks.

PS:

One issue is that I used COLOR_BGR2LAB instead of COLOR_RGB2LAB (thanks Mark Setchell) but it still does not result in the expected vector of 53.23, 80.11, 67.22 it produces: 54.4 83.2 78. which is not close but not the same ...

import numpy as np
import matplotlib.pyplot as plt
import cv2

width = 5
height = 2

array = np.zeros([height, width, 3], dtype=np.uint8)
array[:,:] = [255, 0, 0] # make it red

print(array)

array = cv2.cvtColor(array, cv2.COLOR_RGB2LAB)
array = array / 2.5

print(array)

Upvotes: 1

Views: 2480

Answers (2)

Ana
Ana

Reputation: 51

Actually you have to divide by 255. This way you have the same results as SKimage and Matlab...

cv2.cvtColor(array.astype('float32')/255., cv2.COLOR_RGB2Lab)

otherwise it gives wrong ranges. you can change the value of the array and check:

width = 5
height = 1

array = np.zeros([height, width, 3], dtype=np.uint8)
array[:,:] = [150, 20, 255] # make it red

print(array)

array2=rgb2lab(array )
print(array2.max(), array2.min())

array3 = cv2.cvtColor(array, cv2.COLOR_RGB2Lab)
print(array3 .max(), array3 .min())

array4 = cv2.cvtColor(array.astype('float32'), cv2.COLOR_RGB2Lab)

print(array4 .max(), array4 .min())

array5 = cv2.cvtColor(array.astype('float32')/255., cv2.COLOR_RGB2Lab)

print(array5 .max(), array5 .min())

Upvotes: 0

Mark Setchell
Mark Setchell

Reputation: 207465

You created the image in RGB order, so this

array = cv2.cvtColor(array, cv2.COLOR_BGR2LAB)

should be:

array = cv2.cvtColor(array, cv2.COLOR_RGB2LAB)

If you display it using OpenCV cv2.imshow(array) and cv2.waitKey() you will see OpenCV considers it blue.


As regards the discrepancy you see between the online converter and OpenCV, I can only assume this has something to do with rounding errors arising from using uint8 for the RGB values. If you convert to float type, the issue goes away:

Lab = cv2.cvtColor(array.astype(np.float32), cv2.COLOR_RGB2LAB)

# Result
array([[[53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125]],

       [[53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125],
        [53.240967, 80.09375 , 67.203125]]], dtype=float32)

As an aside, I note that scikit-image chooses to automatically return you a float when you pass it uint8:

from skimage import color
import numpy as np

# Make a rather small red image
array = np.full((1, 1, 3), [255,0,0], dtype=np.uint8)

# Convert to Lab with scikit-image
Lab = color.rgb2lab(array)

# Result
array([[[53.24058794, 80.09230823, 67.20275104]]])

Just for fun, while we are at it, check what ImageMagick makes it:

magick xc:red -colorspace lab txt:
# ImageMagick pixel enumeration: 1,1,65535,cielab
0,0: (34891.4,53351.7,17270.9)  #884BD068C376 cielab(53.2408,80.0943,67.202)

Upvotes: 2

Related Questions