Coverage for colour/models/yrg.py: 100%

41 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-15 19:01 +1300

1""" 

2Yrg Colourspace - Kirk (2019) 

3============================= 

4 

5Define the *Kirk (2019)* *Yrg* colourspace transformations. 

6 

7- :func:`colour.models.LMS_to_Yrg` 

8- :func:`colour.models.Yrg_to_LMS` 

9- :func:`colour.XYZ_to_Yrg` 

10- :func:`colour.Yrg_to_XYZ` 

11 

12References 

13---------- 

14- :cite:`Kirk2019` : Kirk, R. A. (2019). Chromaticity coordinates for graphic 

15 arts based on CIE 2006 LMS with even spacing of Munsell colours. Color and 

16 Imaging Conference, 27(1), 215-219. doi:10.2352/issn.2169-2629.2019.27.38 

17""" 

18 

19from __future__ import annotations 

20 

21import numpy as np 

22 

23from colour.algebra import sdiv, sdiv_mode, vecmul 

24from colour.hints import ( # noqa: TC001 

25 Domain1, 

26 NDArrayFloat, 

27 Range1, 

28) 

29from colour.utilities import from_range_1, to_domain_1, tsplit, tstack 

30 

31__author__ = "Colour Developers" 

32__copyright__ = "Copyright 2013 Colour Developers" 

33__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause" 

34__maintainer__ = "Colour Developers" 

35__email__ = "colour-developers@colour-science.org" 

36__status__ = "Production" 

37 

38__all__ = [ 

39 "LMS_to_Yrg", 

40 "Yrg_to_LMS", 

41 "XYZ_to_Yrg", 

42 "Yrg_to_XYZ", 

43] 

44 

45MATRIX_XYZ_TO_LMS_KIRK2019: NDArrayFloat = np.array( 

46 [ 

47 [0.257085, 0.859943, -0.031061], 

48 [-0.394427, 1.175800, 0.106423], 

49 [0.064856, -0.076250, 0.559067], 

50 ] 

51) 

52""" 

53*Kirk (2019)* matrix converting from *CIE XYZ* tristimulus values to *LMS* 

54colourspace. 

55""" 

56 

57MATRIX_LMS_TO_XYZ_KIRK2019: NDArrayFloat = np.linalg.inv(MATRIX_XYZ_TO_LMS_KIRK2019) 

58""" 

59*Kirk (2019)* matrix converting from *LMS* colourspace to *CIE XYZ* tristimulus 

60values. 

61""" 

62 

63 

64def LMS_to_Yrg(LMS: Domain1) -> Range1: 

65 """ 

66 Convert from *LMS* cone fundamentals colourspace to *Kirk (2019)* *Yrg* 

67 colourspace. 

68 

69 Parameters 

70 ---------- 

71 LMS 

72 *LMS* cone fundamentals colourspace values. 

73 

74 Returns 

75 ------- 

76 :class:`numpy.ndarray` 

77 *Kirk (2019)* *Yrg* colourspace array with :math:`Y` luminance, 

78 :math:`r` redness, and :math:`g` greenness components. 

79 

80 Notes 

81 ----- 

82 +------------+-----------------------+----------------+ 

83 | **Domain** | **Scale - Reference** | **Scale - 1** | 

84 +============+=======================+================+ 

85 | ``LMS`` | 1 | 1 | 

86 +------------+-----------------------+----------------+ 

87 

88 +------------+-----------------------+----------------+ 

89 | **Range** | **Scale - Reference** | **Scale - 1** | 

90 +============+=======================+================+ 

91 | ``Yrg`` | 1 | 1 | 

92 +------------+-----------------------+----------------+ 

93 

94 References 

95 ---------- 

96 :cite:`Kirk2019` 

97 

98 Examples 

99 -------- 

100 >>> import numpy as np 

101 >>> LMS = np.array([0.15639195, 0.06741689, 0.03281398]) 

102 >>> LMS_to_Yrg(LMS) # doctest: +ELLIPSIS 

103 array([ 0.1313780..., 0.4903764..., 0.3777739...]) 

104 """ 

105 

106 L, M, S = tsplit(to_domain_1(LMS)) 

107 

108 Y = 0.68990272 * L + 0.34832189 * M 

109 

110 a = L + M + S 

111 

112 with sdiv_mode(): 

113 l = sdiv(L, a) # noqa: E741 

114 m = sdiv(M, a) 

115 

116 r = 1.0671 * l - 0.6873 * m + 0.02062 

117 g = -0.0362 * l + 1.7182 * m - 0.05155 

118 

119 Yrg = tstack([Y, r, g]) 

120 

121 return from_range_1(Yrg) 

122 

123 

124def Yrg_to_LMS(Yrg: Domain1) -> Range1: 

