예제 #1
0
    def test_RGB_to_sd_Smits1999(self):
        """
        Tests :func:`colour.recovery.smits1999.RGB_to_sd_Smits1999`
        definition.
        """

        np.testing.assert_almost_equal(
            RGB_to_sd_Smits1999(
                XYZ_to_RGB_Smits1999(
                    np.array([0.21781186, 0.12541048, 0.04697113]))).values,
            np.array([
                0.07691923, 0.05870050, 0.03943195, 0.03024978, 0.02750692,
                0.02808645, 0.34298985, 0.41185795, 0.41185795, 0.41180754
            ]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_sd_Smits1999(
                XYZ_to_RGB_Smits1999(
                    np.array([0.15434689, 0.22960951, 0.09620221]))).values,
            np.array([
                0.06981477, 0.06981351, 0.07713379, 0.25139495, 0.30063408,
                0.28797045, 0.11990414, 0.08186170, 0.08198613, 0.08272671
            ]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_sd_Smits1999(
                XYZ_to_RGB_Smits1999(
                    np.array([0.07683480, 0.06006092, 0.25833845]))).values,
            np.array([
                0.29091152, 0.29010285, 0.26572455, 0.13140471, 0.05160646,
                0.05162034, 0.02765638, 0.03199188, 0.03472939, 0.03504156
            ]),
            decimal=7)
예제 #2
0
    def test_domain_range_scale_RGB_to_sd_Smits1999(self):
        """
        Tests :func:`colour.recovery.smits1999.RGB_to_sd_Smits1999`
        definition domain and range scale support.
        """

        RGB_i = XYZ_to_RGB_Smits1999(
            np.array([0.21781186, 0.12541048, 0.04697113]))
        XYZ_o = sd_to_XYZ_integration(RGB_to_sd_Smits1999(RGB_i))

        d_r = (('reference', 1, 1), (1, 1, 0.01), (100, 100, 1))
        for scale, factor_a, factor_b in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(sd_to_XYZ_integration(
                    RGB_to_sd_Smits1999(RGB_i * factor_a)),
                                               XYZ_o * factor_b,
                                               decimal=7)
예제 #3
0
    def test_domain_range_scale_RGB_to_sd_Smits1999(self):
        """
        Test :func:`colour.recovery.smits1999.RGB_to_sd_Smits1999`
        definition domain and range scale support.
        """

        XYZ_i = np.array([0.20654008, 0.12197225, 0.05136952])
        RGB_i = XYZ_to_RGB_Smits1999(XYZ_i)
        XYZ_o = sd_to_XYZ_integration(RGB_to_sd_Smits1999(RGB_i))

        d_r = (("reference", 1, 1), ("1", 1, 0.01), ("100", 100, 1))
        for scale, factor_a, factor_b in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(
                    sd_to_XYZ_integration(RGB_to_sd_Smits1999(RGB_i *
                                                              factor_a)),
                    XYZ_o * factor_b,
                    decimal=7,
                )
예제 #4
0
    def test_RGB_to_sd_Smits1999(self):
        """
        Tests :func:`colour.recovery.smits1999.RGB_to_sd_Smits1999`
        definition.
        """

        np.testing.assert_almost_equal(RGB_to_sd_Smits1999(
            XYZ_to_RGB_Smits1999(np.array([0.21781186, 0.12541048,
                                           0.04697113]))).values,
                                       np.array([
                                           0.07691923, 0.05870050, 0.03943195,
                                           0.03024978, 0.02750692, 0.02808645,
                                           0.34298985, 0.41185795, 0.41185795,
                                           0.41180754
                                       ]),
                                       decimal=7)

        np.testing.assert_almost_equal(RGB_to_sd_Smits1999(
            XYZ_to_RGB_Smits1999(np.array([0.15434689, 0.22960951,
                                           0.09620221]))).values,
                                       np.array([
                                           0.06981477, 0.06981351, 0.07713379,
                                           0.25139495, 0.30063408, 0.28797045,
                                           0.11990414, 0.08186170, 0.08198613,
                                           0.08272671
                                       ]),
                                       decimal=7)

        np.testing.assert_almost_equal(RGB_to_sd_Smits1999(
            XYZ_to_RGB_Smits1999(np.array([0.07683480, 0.06006092,
                                           0.25833845]))).values,
                                       np.array([
                                           0.29091152, 0.29010285, 0.26572455,
                                           0.13140471, 0.05160646, 0.05162034,
                                           0.02765638, 0.03199188, 0.03472939,
                                           0.03504156
                                       ]),
                                       decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_sd_Smits1999(XYZ_to_RGB_Smits1999(np.array([0.0, 1.0,
                                                               0.0]))).values,
            np.array([
                -0.2549796, -0.2848386, -0.1634905, 1.5254829, 1.9800433,
                1.8510762, -0.7327702, -1.2758621, -1.2758621, -1.2703551
            ]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_sd_Smits1999(XYZ_to_RGB_Smits1999(np.array([1.0, 1.0,
                                                               0.0]))).values,
            np.array([
                -0.1168428, -0.1396982, -0.0414535, 0.581391, 0.9563091,
                0.9562111, 1.3366949, 1.3742666, 1.3853491, 1.4027005
            ]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_sd_Smits1999(XYZ_to_RGB_Smits1999(np.array([0.5, 0.0,
                                                               1.0]))).values,
            np.array([
                1.1938776, 1.1938776, 1.1213867, -0.067889, -0.4668587,
                -0.4030985, 0.703056, 0.9407334, 0.9437298, 0.9383386
            ]),
            decimal=7)
예제 #5
0
def XYZ_to_sd(
    XYZ: ArrayLike,
    method: Union[Literal["Jakob 2019", "Mallett 2019", "Meng 2015",
                          "Otsu 2018", "Smits 1999", ], str, ] = "Meng 2015",
    **kwargs: Any,
) -> SpectralDistribution:
    """
    Recover the spectral distribution of given *CIE XYZ* tristimulus
    values using given method.

    Parameters
    ----------
    XYZ
        *CIE XYZ* tristimulus values to recover the spectral distribution
        from.
    method
        Computation method.

    Other Parameters
    ----------------
    additional_data
        {:func:`colour.recovery.XYZ_to_sd_Jakob2019`},
        If *True*, ``error`` will be returned alongside ``sd``.
    basis_functions
        {:func:`colour.recovery.RGB_to_sd_Mallett2019`},
        Basis functions for the method. The default is to use the built-in
        *sRGB* basis functions, i.e.
        :attr:`colour.recovery.MSDS_BASIS_FUNCTIONS_sRGB_MALLETT2019`.
    clip
        {:func:`colour.recovery.XYZ_to_sd_Otsu2018`},
        If *True*, the default, values below zero and above unity in the
        recovered spectral distributions will be clipped. This ensures that the
        returned reflectance is physical and conserves energy, but will cause
        noticeable colour differences in case of very saturated colours.
    cmfs
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Standard observer colour matching functions.
    colourspace
        {:func:`colour.recovery.XYZ_to_sd_Jakob2019`},
        *RGB* colourspace of the target colour. Note that no chromatic
        adaptation is performed between ``illuminant`` and the colourspace
        whitepoint.
    dataset
        {:func:`colour.recovery.XYZ_to_sd_Otsu2018`},
        Dataset to use for reconstruction. The default is to use the published
        data.
    illuminant
        {:func:`colour.recovery.XYZ_to_sd_Jakob2019`,
        :func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Illuminant spectral distribution, default to
        *CIE Standard Illuminant D65*.
    interval
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Wavelength :math:`\\lambda_{i}` range interval in nm. The smaller
        ``interval`` is, the longer the computations will be.
    optimisation_kwargs
        {:func:`colour.recovery.XYZ_to_sd_Jakob2019`,
        :func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Parameters for :func:`scipy.optimize.minimize` and
        :func:`colour.recovery.find_coefficients_Jakob2019` definitions.

    Returns
    -------
    :class:`colour.SpectralDistribution`
        Recovered spectral distribution.

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

    -   *Smits (1999)* method will internally convert given *CIE XYZ*
        tristimulus values to *sRGB* colourspace array assuming equal energy
        illuminant *E*.

    References
    ----------
    :cite:`Jakob2019`,  :cite:`Mallett2019`, :cite:`Meng2015c`,
    :cite:`Otsu2018`, :cite:`Smits1999a`

    Examples
    --------
    *Jakob and Hanika (2009)* reflectance recovery:

    >>> import numpy as np
    >>> from colour import MSDS_CMFS, SDS_ILLUMINANTS, SpectralShape
    >>> from colour.colorimetry import sd_to_XYZ_integration
    >>> from colour.utilities import numpy_print_options
    >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
    >>> cmfs = (
    ...     MSDS_CMFS['CIE 1931 2 Degree Standard Observer'].
    ...     copy().align(SpectralShape(360, 780, 10))
    ... )
    >>> illuminant = SDS_ILLUMINANTS['D65'].copy().align(cmfs.shape)
    >>> sd = XYZ_to_sd(
    ...     XYZ, method='Jakob 2019', cmfs=cmfs, illuminant=illuminant)
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +ELLIPSIS
    SpectralDistribution([[ 360.        ,    0.4893773...],
                          [ 370.        ,    0.3258214...],
                          [ 380.        ,    0.2147792...],
                          [ 390.        ,    0.1482413...],
                          [ 400.        ,    0.1086169...],
                          [ 410.        ,    0.0841255...],
                          [ 420.        ,    0.0683114...],
                          [ 430.        ,    0.0577144...],
                          [ 440.        ,    0.0504267...],
                          [ 450.        ,    0.0453552...],
                          [ 460.        ,    0.0418520...],
                          [ 470.        ,    0.0395259...],
                          [ 480.        ,    0.0381430...],
                          [ 490.        ,    0.0375741...],
                          [ 500.        ,    0.0377685...],
                          [ 510.        ,    0.0387432...],
                          [ 520.        ,    0.0405871...],
                          [ 530.        ,    0.0434783...],
                          [ 540.        ,    0.0477225...],
                          [ 550.        ,    0.0538256...],
                          [ 560.        ,    0.0626314...],
                          [ 570.        ,    0.0755869...],
                          [ 580.        ,    0.0952675...],
                          [ 590.        ,    0.1264265...],
                          [ 600.        ,    0.1779272...],
                          [ 610.        ,    0.2649393...],
                          [ 620.        ,    0.4039779...],
                          [ 630.        ,    0.5832105...],
                          [ 640.        ,    0.7445440...],
                          [ 650.        ,    0.8499970...],
                          [ 660.        ,    0.9094792...],
                          [ 670.        ,    0.9425378...],
                          [ 680.        ,    0.9616376...],
                          [ 690.        ,    0.9732481...],
                          [ 700.        ,    0.9806562...],
                          [ 710.        ,    0.9855873...],
                          [ 720.        ,    0.9889903...],
                          [ 730.        ,    0.9914117...],
                          [ 740.        ,    0.9931801...],
                          [ 750.        ,    0.9945009...],
                          [ 760.        ,    0.9955066...],
                          [ 770.        ,    0.9962855...],
                          [ 780.        ,    0.9968976...]],
                         interpolator=SpragueInterpolator,
                         interpolator_kwargs={},
                         extrapolator=Extrapolator,
                         extrapolator_kwargs={...})
    >>> sd_to_XYZ_integration(sd, cmfs, illuminant) / 100  # doctest: +ELLIPSIS
    array([ 0.2066217...,  0.1220128...,  0.0513958...])

    *Mallett and Yuksel (2019)* reflectance recovery:

    >>> cmfs = (
    ...     MSDS_CMFS['CIE 1931 2 Degree Standard Observer'].
    ...     copy().align(SPECTRAL_SHAPE_sRGB_MALLETT2019)
    ... )
    >>> illuminant = SDS_ILLUMINANTS['D65'].copy().align(cmfs.shape)
    >>> sd = XYZ_to_sd(XYZ, method='Mallett 2019')
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +ELLIPSIS
    SpectralDistribution([[ 380.        ,    0.1735531...],
                          [ 385.        ,    0.1720357...],
                          [ 390.        ,    0.1677721...],
                          [ 395.        ,    0.1576605...],
                          [ 400.        ,    0.1372829...],
                          [ 405.        ,    0.1170849...],
                          [ 410.        ,    0.0895694...],
                          [ 415.        ,    0.0706232...],
                          [ 420.        ,    0.0585765...],
                          [ 425.        ,    0.0523959...],
                          [ 430.        ,    0.0497598...],
                          [ 435.        ,    0.0476057...],
                          [ 440.        ,    0.0465079...],
                          [ 445.        ,    0.0460337...],
                          [ 450.        ,    0.0455839...],
                          [ 455.        ,    0.0452872...],
                          [ 460.        ,    0.0450981...],
                          [ 465.        ,    0.0448895...],
                          [ 470.        ,    0.0449257...],
                          [ 475.        ,    0.0448987...],
                          [ 480.        ,    0.0446834...],
                          [ 485.        ,    0.0441372...],
                          [ 490.        ,    0.0417137...],
                          [ 495.        ,    0.0373832...],
                          [ 500.        ,    0.0357657...],
                          [ 505.        ,    0.0348263...],
                          [ 510.        ,    0.0341953...],
                          [ 515.        ,    0.0337683...],
                          [ 520.        ,    0.0334979...],
                          [ 525.        ,    0.0332991...],
                          [ 530.        ,    0.0331909...],
                          [ 535.        ,    0.0332181...],
                          [ 540.        ,    0.0333387...],
                          [ 545.        ,    0.0334970...],
                          [ 550.        ,    0.0337381...],
                          [ 555.        ,    0.0341847...],
                          [ 560.        ,    0.0346447...],
                          [ 565.        ,    0.0353993...],
                          [ 570.        ,    0.0367367...],
                          [ 575.        ,    0.0392007...],
                          [ 580.        ,    0.0445902...],
                          [ 585.        ,    0.0625633...],
                          [ 590.        ,    0.2965381...],
                          [ 595.        ,    0.4215576...],
                          [ 600.        ,    0.4347139...],
                          [ 605.        ,    0.4385134...],
                          [ 610.        ,    0.4385184...],
                          [ 615.        ,    0.4385249...],
                          [ 620.        ,    0.4374694...],
                          [ 625.        ,    0.4384672...],
                          [ 630.        ,    0.4368251...],
                          [ 635.        ,    0.4340867...],
                          [ 640.        ,    0.4303219...],
                          [ 645.        ,    0.4243257...],
                          [ 650.        ,    0.4159482...],
                          [ 655.        ,    0.4057443...],
                          [ 660.        ,    0.3919874...],
                          [ 665.        ,    0.3742784...],
                          [ 670.        ,    0.3518421...],
                          [ 675.        ,    0.3240127...],
                          [ 680.        ,    0.2955145...],
                          [ 685.        ,    0.2625658...],
                          [ 690.        ,    0.2343423...],
                          [ 695.        ,    0.2174830...],
                          [ 700.        ,    0.2060461...],
                          [ 705.        ,    0.1977437...],
                          [ 710.        ,    0.1916846...],
                          [ 715.        ,    0.1861020...],
                          [ 720.        ,    0.1823908...],
                          [ 725.        ,    0.1807923...],
                          [ 730.        ,    0.1795571...],
                          [ 735.        ,    0.1785623...],
                          [ 740.        ,    0.1775758...],
                          [ 745.        ,    0.1771614...],
                          [ 750.        ,    0.1767431...],
                          [ 755.        ,    0.1764319...],
                          [ 760.        ,    0.1762597...],
                          [ 765.        ,    0.1762209...],
                          [ 770.        ,    0.1761803...],
                          [ 775.        ,    0.1761195...],
                          [ 780.        ,    0.1760763...]],
                         interpolator=SpragueInterpolator,
                         interpolator_kwargs={},
                         extrapolator=Extrapolator,
                         extrapolator_kwargs={...})
    >>> sd_to_XYZ_integration(sd, cmfs, illuminant) / 100
    ... # doctest: +ELLIPSIS
    array([ 0.2065436...,  0.1219996...,  0.0513764...])

    *Meng (2015)* reflectance recovery:

    >>> cmfs = (
    ...     MSDS_CMFS['CIE 1931 2 Degree Standard Observer'].
    ...     copy().align(SpectralShape(360, 780, 10))
    ... )
    >>> illuminant = SDS_ILLUMINANTS['D65'].copy().align(cmfs.shape)
    >>> sd = XYZ_to_sd(
    ...     XYZ, method='Meng 2015', cmfs=cmfs, illuminant=illuminant)
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +SKIP
    SpectralDistribution([[ 360.        ,    0.0762005...],
                          [ 370.        ,    0.0761792...],
                          [ 380.        ,    0.0761363...],
                          [ 390.        ,    0.0761194...],
                          [ 400.        ,    0.0762539...],
                          [ 410.        ,    0.0761671...],
                          [ 420.        ,    0.0754649...],
                          [ 430.        ,    0.0731519...],
                          [ 440.        ,    0.0676701...],
                          [ 450.        ,    0.0577800...],
                          [ 460.        ,    0.0441993...],
                          [ 470.        ,    0.0285064...],
                          [ 480.        ,    0.0138728...],
                          [ 490.        ,    0.0033585...],
                          [ 500.        ,    0.       ...],
                          [ 510.        ,    0.       ...],
                          [ 520.        ,    0.       ...],
                          [ 530.        ,    0.       ...],
                          [ 540.        ,    0.0055767...],
                          [ 550.        ,    0.0317581...],
                          [ 560.        ,    0.0754491...],
                          [ 570.        ,    0.1314115...],
                          [ 580.        ,    0.1937649...],
                          [ 590.        ,    0.2559311...],
                          [ 600.        ,    0.3123173...],
                          [ 610.        ,    0.3584966...],
                          [ 620.        ,    0.3927335...],
                          [ 630.        ,    0.4159458...],
                          [ 640.        ,    0.4306660...],
                          [ 650.        ,    0.4391040...],
                          [ 660.        ,    0.4439497...],
                          [ 670.        ,    0.4463618...],
                          [ 680.        ,    0.4474625...],
                          [ 690.        ,    0.4479868...],
                          [ 700.        ,    0.4482116...],
                          [ 710.        ,    0.4482800...],
                          [ 720.        ,    0.4483472...],
                          [ 730.        ,    0.4484251...],
                          [ 740.        ,    0.4484633...],
                          [ 750.        ,    0.4485071...],
                          [ 760.        ,    0.4484969...],
                          [ 770.        ,    0.4484853...],
                          [ 780.        ,    0.4485134...]],
                         interpolator=SpragueInterpolator,
                         interpolator_kwargs={},
                         extrapolator=Extrapolator,
                         extrapolator_kwargs={...})
    >>> sd_to_XYZ_integration(sd, cmfs, illuminant) / 100  # doctest: +ELLIPSIS
    array([ 0.2065400...,  0.1219722...,  0.0513695...])

    *Otsu, Yamamoto and Hachisuka (2018)* reflectance recovery:

    >>> cmfs = (
    ...     MSDS_CMFS['CIE 1931 2 Degree Standard Observer'].
    ...     copy().align(SPECTRAL_SHAPE_OTSU2018)
    ... )
    >>> illuminant = SDS_ILLUMINANTS['D65'].copy().align(cmfs.shape)
    >>> sd = XYZ_to_sd(
    ...     XYZ, method='Otsu 2018', cmfs=cmfs, illuminant=illuminant)
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +ELLIPSIS
    SpectralDistribution([[ 380.        ,    0.0601939...],
                          [ 390.        ,    0.0568063...],
                          [ 400.        ,    0.0517429...],
                          [ 410.        ,    0.0495841...],
                          [ 420.        ,    0.0502007...],
                          [ 430.        ,    0.0506489...],
                          [ 440.        ,    0.0510020...],
                          [ 450.        ,    0.0493782...],
                          [ 460.        ,    0.0468046...],
                          [ 470.        ,    0.0437132...],
                          [ 480.        ,    0.0416957...],
                          [ 490.        ,    0.0403783...],
                          [ 500.        ,    0.0405197...],
                          [ 510.        ,    0.0406031...],
                          [ 520.        ,    0.0416912...],
                          [ 530.        ,    0.0430956...],
                          [ 540.        ,    0.0444474...],
                          [ 550.        ,    0.0459336...],
                          [ 560.        ,    0.0507631...],
                          [ 570.        ,    0.0628967...],
                          [ 580.        ,    0.0844661...],
                          [ 590.        ,    0.1334277...],
                          [ 600.        ,    0.2262428...],
                          [ 610.        ,    0.3599330...],
                          [ 620.        ,    0.4885571...],
                          [ 630.        ,    0.5752546...],
                          [ 640.        ,    0.6193023...],
                          [ 650.        ,    0.6450744...],
                          [ 660.        ,    0.6610548...],
                          [ 670.        ,    0.6688673...],
                          [ 680.        ,    0.6795426...],
                          [ 690.        ,    0.6887933...],
                          [ 700.        ,    0.7003469...],
                          [ 710.        ,    0.7084128...],
                          [ 720.        ,    0.7154674...],
                          [ 730.        ,    0.7234334...]],
                         interpolator=SpragueInterpolator,
                         interpolator_kwargs={},
                         extrapolator=Extrapolator,
                         extrapolator_kwargs={...})
    >>> sd_to_XYZ_integration(sd, cmfs, illuminant) / 100  # doctest: +ELLIPSIS
    array([ 0.2065494...,  0.1219712...,  0.0514002...])

    *Smits (1999)* reflectance recovery:

    >>> cmfs = (
    ...     MSDS_CMFS['CIE 1931 2 Degree Standard Observer'].
    ...     copy().align(SpectralShape(360, 780, 10))
    ... )
    >>> illuminant = SDS_ILLUMINANTS['E'].copy().align(cmfs.shape)
    >>> sd = XYZ_to_sd(XYZ, method='Smits 1999')
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +ELLIPSIS
    SpectralDistribution([[ 380.        ,    0.0787830...],
                          [ 417.7778    ,    0.0622018...],
                          [ 455.5556    ,    0.0446206...],
                          [ 493.3333    ,    0.0352220...],
                          [ 531.1111    ,    0.0324149...],
                          [ 568.8889    ,    0.0330105...],
                          [ 606.6667    ,    0.3207115...],
                          [ 644.4444    ,    0.3836164...],
                          [ 682.2222    ,    0.3836164...],
                          [ 720.        ,    0.3835649...]],
                         interpolator=LinearInterpolator,
                         interpolator_kwargs={},
                         extrapolator=Extrapolator,
                         extrapolator_kwargs={...})
    >>> sd_to_XYZ_integration(sd, cmfs, illuminant) / 100  # doctest: +ELLIPSIS
    array([ 0.1894770...,  0.1126470...,  0.0474420...])
    """

    a = as_float_array(XYZ)
    method = validate_method(method, XYZ_TO_SD_METHODS)

    function = XYZ_TO_SD_METHODS[method]

    if function is RGB_to_sd_Smits1999:
        from colour.recovery.smits1999 import XYZ_to_RGB_Smits1999

        a = XYZ_to_RGB_Smits1999(XYZ)
    elif function is RGB_to_sd_Mallett2019:
        from colour.models import XYZ_to_sRGB

        a = XYZ_to_sRGB(XYZ, apply_cctf_encoding=False)

    return function(a, **filter_kwargs(function, **kwargs))
예제 #6
0
def XYZ_to_sd(XYZ, method='Meng 2015', **kwargs):
    """
    Recovers the spectral distribution of given *CIE XYZ* tristimulus
    values using given method.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values to recover the spectral distribution
        from.
    method : unicode, optional
        **{'Meng 2015', 'Smits 1999'}**,
        Computation method.

    Other Parameters
    ----------------
    cmfs : XYZ_ColourMatchingFunctions
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Standard observer colour matching functions.
    interval : numeric, optional
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Wavelength :math:`\\lambda_{i}` range interval in nm. The smaller
        ``interval`` is, the longer the computations will be.
    optimisation_parameters : dict_like, optional
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Parameters for :func:`scipy.optimize.minimize` definition.

    Returns
    -------
    SpectralDistribution
        Recovered spectral distribution.

    Notes
    -----

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

    -   *Smits (1999)* method will internally convert given *CIE XYZ*
        tristimulus values to *RGB* colourspace array assuming equal energy
        illuminant *E*.

    References
    ----------
    :cite:`Meng2015c`, :cite:`Smits1999a`

    Examples
    --------

    *Meng (2015)* reflectance recovery:

    >>> import numpy as np
    >>> from colour.utilities import numpy_print_options
    >>> from colour.colorimetry import sd_to_XYZ_integration
    >>> XYZ = np.array([0.21781186, 0.12541048, 0.04697113])
    >>> sd = XYZ_to_sd(XYZ, interval=10)
    >>> with numpy_print_options(suppress=True):
    ...     # Doctests skip for Python 2.x compatibility.
    ...     sd  # doctest: +SKIP
    SpectralDistribution([[ 360.        ,    0.0741540...],
                          [ 370.        ,    0.0741409...],
                          [ 380.        ,    0.0741287...],
                          [ 390.        ,    0.0740876...],
                          [ 400.        ,    0.0740215...],
                          [ 410.        ,    0.0738692...],
                          [ 420.        ,    0.0731412...],
                          [ 430.        ,    0.0705798...],
                          [ 440.        ,    0.0647359...],
                          [ 450.        ,    0.0551962...],
                          [ 460.        ,    0.0425597...],
                          [ 470.        ,    0.0283678...],
                          [ 480.        ,    0.0147370...],
                          [ 490.        ,    0.0044271...],
                          [ 500.        ,    0.0000302...],
                          [ 510.        ,    0.       ...],
                          [ 520.        ,    0.       ...],
                          [ 530.        ,    0.       ...],
                          [ 540.        ,    0.0051962...],
                          [ 550.        ,    0.0289516...],
                          [ 560.        ,    0.0687006...],
                          [ 570.        ,    0.1204130...],
                          [ 580.        ,    0.1789378...],
                          [ 590.        ,    0.2383451...],
                          [ 600.        ,    0.2930157...],
                          [ 610.        ,    0.3387433...],
                          [ 620.        ,    0.3734033...],
                          [ 630.        ,    0.3972820...],
                          [ 640.        ,    0.4125508...],
                          [ 650.        ,    0.4215782...],
                          [ 660.        ,    0.4265503...],
                          [ 670.        ,    0.4292647...],
                          [ 680.        ,    0.4307000...],
                          [ 690.        ,    0.4313993...],
                          [ 700.        ,    0.4316316...],
                          [ 710.        ,    0.4317109...],
                          [ 720.        ,    0.4317684...],
                          [ 730.        ,    0.4317864...],
                          [ 740.        ,    0.4317972...],
                          [ 750.        ,    0.4318385...],
                          [ 760.        ,    0.4318576...],
                          [ 770.        ,    0.4318455...],
                          [ 780.        ,    0.4317877...],
                          [ 790.        ,    0.4318119...],
                          [ 800.        ,    0.4318070...],
                          [ 810.        ,    0.4318089...],
                          [ 820.        ,    0.4317781...],
                          [ 830.        ,    0.4317733...]],
                         interpolator=SpragueInterpolator,
                         interpolator_args={},
                         extrapolator=Extrapolator,
                         extrapolator_args={...})
    >>> sd_to_XYZ_integration(sd) / 100  # doctest: +ELLIPSIS
    array([ 0.2178552...,  0.1254142...,  0.0470105...])

    *Smits (1999)* reflectance recovery:

    >>> sd = XYZ_to_sd(XYZ, method='Smits 1999')
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +ELLIPSIS
    SpectralDistribution([[ 380.        ,    0.07691923],
                          [ 417.7778    ,    0.0587005 ],
                          [ 455.5556    ,    0.03943195],
                          [ 493.3333    ,    0.03024978],
                          [ 531.1111    ,    0.02750692],
                          [ 568.8889    ,    0.02808645],
                          [ 606.6667    ,    0.34298985],
                          [ 644.4444    ,    0.41185795],
                          [ 682.2222    ,    0.41185795],
                          [ 720.        ,    0.41180754]],
                         interpolator=LinearInterpolator,
                         interpolator_args={},
                         extrapolator=Extrapolator,
                         extrapolator_args={...})
    >>> sd_to_XYZ_integration(sd) / 100  # doctest: +ELLIPSIS
    array([ 0.2004540...,  0.1105632...,  0.0420963...])
    """

    a = as_float_array(XYZ)

    function = XYZ_TO_SD_METHODS[method]

    if function is RGB_to_sd_Smits1999:
        from colour.recovery.smits1999 import XYZ_to_RGB_Smits1999

        a = XYZ_to_RGB_Smits1999(XYZ)

    return function(a, **filter_kwargs(function, **kwargs))
예제 #7
0
# -*- coding: utf-8 -*-
"""
Showcases reflectance recovery computations using *Smits (1999)* method.
"""

import numpy as np

import colour
from colour.recovery.smits1999 import XYZ_to_RGB_Smits1999
from colour.utilities import message_box

message_box('"Smits (1999)" - Reflectance Recovery Computations')

XYZ = np.array([1.14176346, 1.00000000, 0.49815206])
RGB = XYZ_to_RGB_Smits1999(XYZ)
message_box(('Recovering reflectance using "Smits (1999)" method from '
             'given "RGB" colourspace array:\n'
             '\n\tRGB: {0}'.format(RGB)))
print(colour.XYZ_to_sd(XYZ, method='Smits 1999'))
print(colour.recovery.RGB_to_sd_Smits1999(RGB))

print('\n')

message_box(
    ('An analysis of "Smits (1999)" method is available at the '
     'following url : '
     'http://nbviewer.jupyter.org/github/colour-science/colour-website/'
     'blob/master/ipython/about_reflectance_recovery.ipynb'))
예제 #8
0
def XYZ_to_sd(XYZ, method='Meng 2015', **kwargs):
    """
    Recovers the spectral distribution of given *CIE XYZ* tristimulus
    values using given method.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values to recover the spectral distribution
        from.
    method : unicode, optional
        **{'Meng 2015', 'Smits 1999'}**,
        Computation method.

    Other Parameters
    ----------------
    cmfs : XYZ_ColourMatchingFunctions
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Standard observer colour matching functions.
    interval : numeric, optional
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Wavelength :math:`\\lambda_{i}` range interval in nm. The smaller
        ``interval`` is, the longer the computations will be.
    optimisation_parameters : dict_like, optional
        {:func:`colour.recovery.XYZ_to_sd_Meng2015`},
        Parameters for :func:`scipy.optimize.minimize` definition.

    Returns
    -------
    SpectralDistribution
        Recovered spectral distribution.

    Notes
    -----

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

    -   *Smits (1999)* method will internally convert given *CIE XYZ*
        tristimulus values to *RGB* colourspace array assuming equal energy
        illuminant *E*.

    References
    ----------
    :cite:`Meng2015c`, :cite:`Smits1999a`

    Examples
    --------

    *Meng (2015)* reflectance recovery:

    >>> import numpy as np
    >>> from colour.utilities import numpy_print_options
    >>> from colour.colorimetry import (
    ...     STANDARD_OBSERVERS_CMFS, SpectralShape, sd_to_XYZ_integration)
    >>> XYZ = np.array([0.21781186, 0.12541048, 0.04697113])
    >>> cmfs = (
    ...     STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].
    ...     copy().align(SpectralShape(360, 780, 10))
    ... )
    >>> sd = XYZ_to_sd(XYZ, cmfs=cmfs)
    >>> with numpy_print_options(suppress=True):
    ...     # Doctests skip for Python 2.x compatibility.
    ...     sd  # doctest: +SKIP
    SpectralDistribution([[ 360.        ,    0.0780114...],
                          [ 370.        ,    0.0780316...],
                          [ 380.        ,    0.0780471...],
                          [ 390.        ,    0.0780351...],
                          [ 400.        ,    0.0779702...],
                          [ 410.        ,    0.0778033...],
                          [ 420.        ,    0.0770958...],
                          [ 430.        ,    0.0748008...],
                          [ 440.        ,    0.0693230...],
                          [ 450.        ,    0.0601136...],
                          [ 460.        ,    0.0477407...],
                          [ 470.        ,    0.0334964...],
                          [ 480.        ,    0.0193352...],
                          [ 490.        ,    0.0074858...],
                          [ 500.        ,    0.0001225...],
                          [ 510.        ,    0.       ...],
                          [ 520.        ,    0.       ...],
                          [ 530.        ,    0.       ...],
                          [ 540.        ,    0.0124896...],
                          [ 550.        ,    0.0389831...],
                          [ 560.        ,    0.0775105...],
                          [ 570.        ,    0.1247947...],
                          [ 580.        ,    0.1765339...],
                          [ 590.        ,    0.2281918...],
                          [ 600.        ,    0.2751347...],
                          [ 610.        ,    0.3140115...],
                          [ 620.        ,    0.3433561...],
                          [ 630.        ,    0.3635777...],
                          [ 640.        ,    0.3765428...],
                          [ 650.        ,    0.3841726...],
                          [ 660.        ,    0.3883633...],
                          [ 670.        ,    0.3905415...],
                          [ 680.        ,    0.3916742...],
                          [ 690.        ,    0.3922554...],
                          [ 700.        ,    0.3925427...],
                          [ 710.        ,    0.3926783...],
                          [ 720.        ,    0.3927330...],
                          [ 730.        ,    0.3927586...],
                          [ 740.        ,    0.3927548...],
                          [ 750.        ,    0.3927681...],
                          [ 760.        ,    0.3927813...],
                          [ 770.        ,    0.3927840...],
                          [ 780.        ,    0.3927536...]],
                         interpolator=SpragueInterpolator,
                         interpolator_args={},
                         extrapolator=Extrapolator,
                         extrapolator_args={...})
    >>> sd_to_XYZ_integration(sd) / 100  # doctest: +ELLIPSIS
    array([ 0.2178545...,  0.1254141...,  0.0470095...])

    *Smits (1999)* reflectance recovery:

    >>> sd = XYZ_to_sd(XYZ, method='Smits 1999')
    >>> with numpy_print_options(suppress=True):
    ...     sd  # doctest: +ELLIPSIS
    SpectralDistribution([[ 380.        ,    0.07691923],
                          [ 417.7778    ,    0.0587005 ],
                          [ 455.5556    ,    0.03943195],
                          [ 493.3333    ,    0.03024978],
                          [ 531.1111    ,    0.02750692],
                          [ 568.8889    ,    0.02808645],
                          [ 606.6667    ,    0.34298985],
                          [ 644.4444    ,    0.41185795],
                          [ 682.2222    ,    0.41185795],
                          [ 720.        ,    0.41180754]],
                         interpolator=LinearInterpolator,
                         interpolator_args={},
                         extrapolator=Extrapolator,
                         extrapolator_args={...})
    >>> sd_to_XYZ_integration(sd) / 100  # doctest: +ELLIPSIS
    array([ 0.2004523...,  0.1105627...,  0.0420964...])
    """

    a = as_float_array(XYZ)

    function = XYZ_TO_SD_METHODS[method]

    if function is RGB_to_sd_Smits1999:
        from colour.recovery.smits1999 import XYZ_to_RGB_Smits1999

        a = XYZ_to_RGB_Smits1999(XYZ)

    return function(a, **filter_kwargs(function, **kwargs))
예제 #9
0
def XYZ_to_spectral(XYZ, method='Meng 2015', **kwargs):
    """
    Recovers the spectral power distribution of given *CIE XYZ* tristimulus
    values using given method.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values to recover the spectral power distribution
        from.
    method : unicode, optional
        **{'Meng 2015', 'Smits 1999'}**,
        Computation method.

    Other Parameters
    ----------------
    cmfs : XYZ_ColourMatchingFunctions
        {:func:`colour.recovery.XYZ_to_spectral_Meng2015`},
        Standard observer colour matching functions.
    interval : numeric, optional
        {:func:`colour.recovery.XYZ_to_spectral_Meng2015`},
        Wavelength :math:`\lambda_{i}` range interval in nm. The smaller
        ``interval`` is, the longer the computations will be.
    tolerance : numeric, optional
        {:func:`colour.recovery.XYZ_to_spectral_Meng2015`},
        Tolerance for termination. The lower ``tolerance`` is, the smoother
        the recovered spectral power distribution will be.
    maximum_iterations : int, optional
        {:func:`colour.recovery.XYZ_to_spectral_Meng2015`},
        Maximum number of iterations to perform.

    Returns
    -------
    SpectralPowerDistribution
        Recovered spectral power distribution.

    Notes
    -----
    -   *Smits (1999)* method will internally convert given *CIE XYZ*
        tristimulus values to *RGB* colourspace array assuming equal energy
        illuminant *E*.

    References
    ----------
    -   :cite:`Meng2015c`
    -   :cite:`Smits1999a`

    Examples
    --------

    *Meng (2015)* reflectance recovery:

    >>> from colour.utilities import numpy_print_options
    >>> from colour.colorimetry import spectral_to_XYZ_integration
    >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313])
    >>> spd = XYZ_to_spectral(XYZ, interval=10)
    >>> with numpy_print_options(suppress=True):
    ...     spd  # doctest: +ELLIPSIS
    SpectralPowerDistribution([[ 360.        ,    0.0788075...],
                               [ 370.        ,    0.0788543...],
                               [ 380.        ,    0.0788825...],
                               [ 390.        ,    0.0788714...],
                               [ 400.        ,    0.0788911...],
                               [ 410.        ,    0.07893  ...],
                               [ 420.        ,    0.0797471...],
                               [ 430.        ,    0.0813339...],
                               [ 440.        ,    0.0840145...],
                               [ 450.        ,    0.0892826...],
                               [ 460.        ,    0.0965359...],
                               [ 470.        ,    0.1053176...],
                               [ 480.        ,    0.1150921...],
                               [ 490.        ,    0.1244252...],
                               [ 500.        ,    0.1326083...],
                               [ 510.        ,    0.1390282...],
                               [ 520.        ,    0.1423548...],
                               [ 530.        ,    0.1414636...],
                               [ 540.        ,    0.1365195...],
                               [ 550.        ,    0.1277319...],
                               [ 560.        ,    0.1152622...],
                               [ 570.        ,    0.1004513...],
                               [ 580.        ,    0.0844187...],
                               [ 590.        ,    0.0686863...],
                               [ 600.        ,    0.0543013...],
                               [ 610.        ,    0.0423486...],
                               [ 620.        ,    0.0333861...],
                               [ 630.        ,    0.0273558...],
                               [ 640.        ,    0.0233407...],
                               [ 650.        ,    0.0211208...],
                               [ 660.        ,    0.0197248...],
                               [ 670.        ,    0.0187157...],
                               [ 680.        ,    0.0181510...],
                               [ 690.        ,    0.0179691...],
                               [ 700.        ,    0.0179247...],
                               [ 710.        ,    0.0178665...],
                               [ 720.        ,    0.0178005...],
                               [ 730.        ,    0.0177570...],
                               [ 740.        ,    0.0177090...],
                               [ 750.        ,    0.0175743...],
                               [ 760.        ,    0.0175058...],
                               [ 770.        ,    0.0174492...],
                               [ 780.        ,    0.0174984...],
                               [ 790.        ,    0.0175667...],
                               [ 800.        ,    0.0175657...],
                               [ 810.        ,    0.0175319...],
                               [ 820.        ,    0.0175184...],
                               [ 830.        ,    0.0175390...]],
                              interpolator=SpragueInterpolator,
                              interpolator_args={},
                              extrapolator=Extrapolator,
                              extrapolator_args={...})
    >>> spectral_to_XYZ_integration(spd) / 100  # doctest: +ELLIPSIS
    array([ 0.0705100...,  0.1007987...,  0.0956738...])

    *Smits (1999)* reflectance recovery:

    >>> spd = XYZ_to_spectral(XYZ, method='Smits 1999')
    >>> with numpy_print_options(suppress=True):
    ...     spd  # doctest: +ELLIPSIS
    SpectralPowerDistribution([[ 380.        ,    0.0908046...],
                               [ 417.7778    ,    0.0887761...],
                               [ 455.5556    ,    0.0939795...],
                               [ 493.3333    ,    0.1236033...],
                               [ 531.1111    ,    0.1315788...],
                               [ 568.8889    ,    0.1293411...],
                               [ 606.6667    ,    0.0392680...],
                               [ 644.4444    ,    0.0214496...],
                               [ 682.2222    ,    0.0214496...],
                               [ 720.        ,    0.0215462...]],
                              interpolator=CubicSplineInterpolator,
                              interpolator_args={},
                              extrapolator=Extrapolator,
                              extrapolator_args={...})
    >>> spectral_to_XYZ_integration(spd) / 100  # doctest: +ELLIPSIS
    array([ 0.0753341...,  0.1054586...,  0.0977855...])
    """

    a = np.asarray(XYZ)

    function = REFLECTANCE_RECOVERY_METHODS[method]

    if function is RGB_to_spectral_Smits1999:
        from colour.recovery.smits1999 import XYZ_to_RGB_Smits1999

        a = XYZ_to_RGB_Smits1999(XYZ)

    return function(a, **filter_kwargs(function, **kwargs))