2

I am trying to convert an image from RGB to XYZ using scikit-image. I found out that there are some differences depending the input type:

from numpy import array,uint8
import skimage.color

rgb = array([array([[56,79,132],[255,100,70]])]) 
i1 = skimage.color.rgb2xyz(rgb)#rgb.dtype ->dtype('int32')
i2 = skimage.color.rgb2xyz(rgb.astype(uint8))
i3 = skimage.color.rgb2xyz(rgb.astype(float))

print i1[0,1,:]
print i2[0,1,:]
print i3[0,1,:]

This is the output:

[  5.55183419e-09   4.73226247e-09   3.02426596e-09]
[ 0.46907236  0.3082294   0.09272133]
[ 240644.54537677  153080.21825017   39214.47581034]

The cause of the differences is the function img_to_float which is used inside rgb2xyz (see this question).

But I am wondering: What is the correct way to use rgb2xyz?

Regarding this question there are multiple solutions, depending on the formula, but again: what is the correct image type that is required by rgb2xyz? It seems that unit8, but why? Thanks!

Community
  • 1
  • 1
phyrox
  • 2,423
  • 15
  • 23
  • There is a reference that helps to understand this: http://scikit-image.org/docs/0.9.x/user_guide/data_types.html – phyrox Jan 31 '14 at 09:01

1 Answers1

0

The following code should be self explanatory, but floating point values should have a range in (0, 1), and integer type have their full range mapped to (0, 1) (for unsigned types) or (-1, 1) (for signed types):

>>> from numpy import int32
>>> skimage.color.rgb2xyz((rgb / 255 * (2**31 - 1)).astype(int32))
array([[[ 0.08590003,  0.08097913,  0.2293394 ],
        [ 0.46907236,  0.3082294 ,  0.09272133]]])
>>> skimage.color.rgb2xyz(rgb.astype(uint8))
array([[[ 0.08590003,  0.08097913,  0.2293394 ],
        [ 0.46907236,  0.3082294 ,  0.09272133]]])
>>> skimage.color.rgb2xyz(rgb.astype(float) / 255)
array([[[ 0.08590003,  0.08097913,  0.2293394 ],
        [ 0.46907236,  0.3082294 ,  0.09272133]]])
Jaime
  • 65,696
  • 17
  • 124
  • 159
  • Thanks @Jaime! So you are suggesting that the correct use of `rgb2xyz` is having the input scaled to the correct range, aren't you? – phyrox Jan 29 '14 at 15:16
  • 1
    Well, the normal usage would be to have everything be `np.uint8` with the usual 0-255 range. If you switch to floats, remember to divide by 255. And don't use other int type unless you know what (and why) you are doing... – Jaime Jan 29 '14 at 16:56
  • 2
    No need to do any manual scaling if you use the appropriate tools: ``img_as_float``, ``img_as_ubyte``, etc. – Stefan van der Walt Jan 29 '14 at 23:41