Source code for colour.adaptation.vonkries

"""
Von Kries Chromatic Adaptation Model
====================================

Defines the *Von Kries* chromatic adaptation model objects:

-   :func:`colour.adaptation.matrix_chromatic_adaptation_VonKries`
-   :func:`colour.adaptation.chromatic_adaptation_VonKries`

References
----------
-   :cite:`Fairchild2013t` : Fairchild, M. D. (2013). Chromatic Adaptation
    Models. In Color Appearance Models (3rd ed., pp. 4179-4252). Wiley.
    ISBN:B00DAYO8E2
"""

from __future__ import annotations

import numpy as np

from colour.adaptation import CHROMATIC_ADAPTATION_TRANSFORMS
from colour.algebra import matrix_dot, sdiv, sdiv_mode, vector_dot
from colour.hints import (
    ArrayLike,
    LiteralChromaticAdaptationTransform,
    NDArrayFloat,
)
from colour.utilities import (
    from_range_1,
    row_as_diagonal,
    to_domain_1,
    validate_method,
)

__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__ = [
    "matrix_chromatic_adaptation_VonKries",
    "chromatic_adaptation_VonKries",
]


[docs] def matrix_chromatic_adaptation_VonKries( XYZ_w: ArrayLike, XYZ_wr: ArrayLike, transform: LiteralChromaticAdaptationTransform | str = "CAT02", ) -> NDArrayFloat: """ Compute the *chromatic adaptation* matrix from test viewing conditions to reference viewing conditions. Parameters ---------- XYZ_w Test viewing conditions *CIE XYZ* tristimulus values of whitepoint. XYZ_wr Reference viewing conditions *CIE XYZ* tristimulus values of whitepoint. transform Chromatic adaptation transform. Returns ------- :class:`numpy.ndarray` Chromatic adaptation matrix :math:`M_{cat}`. Notes ----- +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``XYZ_w`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ | ``XYZ_wr`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- :cite:`Fairchild2013t` Examples -------- >>> XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) >>> XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) >>> matrix_chromatic_adaptation_VonKries(XYZ_w, XYZ_wr) ... # doctest: +ELLIPSIS array([[ 1.0425738..., 0.0308910..., -0.0528125...], [ 0.0221934..., 1.0018566..., -0.0210737...], [-0.0011648..., -0.0034205..., 0.7617890...]]) Using Bradford method: >>> XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) >>> XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) >>> method = "Bradford" >>> matrix_chromatic_adaptation_VonKries(XYZ_w, XYZ_wr, method) ... # doctest: +ELLIPSIS array([[ 1.0479297..., 0.0229468..., -0.0501922...], [ 0.0296278..., 0.9904344..., -0.0170738...], [-0.0092430..., 0.0150551..., 0.7518742...]]) """ XYZ_w = to_domain_1(XYZ_w) XYZ_wr = to_domain_1(XYZ_wr) transform = validate_method( transform, tuple(CHROMATIC_ADAPTATION_TRANSFORMS), '"{0}" chromatic adaptation transform is invalid, ' "it must be one of {1}!", ) M = CHROMATIC_ADAPTATION_TRANSFORMS[transform] RGB_w = np.einsum("...i,...ij->...j", XYZ_w, np.transpose(M)) RGB_wr = np.einsum("...i,...ij->...j", XYZ_wr, np.transpose(M)) with sdiv_mode(): D = sdiv(RGB_wr, RGB_w) D = row_as_diagonal(D) M_CAT = matrix_dot(np.linalg.inv(M), D) M_CAT = matrix_dot(M_CAT, M) return M_CAT
[docs] def chromatic_adaptation_VonKries( XYZ: ArrayLike, XYZ_w: ArrayLike, XYZ_wr: ArrayLike, transform: LiteralChromaticAdaptationTransform | str = "CAT02", ) -> NDArrayFloat: """ Adapt given stimulus from test viewing conditions to reference viewing conditions. Parameters ---------- XYZ *CIE XYZ* tristimulus values of stimulus to adapt. XYZ_w Test viewing conditions *CIE XYZ* tristimulus values of whitepoint. XYZ_wr Reference viewing conditions *CIE XYZ* tristimulus values of whitepoint. transform Chromatic adaptation transform. Returns ------- :class:`numpy.ndarray` *CIE XYZ_c* tristimulus values of the stimulus corresponding colour. Notes ----- +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``XYZ`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ | ``XYZ_n`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ | ``XYZ_r`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``XYZ_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- :cite:`Fairchild2013t` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) >>> XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) >>> chromatic_adaptation_VonKries(XYZ, XYZ_w, XYZ_wr) # doctest: +ELLIPSIS array([ 0.2163881..., 0.1257 , 0.0384749...]) Using Bradford method: >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) >>> XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) >>> transform = "Bradford" >>> chromatic_adaptation_VonKries(XYZ, XYZ_w, XYZ_wr, transform) ... # doctest: +ELLIPSIS array([ 0.2166600..., 0.1260477..., 0.0385506...]) """ XYZ = to_domain_1(XYZ) M_CAT = matrix_chromatic_adaptation_VonKries(XYZ_w, XYZ_wr, transform) XYZ_a = vector_dot(M_CAT, XYZ) return from_range_1(XYZ_a)