# -*- coding: utf-8 -*-
"""
CIE L*a*b* Colourspace
======================
Defines the *CIE L\\*a\\*b\\** colourspace transformations:
- :func:`colour.XYZ_to_Lab`
- :func:`colour.Lab_to_XYZ`
- :func:`colour.Lab_to_LCHab`
- :func:`colour.LCHab_to_Lab`
See Also
--------
`CIE L*a*b* Colourspace Jupyter Notebook
<http://nbviewer.jupyter.org/github/colour-science/colour-notebooks/\
blob/master/notebooks/models/cie_lab.ipynb>`_
References
----------
- :cite:`CIETC1-482004m` : CIE TC 1-48. (2004). CIE 1976 uniform colour
spaces. In CIE 015:2004 Colorimetry, 3rd Edition (p. 24).
ISBN:978-3-901-90633-6
"""
from __future__ import division, unicode_literals
import numpy as np
from colour.algebra import cartesian_to_polar, polar_to_cartesian
from colour.colorimetry import (ILLUMINANTS,
intermediate_lightness_function_CIE1976,
intermediate_luminance_function_CIE1976)
from colour.models import xy_to_xyY, xyY_to_XYZ
from colour.utilities import (from_range_1, from_range_100, from_range_degrees,
to_domain_1, to_domain_100, to_domain_degrees,
tsplit, tstack)
__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2013-2019 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'
__all__ = ['XYZ_to_Lab', 'Lab_to_XYZ', 'Lab_to_LCHab', 'LCHab_to_Lab']
[docs]def XYZ_to_Lab(
XYZ,
illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']):
"""
Converts from *CIE XYZ* tristimulus values to *CIE L\\*a\\*b\\**
colourspace.
Parameters
----------
XYZ : array_like
*CIE XYZ* tristimulus values.
illuminant : array_like, optional
Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY*
colourspace array.
Returns
-------
ndarray
*CIE L\\*a\\*b\\** colourspace array.
Notes
-----
+----------------+-----------------------+-----------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+================+=======================+=================+
| ``XYZ`` | [0, 1] | [0, 1] |
+----------------+-----------------------+-----------------+
| ``illuminant`` | [0, 1] | [0, 1] |
+----------------+-----------------------+-----------------+
+----------------+-----------------------+-----------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+================+=======================+=================+
| ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] |
| | | |
| | ``a`` : [-100, 100] | ``a`` : [-1, 1] |
| | | |
| | ``b`` : [-100, 100] | ``b`` : [-1, 1] |
+----------------+-----------------------+-----------------+
References
----------
:cite:`CIETC1-482004m`
Examples
--------
>>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
>>> XYZ_to_Lab(XYZ) # doctest: +ELLIPSIS
array([ 41.5278752..., 52.6385830..., 26.9231792...])
"""
X, Y, Z = tsplit(to_domain_1(XYZ))
X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant)))
f_X_X_n = intermediate_lightness_function_CIE1976(X, X_n)
f_Y_Y_n = intermediate_lightness_function_CIE1976(Y, Y_n)
f_Z_Z_n = intermediate_lightness_function_CIE1976(Z, Z_n)
L = 116 * f_Y_Y_n - 16
a = 500 * (f_X_X_n - f_Y_Y_n)
b = 200 * (f_Y_Y_n - f_Z_Z_n)
Lab = tstack([L, a, b])
return from_range_100(Lab)
[docs]def Lab_to_XYZ(
Lab,
illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65']):
"""
Converts from *CIE L\\*a\\*b\\** colourspace to *CIE XYZ* tristimulus
values.
Parameters
----------
Lab : array_like
*CIE L\\*a\\*b\\** colourspace array.
illuminant : array_like, optional
Reference *illuminant* *xy* chromaticity coordinates or *CIE xyY*
colourspace array.
Returns
-------
ndarray
*CIE XYZ* tristimulus values.
Notes
-----
+----------------+-----------------------+-----------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+================+=======================+=================+
| ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] |
| | | |
| | ``a`` : [-100, 100] | ``a`` : [-1, 1] |
| | | |
| | ``b`` : [-100, 100] | ``b`` : [-1, 1] |
+----------------+-----------------------+-----------------+
| ``illuminant`` | [0, 1] | [0, 1] |
+----------------+-----------------------+-----------------+
+----------------+-----------------------+-----------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+================+=======================+=================+
| ``XYZ`` | [0, 1] | [0, 1] |
+----------------+-----------------------+-----------------+
References
----------
:cite:`CIETC1-482004m`
Examples
--------
>>> Lab = np.array([41.52787529, 52.63858304, 26.92317922])
>>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS
array([ 0.2065400..., 0.1219722..., 0.0513695...])
"""
L, a, b = tsplit(to_domain_100(Lab))
X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant)))
f_Y_Y_n = (L + 16) / 116
f_X_X_n = a / 500 + f_Y_Y_n
f_Z_Z_n = f_Y_Y_n - b / 200
X = intermediate_luminance_function_CIE1976(f_X_X_n, X_n)
Y = intermediate_luminance_function_CIE1976(f_Y_Y_n, Y_n)
Z = intermediate_luminance_function_CIE1976(f_Z_Z_n, Z_n)
XYZ = tstack([X, Y, Z])
return from_range_1(XYZ)
[docs]def Lab_to_LCHab(Lab):
"""
Converts from *CIE L\\*a\\*b\\** colourspace to *CIE L\\*C\\*Hab*
colourspace.
Parameters
----------
Lab : array_like
*CIE L\\*a\\*b\\** colourspace array.
Returns
-------
ndarray
*CIE L\\*C\\*Hab* colourspace array.
Notes
-----
+------------+-----------------------+-----------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+=================+
| ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] |
| | | |
| | ``a`` : [-100, 100] | ``a`` : [-1, 1] |
| | | |
| | ``b`` : [-100, 100] | ``b`` : [-1, 1] |
+------------+-----------------------+-----------------+
+------------+-----------------------+-----------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+=================+
| ``LCHab`` | ``L`` : [0, 100] | ``L`` : [0, 1] |
| | | |
| | ``C`` : [0, 100] | ``C`` : [0, 1] |
| | | |
| | ``ab`` : [0, 360] | ``ab`` : [0, 1] |
+------------+-----------------------+-----------------+
References
----------
:cite:`CIETC1-482004m`
Examples
--------
>>> Lab = np.array([41.52787529, 52.63858304, 26.92317922])
>>> Lab_to_LCHab(Lab) # doctest: +ELLIPSIS
array([ 41.5278752..., 59.1242590..., 27.0884878...])
"""
L, a, b = tsplit(Lab)
C, H = tsplit(cartesian_to_polar(tstack([a, b])))
LCHab = tstack([L, C, from_range_degrees(np.degrees(H) % 360)])
return LCHab
[docs]def LCHab_to_Lab(LCHab):
"""
Converts from *CIE L\\*C\\*Hab* colourspace to *CIE L\\*a\\*b\\**
colourspace.
Parameters
----------
LCHab : array_like
*CIE L\\*C\\*Hab* colourspace array.
Returns
-------
ndarray
*CIE L\\*a\\*b\\** colourspace array.
Notes
-----
+-------------+-----------------------+-----------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+=============+=======================+=================+
| ``LCHab`` | ``L`` : [0, 100] | ``L`` : [0, 1] |
| | | |
| | ``C`` : [0, 100] | ``C`` : [0, 1] |
| | | |
| | ``ab`` : [0, 360] | ``ab`` : [0, 1] |
+-------------+-----------------------+-----------------+
+-------------+-----------------------+-----------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+=============+=======================+=================+
| ``Lab`` | ``L`` : [0, 100] | ``L`` : [0, 1] |
| | | |
| | ``a`` : [-100, 100] | ``a`` : [-1, 1] |
| | | |
| | ``b`` : [-100, 100] | ``b`` : [-1, 1] |
+-------------+-----------------------+-----------------+
References
----------
:cite:`CIETC1-482004m`
Examples
--------
>>> LCHab = np.array([41.52787529, 59.12425901, 27.08848784])
>>> LCHab_to_Lab(LCHab) # doctest: +ELLIPSIS
array([ 41.5278752..., 52.6385830..., 26.9231792...])
"""
L, C, H = tsplit(LCHab)
a, b = tsplit(
polar_to_cartesian(tstack([C, np.radians(to_domain_degrees(H))])))
Lab = tstack([L, a, b])
return Lab