Reputation: 630
When converting images from RGB to LAB with skimage.color.rgb2lab
, I can not really find a documentation, which value range each of the three channels can have in skimage.
My try with the code below proposes that it would be [0.0, 9341.57]
for L
channel, [-6952.27, 7924.33]
for A
channel and [-8700.71, 7621.43]
for B
channel.
But for my eye this does neither look like the typical LBA values ([0, 100]
, [-170, 100]
, [-100, 150]
) one can find in descriptions, nor does the ratio of the numbers seem similar, and also these are generally quite 'odd' looking ranges which do not seem to be normalized to anything at all.
So what values can each channel of an LBA image have, if converted by skimage
?
(And/or where's my error in below try to determine them?)
# WARN: can take a while to calculate
import numpy as np
from skimage.color import rgb2lab
import multiprocessing as mp
colors = [[r,g,b] for r in range(256) for g in range(256) for b in range(256)]
imgs = np.zeros((16777216,1,1,3))
for i, color in enumerate(colors):
imgs[i,:,:] = color
labs = np.zeros((16777216,1,1,3))
pool = mp.Pool(mp.cpu_count()-1)
try:
labs = pool.map(rgb2lab, imgs)
except KeyboardInterrupt:
# without catching this here we will never be able to manually stop running in a sane way
pool.terminate()
pool.close()
pool.join()
print(np.min(labs[:,:,:,0]), np.max(labs[:,:,:,0]), np.min(labs[:,:,:,1]), np.max(labs[:,:,:,1]), np.min(labs[:,:,:,2]), np.max(labs[:,:,:,2]))
# 0.0 9341.570221995466 -6952.27373084052 7924.333617630548 -8700.709143439595 7621.42813486568
Upvotes: 2
Views: 1570
Reputation: 5738
Well, your first mistake is using pure Python loops instead of NumPy expressions, but that's off topic. =) See below for a more efficient version of what you're trying to achieve.
The second mistake is more subtle and possibly the most common mistake from scikit-image newcomers. As of version 0.16, scikit-image uses implicit data ranges for different data types, detailed in this page. np.zeros
defaults to the float data type, so your input array, above, has floats ranging in 0-255, which is a much bigger range than the expected 0-1, so you end up with a similarly bigger range in Lab space.
You can see the range of Lab values using numpy.uint8
values instead of float by changing the imgs
declaration to imgs = np.zeros((16777216, 1, 1, 3), dtype=np.uint8)
. However, complete code for "the NumPy way" below:
In [2]: import numpy as np
In [3]: colors = np.mgrid[0:256, 0:256, 0:256].astype(np.uint8)
In [4]: colors.shape
Out[4]: (3, 256, 256, 256)
In [6]: all_rgb = np.transpose(colors)
In [7]: from skimage import color
In [8]: all_lab = color.rgb2lab(all_rgb)
In [9]: np.max(all_lab, axis=(0, 1, 2))
Out[9]: array([100. , 98.23305386, 94.47812228])
In [10]: np.min(all_lab, axis=(0, 1, 2))
Out[10]: array([ 0. , -86.18302974, -107.85730021])
To illustrate the data range issue, you can see that using floating point input in 0-1 gives you the same result:
In [12]: all_lab2 = color.rgb2lab(all_rgb / 255)
In [13]: np.max(all_lab2, axis=(0, 1, 2))
Out[13]: array([100. , 98.23305386, 94.47812228])
Upvotes: 4