Ejemplo n.º 1
0
    def test_domain_range_scale_CAM16_to_XYZ(self):
        """
        Tests :func:`colour.appearance.cam16.CAM16_to_XYZ` definition domain
        and range scale support.
        """

        XYZ_i = np.array([19.01, 20.00, 21.78])
        XYZ_w = np.array([95.05, 100.00, 108.88])
        L_A = 318.31
        Y_b = 20.0
        surround = CAM16_VIEWING_CONDITIONS['Average']
        specification = XYZ_to_CAM16(XYZ_i, XYZ_w, L_A, Y_b, surround)
        XYZ = CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround)

        d_r = (
            ('reference', 1, 1, 1),
            (1, np.array([1, 1, 1 / 360, 1, 1, 1, 1 / 360]), 0.01, 0.01),
            (100, np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 360]), 1, 1),
        )
        for scale, factor_a, factor_b, factor_c in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(CAM16_to_XYZ(
                    specification[:-1] * factor_a, XYZ_w * factor_b, L_A, Y_b,
                    surround),
                                               XYZ * factor_c,
                                               decimal=7)
Ejemplo n.º 2
0
    def test_CAM16_to_XYZ(self):
        """Test :func:`colour.appearance.cam16.CAM16_to_XYZ` definition."""

        specification = CAM_Specification_CAM16(41.73120791, 0.10335574,
                                                217.06795977)
        XYZ_w = np.array([95.05, 100.00, 108.88])
        L_A = 318.31
        Y_b = 20
        surround = VIEWING_CONDITIONS_CAM16["Average"]
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            np.array([19.01, 20.00, 21.78]),
            decimal=7,
        )

        specification = CAM_Specification_CAM16(65.42828069, 49.67956420,
                                                17.48659243)
        L_A = 31.83
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            np.array([57.06, 43.06, 31.96]),
            decimal=7,
        )

        specification = CAM_Specification_CAM16(21.36052893, 50.99381895,
                                                178.86724266)
        XYZ_w = np.array([109.85, 100, 35.58])
        L_A = 318.31
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            np.array([3.53, 6.56, 2.14]),
            decimal=7,
        )

        specification = CAM_Specification_CAM16(41.36326063, 52.81154022,
                                                258.88676291)
        L_A = 318.31
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            np.array([19.01, 20.00, 21.78]),
            decimal=7,
        )

        specification = CAM_Specification_CAM16(21.03801957, 457.78881613,
                                                350.06445098)
        XYZ_w = np.array([95.05, 100.00, 108.88])
        L_A = 4.074366543152521
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            np.array([61.45276998, 7.00421901, 82.2406738]),
            decimal=7,
        )
Ejemplo n.º 3
0
    def test_domain_range_scale_CAM16_to_XYZ(self):
        """
        Test :func:`colour.appearance.cam16.CAM16_to_XYZ` definition domain
        and range scale support.
        """

        XYZ = np.array([19.01, 20.00, 21.78])
        XYZ_w = np.array([95.05, 100.00, 108.88])
        L_A = 318.31
        Y_b = 20
        surround = VIEWING_CONDITIONS_CAM16["Average"]
        specification = XYZ_to_CAM16(XYZ, XYZ_w, L_A, Y_b, surround)
        XYZ = CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround)

        d_r = (
            ("reference", 1, 1),
            (
                "1",
                np.array([
                    1 / 100,
                    1 / 100,
                    1 / 360,
                    1 / 100,
                    1 / 100,
                    1 / 100,
                    1 / 400,
                    np.nan,
                ]),
                0.01,
            ),
            (
                "100",
                np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 400, np.nan]),
                1,
            ),
        )
        for scale, factor_a, factor_b in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(
                    CAM16_to_XYZ(
                        specification * factor_a,
                        XYZ_w * factor_b,
                        L_A,
                        Y_b,
                        surround,
                    ),
                    XYZ * factor_b,
                    decimal=7,
                )
Ejemplo n.º 4
0
    def _XYZ_from_data(self, data, correlates):
        """
        Returns the *CIE XYZ* tristimulus values from given *CAM16* colour
        appearance model input data.

        Parameters
        ----------
        data : list
            Fixture data.
        correlates : array_like
            Correlates used to build the input *CAM16* colour appearance
            model specification.

        Returns
        -------
        array_like
            *CIE XYZ* tristimulus values
        """

        XYZ_w = tstack([data['X_w'], data['Y_w'], data['Z_w']])

        i, j, k = correlates
        CAM16_specification = as_namedtuple(
            {
                i: data[i],
                j: data[j],
                k: data[k]
            }, CAM16_Specification)

        XYZ = CAM16_to_XYZ(
            CAM16_specification, XYZ_w, data['L_A'], data['Y_b'],
            CAM16_InductionFactors(data['F'], data['c'], data['N_c']))

        return XYZ
Ejemplo n.º 5
0
    def test_n_dimensional_CAM16_to_XYZ(self):
        """
        Test :func:`colour.appearance.cam16.CAM16_to_XYZ` definition
        n-dimensional support.
        """

        XYZ = np.array([19.01, 20.00, 21.78])
        XYZ_w = np.array([95.05, 100.00, 108.88])
        L_A = 318.31
        Y_b = 20
        surround = VIEWING_CONDITIONS_CAM16["Average"]
        specification = XYZ_to_CAM16(XYZ, XYZ_w, L_A, Y_b, surround)
        XYZ = CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround)

        specification = CAM_Specification_CAM16(
            *np.transpose(np.tile(tsplit(specification), (6, 1))).tolist())
        XYZ = np.tile(XYZ, (6, 1))
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            XYZ,
            decimal=7,
        )

        XYZ_w = np.tile(XYZ_w, (6, 1))
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            XYZ,
            decimal=7,
        )

        specification = CAM_Specification_CAM16(
            *tsplit(np.reshape(specification, (2, 3, 8))).tolist())
        XYZ_w = np.reshape(XYZ_w, (2, 3, 3))
        XYZ = np.reshape(XYZ, (2, 3, 3))
        np.testing.assert_almost_equal(
            CAM16_to_XYZ(specification, XYZ_w, L_A, Y_b, surround),
            XYZ,
            decimal=7,
        )
