Coverage for appearance/hke.py: 42%

1"""

2 Helmholtz—Kohlrausch Effect

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

4

5 Define methods for estimating the Helmholtz—Kohlrausch effect (HKE).

6

7- :attr:`colour.HKE_NAYATANI1997_METHODS`: *Nayatani (1997)* HKE

8 computation methods, choice between variable achromatic colour (VAC)

9 and variable chromatic colour (VCC).

10- :func:`colour.HelmholtzKohlrausch_effect_object_Nayatani1997`:

11 Compute HKE value for object colours using *Nayatani (1997)* method.

12- :func:`colour.HelmholtzKohlrausch_effect_luminous_Nayatani1997`:

13 Compute HKE value for luminous colours using *Nayatani (1997)* method.

14- :func:`colour.appearance.coefficient_q_Nayatani1997`:

15 Calculate :math:`q` coefficient for *Nayatani (1997)* HKE estimation.

16- :func:`colour.appearance.coefficient_K_Br_Nayatani1997`:

17 Calculate :math:`K_{Br}` coefficient for *Nayatani (1997)* HKE

18 estimation.

19

20 References

21----------

22- :cite:`Nayatani1997` : Nayatani, Y. (1997). Simple estimation methods for

23 the Helmholtz—Kohlrausch effect. Color Research & Application, 22(6),

24 385-401. doi:10.1002/(SICI)1520-6378(199712)22:6<385::AID-COL6>3.0.CO;2-R

25"""

26

27 from __future__ import annotations

28

29 import typing

30

31 import numpy as np

32

33 from colour.algebra import spow

34

35 if typing.TYPE_CHECKING:

36 from colour.hints import ArrayLike, DTypeFloat, Literal, NDArray, NDArrayFloat

37

38 from colour.utilities import CanonicalMapping, as_float_array, tsplit, validate_method

39

40 __author__ = "Ilia Sibiryakov"

41 __copyright__ = "Copyright 2013 Colour Developers"

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

43 __maintainer__ = "Colour Developers"

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

45 __status__ = "Production"

46

47 __all__ = [

48 "HKE_NAYATANI1997_METHODS",

49 "HelmholtzKohlrausch_effect_object_Nayatani1997",

50 "HelmholtzKohlrausch_effect_luminous_Nayatani1997",

51 "coefficient_q_Nayatani1997",

52 "coefficient_K_Br_Nayatani1997",

53]

54

55 HKE_NAYATANI1997_METHODS = CanonicalMapping(

56 {

57 "VAC": -0.1340,

58 "VCC": -0.8660,

59 }

60)

61 HKE_NAYATANI1997_METHODS.__doc__ = """

62 Define *Nayatani (1997)* *Helmholtz-Kohlrausch effect* (HKE) computation

63 methods: variable achromatic colour ('VAC') and variable chromatic

64 colour ('VCC').

65

66 References

67----------

68:cite:`Nayatani1997`

69"""

70

71

72 def HelmholtzKohlrausch_effect_object_Nayatani1997(

73 uv: ArrayLike,

74 uv_c: ArrayLike,

75 L_a: ArrayLike,

76 method: Literal["VAC", "VCC"] | str = "VCC",

77) -> NDArrayFloat:

