Coverage for models/rgb/hanbury2003.py: 54%
39 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
1"""
2IHLS Colour Encoding
3====================
5Define the :math:`IHLS` (Improved HLS) colourspace encoding and decoding
6transformations. The :math:`IHLS` colourspace provides a 3D-polar coordinate
7colour representation that improves upon the standard HLS model for image
8analysis applications.
10- :func:`colour.RGB_to_IHLS`
11- :func:`colour.IHLS_to_RGB`
13References
14----------
15- :cite:`Hanbury2003` : Hanbury, A. (2003). A 3D-Polar Coordinate Colour
16 Representation Well Adapted to Image Analysis. In J. Bigun & T. Gustavsson
17 (Eds.), Image Analysis (pp. 804-811). Springer Berlin Heidelberg.
18 ISBN:978-3-540-45103-7
19"""
21from __future__ import annotations
23import numpy as np
25from colour.algebra import sdiv, sdiv_mode, vecmul
26from colour.hints import ( # noqa: TC001
27 Domain1,
28 NDArrayFloat,
29 Range1,
30)
31from colour.utilities import from_range_1, to_domain_1, tsplit, tstack, zeros
33__author__ = "Colour Developers"
34__copyright__ = "Copyright 2013 Colour Developers"
35__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
36__maintainer__ = "Colour Developers"
37__email__ = "colour-developers@colour-science.org"
38__status__ = "Production"
40__all__ = [
41 "RGB_to_IHLS",
42 "IHLS_to_RGB",
43]
45MATRIX_RGB_TO_YC_1_C_2: NDArrayFloat = np.array(
46 [
47 [0.2126, 0.7152, 0.0722],
48 [1, -0.5, -0.5],
49 [0, -np.sqrt(3) / 2, np.sqrt(3) / 2],
50 ]
51)
52"""*RGB* colourspace to *YC_1C_2* colourspace matrix."""
54MATRIX_YC_1_C_2_TO_RGB: NDArrayFloat = np.linalg.inv(MATRIX_RGB_TO_YC_1_C_2)
55"""*YC_1C_2* colourspace to *RGB* colourspace matrix."""
58def RGB_to_IHLS(RGB: Domain1) -> Range1:
59 """
60 Convert from *RGB* colourspace to *IHLS* (Improved HLS) colourspace.
62 Parameters
63 ----------
64 RGB
65 *RGB* colourspace array.
67 Returns
68 -------
69 :class:`numpy.ndarray`
70 *HYS* colourspace array.
72 Notes
73 -----
74 +------------+-----------------------+---------------+
75 | **Domain** | **Scale - Reference** | **Scale - 1** |
76 +============+=======================+===============+
77 | ``RGB`` | 1 | 1 |
78 +------------+-----------------------+---------------+
80 +------------+-----------------------+---------------+
81 | **Range** | **Scale - Reference** | **Scale - 1** |
82 +============+=======================+===============+
83 | ``HYS`` | 1 | 1 |
84 +------------+-----------------------+---------------+
86 References
87 ----------
88 :cite:`Hanbury2003`
90 Examples
91 --------
92 >>> RGB = np.array([0.45595571, 0.03039702, 0.04087245])
93 >>> RGB_to_IHLS(RGB) # doctest: +ELLIPSIS
94 array([ 6.2616051..., 0.1216271..., 0.4255586...])
95 """
97 RGB = to_domain_1(RGB)
98 R, G, B = tsplit(RGB)
100 Y, C_1, C_2 = tsplit(vecmul(MATRIX_RGB_TO_YC_1_C_2, RGB))
102 C = np.hypot(C_1, C_2)
104 with sdiv_mode():
105 C_1_C = sdiv(C_1, C)
107 arcos_C_1_C_2 = zeros(C_1_C.shape)
108 arcos_C_1_C_2[C_1_C != 0] = np.arccos(C_1_C[C_1_C != 0])
110 H = np.where(C_2 <= 0, arcos_C_1_C_2, (np.pi * 2) - arcos_C_1_C_2)
112 S = np.maximum(np.maximum(R, G), B) - np.minimum(np.minimum(R, G), B)
114 HYS = tstack([H, Y, S])
116 return from_range_1(HYS)
119def IHLS_to_RGB(HYS: Domain1) -> Range1:
120 """
121 Convert from *IHLS* (Improved HLS) colourspace to *RGB* colourspace.
123 Parameters
124 ----------
125 HYS
126 *IHLS* colourspace array.
128 Returns
129 -------
130 :class:`numpy.ndarray`
131 *RGB* colourspace array.
133 Notes
134 -----
135 +------------+-----------------------+---------------+
136 | **Domain** | **Scale - Reference** | **Scale - 1** |
137 +============+=======================+===============+
138 | ``HYS`` | 1 | 1 |
139 +------------+-----------------------+---------------+
141 +------------+-----------------------+---------------+
142 | **Range** | **Scale - Reference** | **Scale - 1** |
143 +============+=======================+===============+
144 | ``RGB`` | 1 | 1 |
145 +------------+-----------------------+---------------+
147 References
148 ----------
149 :cite:`Hanbury2003`
151 Examples
152 --------
153 >>> HYS = np.array([6.26160518, 0.12162712, 0.42555869])
154 >>> IHLS_to_RGB(HYS) # doctest: +ELLIPSIS
155 array([ 0.4559557..., 0.0303970..., 0.0408724...])
156 """
158 H, Y, S = tsplit(to_domain_1(HYS))
160 pi_3 = np.pi / 3
162 k = np.floor(H / pi_3)
163 H_s = H - k * pi_3
164 C = (np.sqrt(3) * S) / (2 * np.sin(2 * pi_3 - H_s))
166 C_1 = C * np.cos(H)
167 C_2 = -C * np.sin(H)
169 RGB = vecmul(MATRIX_YC_1_C_2_TO_RGB, tstack([Y, C_1, C_2]))
171 return from_range_1(RGB)