Ejemplo n.º 6
0
    def test_nan_CAM16_to_XYZ(self):
        """
        Tests :func:`colour.appearance.cam16.CAM16_to_XYZ` definition
        nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            J = case[0]
            C = case[0]
            h = case[0]
            XYZ_w = np.array(case)
            L_A = case[0]
            Y_b = case[0]
            surround = CAM16_InductionFactors(case[0], case[0], case[0])
            CAM16_to_XYZ(CAM16_Specification(J, C, h), XYZ_w, L_A, Y_b,
                         surround)
Ejemplo n.º 7
0
    def test_raise_exception_CAM16_to_XYZ(self):
        """
        Tests :func:`colour.appearance.cam16.CAM16_to_XYZ` definition raised
        exception.
        """

        try:
            CAM16_to_XYZ(
                CAM16_Specification(
                    41.731207905126638,
                    None,
                    217.06795976739301,
                ),
                np.array([95.05, 100.00, 108.88]),
                318.31,
                20.0,
                CAM16_VIEWING_CONDITIONS['Average'],
            )
        except ValueError:
            pass
Ejemplo n.º 8
0
def UCS_Li2017_to_XYZ(Jpapbp: ArrayLike, coefficients: ArrayLike,
                      **kwargs: Any) -> NDArray:
    """
    Convert from one of the *Li et al. (2017)* *CAM16-LCD*, *CAM16-SCD*, or
    *CAM16-UCS* colourspaces :math:`J'a'b'` array to *CIE XYZ* tristimulus
    values.

    Parameters
    ----------
    Jpapbp
        *Li et al. (2017)* *CAM16-LCD*, *CAM16-SCD*, or *CAM16-UCS*
        colourspaces :math:`J'a'b'` array.
    coefficients
        Coefficients of one of the *Li et al. (2017)* *CAM16-LCD*, *CAM16-SCD*,
        or *CAM16-UCS* colourspaces.

    Other Parameters
    ----------------
    kwargs
        {:func:`colour.CAM16_to_XYZ`},
        See the documentation of the previously listed definition. The default
        viewing conditions are that of *IEC 61966-2-1:1999*, i.e. *sRGB* 64 Lux
        ambient illumination, 80 :math:`cd/m^2`, adapting field luminance about
        20% of a white object in the scene.

    Returns
    -------
    :class:`numpy.ndarray`
        *CIE XYZ* tristimulus values.

    Warnings
    --------
    The ``XYZ_w`` parameter for :func:`colour.XYZ_to_CAM16` definition must be
    given in the same domain-range scale than the ``XYZ`` parameter.

    Notes
    -----
    +------------+------------------------+------------------+
    | **Domain** |  **Scale - Reference** | **Scale - 1**    |
    +============+========================+==================+
    | ``Jpapbp`` | ``Jp`` : [0, 100]      | ``Jp`` : [0, 1]  |
    |            |                        |                  |
    |            | ``ap`` : [-100, 100]   | ``ap`` : [-1, 1] |
    |            |                        |                  |
    |            | ``bp`` : [-100, 100]   | ``bp`` : [-1, 1] |
    +------------+------------------------+------------------+

    +------------+------------------------+------------------+
    | **Range**  |  **Scale - Reference** | **Scale - 1**    |
    +============+========================+==================+
    | ``XYZ``    | [0, 1]                 | [0, 1]           |
    +------------+------------------------+------------------+

    Examples
    --------
    >>> import numpy as np
    >>> Jpapbp = np.array([46.06586037, 41.07586491, 14.51025828])
    >>> UCS_Li2017_to_XYZ(
    ...     Jpapbp, COEFFICIENTS_UCS_LUO2006['CAM02-LCD'])
    ... # doctest: +ELLIPSIS
    array([ 0.2065400...,  0.1219722...,  0.0513695...])

    >>> from colour.appearance import CAM_KWARGS_CIECAM02_sRGB
    >>> XYZ_w = CAM_KWARGS_CIECAM02_sRGB['XYZ_w']
    >>> UCS_Li2017_to_XYZ(
    ...     Jpapbp, COEFFICIENTS_UCS_LUO2006['CAM02-LCD'], XYZ_w=XYZ_w / 100)
    ... # doctest: +ELLIPSIS
    array([ 0.2065400...,  0.1219722...,  0.0513695...])
    """

    from colour.appearance import (
        CAM_KWARGS_CIECAM02_sRGB,
        CAM_Specification_CAM16,
        CAM16_to_XYZ,
    )

    domain_range_reference = get_domain_range_scale() == "reference"

    settings = CAM_KWARGS_CIECAM02_sRGB.copy()
    settings.update(**kwargs)
    XYZ_w = kwargs.get("XYZ_w")

    if XYZ_w is not None and domain_range_reference:
        settings["XYZ_w"] = XYZ_w * 100

    J, M, h = tsplit(UCS_Li2017_to_JMh_CAM16(Jpapbp, coefficients))

    specification = CAM_Specification_CAM16(J=J, M=M, h=h)

    XYZ = CAM16_to_XYZ(specification, **settings)

    if domain_range_reference:
        XYZ /= 100

    return XYZ