125 """ 

126 Convert from *Kirk (2019)* *Yrg* colourspace to *LMS* cone 

127 fundamentals colourspace. 

128 

129 Parameters 

130 ---------- 

131 Yrg 

132 *Kirk (2019)* *Yrg* colourspace array with :math:`Y` luminance, 

133 :math:`r` redness, and :math:`g` greenness components. 

134 

135 Returns 

136 ------- 

137 :class:`numpy.ndarray` 

138 *LMS* cone fundamentals colourspace values. 

139 

140 Notes 

141 ----- 

142 +------------+-----------------------+----------------+ 

143 | **Domain** | **Scale - Reference** | **Scale - 1** | 

144 +============+=======================+================+ 

145 | ``Yrg`` | 1 | 1 | 

146 +------------+-----------------------+----------------+ 

147 

148 +------------+-----------------------+----------------+ 

149 | **Range** | **Scale - Reference** | **Scale - 1** | 

150 +============+=======================+================+ 

151 | ``LMS`` | 1 | 1 | 

152 +------------+-----------------------+----------------+ 

153 

154 References 

155 ---------- 

156 :cite:`Kirk2019` 

157 

158 Examples 

159 -------- 

160 >>> import numpy as np 

161 >>> Yrg = np.array([0.13137801, 0.49037644, 0.37777391]) 

162 >>> Yrg_to_LMS(Yrg) # doctest: +ELLIPSIS 

163 array([ 0.1563929..., 0.0674150..., 0.0328213...]) 

164 """ 

165 

166 Y, r, g = tsplit(to_domain_1(Yrg)) 

167 

168 l = 0.95 * r + 0.38 * g # noqa: E741 

169 m = 0.02 * r + 0.59 * g + 0.03 

170 a = Y / (0.68990272 * l + 0.34832189 * m) 

171 L = l * a 

172 M = m * a 

173 S = (1 - l - m) * a 

174 

175 LMS = tstack([L, M, S]) 

176 

177 return from_range_1(LMS) 

178 

179 

180def XYZ_to_Yrg(XYZ: Domain1) -> Range1: 

181 """ 

182 Convert from *CIE XYZ* tristimulus values to *Kirk (2019)* *Yrg* 

183 colourspace. 

184 

185 Parameters 

186 ---------- 

187 XYZ 

188 *CIE XYZ* tristimulus values. 

189 

190 Returns 

191 ------- 

192 :class:`numpy.ndarray` 

193 *Kirk (2019)* *Yrg* colourspace array with :math:`Y` luminance, 

194 :math:`r` redness, and :math:`g` greenness components. 

195 

196 Notes 

197 ----- 

198 +------------+-----------------------+----------------+ 

199 | **Domain** | **Scale - Reference** | **Scale - 1** | 

200 +============+=======================+================+ 

201 | ``XYZ`` | 1 | 1 | 

202 +------------+-----------------------+----------------+ 

203 

204 +------------+-----------------------+----------------+ 

205 | **Range** | **Scale - Reference** | **Scale - 1** | 

206 +============+=======================+================+ 

207 | ``Yrg`` | 1 | 1 | 

208 +------------+-----------------------+----------------+ 

209 

210 References 

211 ---------- 

212 :cite:`Kirk2019` 

213 

214 Examples 

215 -------- 

216 >>> import numpy as np 

217 >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) 

218 >>> XYZ_to_Yrg(XYZ) # doctest: +ELLIPSIS 

219 array([ 0.1313780..., 0.4903764..., 0.3777738...]) 

220 """ 

221 

222 return LMS_to_Yrg(vecmul(MATRIX_XYZ_TO_LMS_KIRK2019, XYZ)) 

223 

224 

225def Yrg_to_XYZ(Yrg: Domain1) -> Range1: 

226 """ 

227 Convert from *Kirk (2019)* *Yrg* colourspace to *CIE XYZ* tristimulus 

228 values. 

229 

230 Parameters 

231 ---------- 

232 Yrg 

233 *Kirk (2019)* *Yrg* colourspace array with :math:`Y` luminance, 

234 :math:`r` redness, and :math:`g` greenness components. 

235 

236 Returns 

237 ------- 

238 :class:`numpy.ndarray` 

239 *CIE XYZ* tristimulus values. 

240 

241 Notes 

242 ----- 

243 +------------+-----------------------+----------------+ 

244 | **Domain** | **Scale - Reference** | **Scale - 1** | 

245 +============+=======================+================+ 

246 | ``Yrg`` | 1 | 1 | 

247 +------------+-----------------------+----------------+ 

248 

249 +------------+-----------------------+----------------+ 

250 | **Range** | **Scale - Reference** | **Scale - 1** | 

251 +============+=======================+================+ 

252 | ``XYZ`` | 1 | 1 | 

253 +------------+-----------------------+----------------+ 

254 

255 References 

256 ---------- 

257 :cite:`Kirk2019` 

258 

259 Examples 

260 -------- 

261 >>> import numpy as np 

262 >>> Yrg = np.array([0.13137801, 0.49037645, 0.37777388]) 

263 >>> Yrg_to_XYZ(Yrg) # doctest: +ELLIPSIS 

264 array([ 0.2065468..., 0.1219717..., 0.0513819...]) 

265 """ 

266 

267 return vecmul(MATRIX_LMS_TO_XYZ_KIRK2019, Yrg_to_LMS(Yrg))