78 """

79 Compute the *Helmholtz-Kohlrausch effect* (HKE) value for object

80 colours using the *Nayatani (1997)* method.

81

82 Parameters

83 ----------

84 uv

85 *CIE L\\*u\\*v\\** colourspace :math:`uv^p` chromaticity coordinates

86 of the test samples.

87 uv_c

88 *CIE L\\*u\\*v\\** colourspace :math:`uv^p` chromaticity coordinates

89 of the reference white.

90 L_a

91 Adapting luminance in :math:`cd/m^2`.

92 method

93 Estimation method to use: *VCC* (Variable-Chromatic-Colour) or

94 *VAC* (Variable-Achromatic-Colour).

95

96 Returns

97 -------

98 :class:`numpy.ndarray`

99 Luminance factor (:math:`\\Gamma`) values computed using the

100 *Nayatani (1997)* object colour estimation method.

101

102 References

103 ----------

104 :cite:`Nayatani1997`

105

106 Examples

107 --------

108 >>> import colour

109 >>> white = colour.xy_to_Luv_uv(colour.temperature.CCT_to_xy_CIE_D(6504))

110 >>> colours = colour.XYZ_to_xy(

111 ... [colour.wavelength_to_XYZ(430 + i * 50) for i in range(5)]

112 ... )

113 >>> L_adapting = 65

114 >>> HelmholtzKohlrausch_effect_object_Nayatani1997( # doctest: +ELLIPSIS

115 ... colour.xy_to_Luv_uv(colours), white, L_adapting

116 ... )

117 array([ 2.2468383..., 1.4619799..., 1.1801658..., 0.9031318..., \

118 1.7999376...])

119 """

120

121 u, v = tsplit(uv)

122 u_c, v_c = tsplit(uv_c)

123

124 method = validate_method(method, tuple(HKE_NAYATANI1997_METHODS))

125

126 K_Br = coefficient_K_Br_Nayatani1997(L_a)

127 q = coefficient_q_Nayatani1997(np.arctan2(v - v_c, u - u_c))

128 S_uv = 13 * np.sqrt((u - u_c) ** 2 + (v - v_c) ** 2)

129

130 return 1 + (HKE_NAYATANI1997_METHODS[method] * q + 0.0872 * K_Br) * S_uv

131

132

133 def HelmholtzKohlrausch_effect_luminous_Nayatani1997(

134 uv: ArrayLike,

135 uv_c: ArrayLike,

136 L_a: ArrayLike,

137 method: Literal["VAC", "VCC"] | str = "VCC",

138) -> NDArrayFloat:

139 """

140 Compute the *HKE* factor for luminous colours using the

141 *Nayatani (1997)* method.

142

143 Parameters

144 ----------

145 uv

146 *CIE L\\*u\\*v\\** colourspace :math:`uv^p` chromaticity coordinates of

147 test samples.

148 uv_c

149 *CIE L\\*u\\*v\\** colourspace :math:`uv^p` chromaticity coordinates of

150 reference white.

151 L_a

152 Adapting luminance in :math:`cd/m^2`.

153 method

154 Estimation method to use: *VCC* (Variable-Chromatic-Colour) or

155 *VAC* (Variable-Achromatic-Colour).

156

157 Returns

158 -------

159 :class:`numpy.ndarray`

160 Luminance factor (:math:`\\Gamma`) values computed using the

161 Nayatani luminous colour estimation method.

162

163 References

164 ----------

165 :cite:`Nayatani1997`

166

167 Examples

168 --------

169 >>> import colour

170 >>> white = colour.xy_to_Luv_uv(colour.temperature.CCT_to_xy_CIE_D(6504))

171 >>> colours = colour.XYZ_to_xy(

172 ... [colour.wavelength_to_XYZ(430 + i * 50) for i in range(5)]

173 ... )

174 >>> L_adapting = 65

175 >>> HelmholtzKohlrausch_effect_luminous_Nayatani1997( # doctest: +ELLIPSIS

176 ... colour.xy_to_Luv_uv(colours), white, L_adapting

177 ... )

178 array([ 7.4460471..., 2.4767159..., 1.4723422..., 0.7938695..., \

179 4.1828629...])

180 """

181

182 return (

183 0.4462

184 * (

185 HelmholtzKohlrausch_effect_object_Nayatani1997(uv, uv_c, L_a, method)

186 + 0.3086

187 )

188 ** 3

189 )

190

191

192 def coefficient_q_Nayatani1997(

193 theta: ArrayLike,

194) -> NDArrayFloat:

