ENH slight cleanup, fixed *1000 bug, added test and rgb2lab convenience.

This commit is contained in:
Andreas Mueller
2012-07-26 22:44:02 +01:00
parent 8cd912a894
commit 3448e419b3
2 changed files with 91 additions and 63 deletions
+70 -49
View File
@@ -45,7 +45,7 @@ from __future__ import division
__all__ = ['convert_colorspace', 'rgb2hsv', 'hsv2rgb', 'rgb2xyz', 'xyz2rgb',
'rgb2rgbcie', 'rgbcie2rgb', 'rgb2grey', 'rgb2gray', 'gray2rgb',
'xyz2lab', 'lab2xyz',
'xyz2lab', 'lab2xyz', 'lab2rgb', 'rgb2lab'
]
__docformat__ = "restructuredtext en"
@@ -547,21 +547,6 @@ def gray2rgb(image):
return np.dstack((image, image, image))
#----------------------
# Constants for CIE LAB
#----------------------
_one_third = 1.0 / 3.0
_sixteen_hundred_sixteenth = 16.0 / 116.0
# Observer= 2A, Illuminant= D65
_xref = 0.95047
_yref = 1.
_zref = 1.08883
_inv_xref = 1.0 / _xref
_inv_yref = 1.0 / _yref
_inv_zref = 1.0 / _zref
#--------------------------------------------------------------
# The conversion functions that make use of the constants above
#--------------------------------------------------------------
@@ -588,50 +573,47 @@ def xyz2lab(xyz):
-----
Observer= 2A, Illuminant= D65
CIE XYZ tristimulus values x_ref = 95.047, y_ref = 100., z_ref = 108.883
References
----------
.. [1] http://www.easyrgb.com/index.php?X=MATH&H=07#text7
.. [2] http://en.wikipedia.org/wiki/Lab_color_space
Examples
--------
>>> import os
>>> from skimage import data_dir
>>> from skimage import data_dir
>>> from skimage.color import rgb2xyz, xyz2lab
>>> from skimage.io import imread
>>> lena = imread(os.path.join(data_dir, 'lena.png'))
>>> lena_xyz = rgb2xyz(lena)
>>> lena_lab = xyz2lab(lena_xyz)
"""
arr = _prepare_colorarray(xyz).copy()
out = np.empty_like(arr)
arr = _prepare_colorarray(xyz)
#----------------------
# Constants for CIE LAB
#----------------------
# Observer= 2A, Illuminant= D65
ref_white = np.array([0.95047, 1., 1.08883])
# scale by CIE XYZ tristimulus values of the reference white point
x, y, z = arr[:, :, 0], arr[:, :, 1], arr[:, :, 2]
x *= _inv_xref
y *= _inv_yref
z *= _inv_zref
arr = arr / ref_white
# Nonlinear distortion and linear transformation
mask = arr > 0.008856
arr[mask] = np.power(arr[mask], _one_third)
arr[~mask] = 7.787 * arr[~mask] + _sixteen_hundred_sixteenth
arr[mask] = np.power(arr[mask], 1. / 3.)
arr[~mask] = 7.787 * arr[~mask] + 16. / 116.
x, y, z = arr[:, :, 0], arr[:, :, 1], arr[:, :, 2]
# Vector scaling
L = (116. * y) - 16.
a = 500.0 * (x - y)
b = 200.0 * (y - z)
# -- output
out[:, :, 0] = L
out[:, :, 1] = a
out[:, :, 2] = b
return np.dstack([L, a, b])
# remove NaN
out[np.isnan(out)] = 0
return out
def lab2xyz(lab):
"""CIE-LAB to XYZcolor space conversion.
@@ -664,30 +646,69 @@ def lab2xyz(lab):
"""
arr = _prepare_colorarray(lab).copy()
out = np.empty_like(arr)
L, a, b = arr[:, :, 0], arr[:, :, 1], arr[:, :, 2]
y = (L + 16.) / 116.
x = (a / 500.) + y
z = y - (b / 200.)
out[:, :, 0] = x
out[:, :, 1] = y
out[:, :, 2] = z
out = np.dstack([x, y, z])
mask = out > 0.2068966
out[mask] = np.power(out[mask], 3.)
out[~mask] = (out[~mask] - _sixteen_hundred_sixteenth) / 7.787*1000
out[~mask] = (out[~mask] - 16.0 / 116.) / 7.787
# rescale Observer= 2 deg, Illuminant= D65
#x, y, z = out[:, :, 0], out[:, :, 1], out[:, :, 2]
out[:, :, 0] *= _xref
out[:, :, 1] *= _yref
out[:, :, 2] *= _zref
# remove NaN
out[np.isnan(out)] = 0
ref_white = np.array([0.95047, 1., 1.08883])
out *= ref_white
return out
def rgb2lab(rgb):
"""RGB to lab color space conversion.
Parameters
----------
rgb : array_like
The image in RGB format, in a 3-D array of shape (.., .., 3).
Returns
-------
out : ndarray
The image in Lab format, in a 3-D array of shape (.., .., 3).
Raises
------
ValueError
If `rgb` is not a 3-D array of shape (.., .., 3).
Notes
-----
This function uses rgb2xyz and xyz2lab.
"""
return xyz2lab(rgb2xyz(rgb))
def lab2rgb(lab):
"""Lab to RGB color space conversion.
Parameters
----------
rgb : array_like
The image in Lab format, in a 3-D array of shape (.., .., 3).
Returns
-------
out : ndarray
The image in RGB format, in a 3-D array of shape (.., .., 3).
Raises
------
ValueError
If `lab` is not a 3-D array of shape (.., .., 3).
Notes
-----
This function uses lab2xyz and xyz2rgb.
"""
return xyz2rgb(lab2xyz(lab))
+21 -14
View File
@@ -25,6 +25,7 @@ from skimage.color import (
convert_colorspace,
rgb2grey, gray2rgb,
xyz2lab, lab2xyz,
lab2rgb, rgb2lab
)
from skimage import data_dir
@@ -44,18 +45,17 @@ class TestColorconv(TestCase):
colbars_point75 = colbars * 0.75
colbars_point75_array = np.swapaxes(colbars_point75.reshape(3, 4, 2), 0, 2)
xyz_array = np.array([[[0.4124, 0.21260, 0.01930]], #red
[[0, 0, 0]], #black
[[.9505, 1., 1.089]], #white
[[.1805, .0722, .9505]], #blue
[[.07719, .15438, .02573]], #green
xyz_array = np.array([[[0.4124, 0.21260, 0.01930]], # red
[[0, 0, 0]], # black
[[.9505, 1., 1.089]], # white
[[.1805, .0722, .9505]], # blue
[[.07719, .15438, .02573]], # green
])
lab_array = np.array([[[53.233, 80.109, 67.220]], #red
[[0.,0.,0.]], #black
[[100.0, 0.005, -0.010]], #white
[[32.303, 79.197, -107.864]], #blue
[[46.229, -51.7, 49.898]], #green
lab_array = np.array([[[53.233, 80.109, 67.220]], # red
[[0., 0., 0.]], # black
[[100.0, 0.005, -0.010]], # white
[[32.303, 79.197, -107.864]], # blue
[[46.229, -51.7, 49.898]], # green
])
# RGB to HSV
@@ -167,10 +167,17 @@ class TestColorconv(TestCase):
# test matrices for xyz2lab and lab2xyz generated using http://www.easyrgb.com/index.php?X=CALC
# Note: easyrgb website displays xyz*100
def test_xyz2lab(self):
assert_array_almost_equal(xyz2lab(self.xyz_array), self.lab_array, decimal=3)
assert_array_almost_equal(xyz2lab(self.xyz_array),
self.lab_array, decimal=3)
def test_lab2xyz(self):
assert_array_almost_equal(lab2xyz(self.lab_array),
self.xyz_array, decimal=3)
def test_lab_rgb_roundtrip(self):
img_rgb = img_as_float(self.img_rgb)
assert_array_almost_equal(lab2rgb(rgb2lab(img_rgb)), img_rgb)
def test_lab2xyz(self):
assert_array_almost_equal(lab2xyz(self.lab_array), self.xyz_array, decimal=3)
def test_gray2rgb():
x = np.array([0, 0.5, 1])