"""
IHLS Colour Encoding
====================
Define the :math:`IHLS` (Improved HLS) colourspace related transformations:
- :func:`colour.RGB_to_IHLS`
- :func:`colour.IHLS_to_RGB`
References
----------
- :cite:`Hanbury2003` : Hanbury, A. (2003). A 3D-Polar Coordinate Colour
Representation Well Adapted to Image Analysis. In J. Bigun & T. Gustavsson
(Eds.), Image Analysis (pp. 804-811). Springer Berlin Heidelberg.
ISBN:978-3-540-45103-7
"""
from __future__ import annotations
import numpy as np
from colour.algebra import sdiv, sdiv_mode, vecmul
from colour.hints import ArrayLike, NDArrayFloat
from colour.utilities import (
from_range_1,
to_domain_1,
tsplit,
tstack,
zeros,
)
__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "colour-developers@colour-science.org"
__status__ = "Production"
__all__ = [
"RGB_to_IHLS",
"IHLS_to_RGB",
]
MATRIX_RGB_TO_YC_1_C_2: NDArrayFloat = np.array(
[
[0.2126, 0.7152, 0.0722],
[1, -0.5, -0.5],
[0, -np.sqrt(3) / 2, np.sqrt(3) / 2],
]
)
"""*RGB* colourspace to *YC_1C_2* colourspace matrix."""
MATRIX_YC_1_C_2_TO_RGB: NDArrayFloat = np.linalg.inv(MATRIX_RGB_TO_YC_1_C_2)
"""*YC_1C_2* colourspace to *RGB* colourspace matrix."""
[docs]
def RGB_to_IHLS(RGB: ArrayLike) -> NDArrayFloat:
"""
Convert from *RGB* colourspace to *IHLS* (Improved HLS) colourspace.
Parameters
----------
RGB
*RGB* colourspace array.
Returns
-------
:class:`numpy.ndarray`
*HYS* colourspace array.
Notes
-----
+------------+-----------------------+---------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``RGB`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
+------------+-----------------------+---------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``HYS`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
References
----------
:cite:`Hanbury2003`
Examples
--------
>>> RGB = np.array([0.45595571, 0.03039702, 0.04087245])
>>> RGB_to_IHLS(RGB) # doctest: +ELLIPSIS
array([ 6.2616051..., 0.1216271..., 0.4255586...])
"""
RGB = to_domain_1(RGB)
R, G, B = tsplit(RGB)
Y, C_1, C_2 = tsplit(vecmul(MATRIX_RGB_TO_YC_1_C_2, RGB))
C = np.hypot(C_1, C_2)
with sdiv_mode():
C_1_C = sdiv(C_1, C)
arcos_C_1_C_2 = zeros(C_1_C.shape)
arcos_C_1_C_2[C_1_C != 0] = np.arccos(C_1_C[C_1_C != 0])
H = np.where(C_2 <= 0, arcos_C_1_C_2, (np.pi * 2) - arcos_C_1_C_2)
S = np.maximum(np.maximum(R, G), B) - np.minimum(np.minimum(R, G), B)
HYS = tstack([H, Y, S])
return from_range_1(HYS)
[docs]
def IHLS_to_RGB(HYS: ArrayLike) -> NDArrayFloat:
"""
Convert from *IHLS* (Improved HLS) colourspace to *RGB* colourspace.
Parameters
----------
HYS
*IHLS* colourspace array.
Returns
-------
:class:`numpy.ndarray`
*RGB* colourspace array.
Notes
-----
+------------+-----------------------+---------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``HYS`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
+------------+-----------------------+---------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``RGB`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
References
----------
:cite:`Hanbury2003`
Examples
--------
>>> HYS = np.array([6.26160518, 0.12162712, 0.42555869])
>>> IHLS_to_RGB(HYS) # doctest: +ELLIPSIS
array([ 0.4559557..., 0.0303970..., 0.0408724...])
"""
H, Y, S = tsplit(to_domain_1(HYS))
pi_3 = np.pi / 3
k = np.floor(H / pi_3)
H_s = H - k * pi_3
C = (np.sqrt(3) * S) / (2 * np.sin(2 * pi_3 - H_s))
C_1 = C * np.cos(H)
C_2 = -C * np.sin(H)
RGB = vecmul(MATRIX_YC_1_C_2_TO_RGB, tstack([Y, C_1, C_2]))
return from_range_1(RGB)