195 """

196 Compute the :math:`q(\\theta)` coefficient for *Nayatani (1997)* *HKE*

197 computations.

198

199 The hue angle :math:`\\theta` can be computed as follows:

200

201 :math:`tan^{-1}\\cfrac{v' - v'_c}{u' - u'_c}`

202

203 where :math:`u'` and :math:`v'` are the *CIE L\\*u\\*v\\** colourspace

204 :math:`uv^p` chromaticity coordinates of the test chromatic light and

205 :math:`u'_c` and :math:`v'_c` are the *CIE L\\*u\\*v\\**

206 colourspace :math:`uv^p` chromaticity coordinates of the reference

207 white light.

208

209 Parameters

210 ----------

211 theta

212 Hue angle (:math:`\\theta`) in radians.

213

214 Returns

215 -------

216 :class:`numpy.ndarray`

217 :math:`q` coefficient for *Nayatani (1997)* *HKE* methods.

218

219 References

220 ----------

221 :cite:`Nayatani1997`

222

223 Examples

224 --------

225 This recreates *FIG. A-1*.

226

227 >>> import matplotlib.pyplot as plt

228 >>> angles = [(np.pi * 2 / 100 * i) for i in range(100)]

229 >>> q_values = coefficient_q_Nayatani1997(angles)

230 >>> plt.plot(np.array(angles), q_values / (np.pi * 2) * 180)

231 ... # doctest: +ELLIPSIS

232 [<matplotlib.lines.Line2D object at 0x...>]

233 >>> plt.show() # doctest: +SKIP

234 """

235

236 theta = as_float_array(theta)

237

238 theta_2, theta_3, theta_4 = 2 * theta, 3 * theta, 4 * theta

239

240 return (

241 -0.01585

242 - 0.03017 * np.cos(theta)

243 - 0.04556 * np.cos(theta_2)

244 - 0.02667 * np.cos(theta_3)

245 - 0.00295 * np.cos(theta_4)

246 + 0.14592 * np.sin(theta)

247 + 0.05084 * np.sin(theta_2)

248 - 0.01900 * np.sin(theta_3)

249 - 0.00764 * np.sin(theta_4)

250 )

251

252

253@typing.overload

254 def coefficient_K_Br_Nayatani1997(L_a: float | DTypeFloat) -> DTypeFloat: ...

255@typing.overload

256 def coefficient_K_Br_Nayatani1997(L_a: NDArray) -> NDArrayFloat: ...

257@typing.overload

258 def coefficient_K_Br_Nayatani1997(L_a: ArrayLike) -> DTypeFloat | NDArrayFloat: ...

259 def coefficient_K_Br_Nayatani1997(L_a: ArrayLike) -> DTypeFloat | NDArrayFloat:

260 """

261 Compute the :math:`K_{Br}` coefficient for *Nayatani (1997)* *HKE*

262 computations.

263

264 Parameters

265 ----------

266 L_a

267 Adapting luminance in :math:`cd/m^2`.

268

269 Returns

270 -------

271 :class:`numpy.ndarray`

272 :math:`K_{Br}` coefficient for *Nayatani (1997)* *HKE* methods.

273

274 Notes

275 -----

276 - The :math:`K_{Br}` coefficient is normalised to unity around

277 :math:`63.66cd/m^2`.

278

279 References

280 ----------

281 :cite:`Nayatani1997`

282

283 Examples

284 --------

285 >>> L_a_values = [10 + i * 20 for i in range(5)]

286 >>> coefficient_K_Br_Nayatani1997(L_a_values) # doctest: +ELLIPSIS

287 array([ 0.7134481..., 0.8781172..., 0.9606248..., 1.0156689..., \

288 1.0567008...])

289 >>> coefficient_K_Br_Nayatani1997(63.66) # doctest: +ELLIPSIS

290 1.0001284...

291 """

292

293 L_a_4495 = spow(L_a, 0.4495)

294

295 return (L_a_4495 * 6.362 + 6.469) * 0.2717 / (L_a_4495 + 6.469)