Пример #1
0
    def test_handle_arguments_deprecation(self):
        """
        Tests :func:`colour.utilities.deprecation.handle_arguments_deprecation`
        definition.
        """

        changes = {
            'ArgumentRenamed': [[
                'argument_1_name',
                'argument_1_new_name',
            ]],
            'ArgumentFutureRename': [[
                'argument_2_name',
                'argument_2_new_name',
            ]],
            'ArgumentRemoved': ['argument_3_name'],
            'ArgumentFutureRemove': ['argument_4_name'],
        }

        self.assertDictEqual(
            handle_arguments_deprecation(changes,
                                         argument_1_name=True,
                                         argument_2_name=True,
                                         argument_4_name=True), {
                                             'argument_1_new_name': True,
                                             'argument_2_new_name': True,
                                             'argument_4_name': True
                                         })

        self.assertRaises(
            ValueError,
            lambda: handle_arguments_deprecation(changes, argument_3_name=True
                                                 ),
        )
Пример #2
0
def log_decoding_Log3G10(y, method='v2', **kwargs):
    """
    Defines the *Log3G10* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    y : numeric or array_like
        Non-linear data :math:`y`.
    method : unicode, optional
        **{'v1', 'v2'}**,
        Computation method.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`x`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Nattress2016a`

    Examples
    --------
    >>> log_decoding_Log3G10(1.0)  # doctest: +ELLIPSIS
    184.3223476...
    >>> log_decoding_Log3G10(1.0 / 3, method='v1')  # doctest: +ELLIPSIS
    0.1799994...
    """

    method = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['legacy_curve', 'method']],
        }, **kwargs).get('method', method)
    method = {True: 'v1', False: 'v2'}.get(method, method)

    return LOG3G10_DECODING_METHODS[method](y)
Пример #3
0
def apply(self,
          RGB,
          inverse=False,
          interpolator=LinearInterpolator,
          interpolator_kwargs=None,
          **kwargs):
    """
    Applies the *LUT* to given *RGB* colourspace array using given method.
    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array to apply the *LUT* onto.
    inverse : boolean, optional
        Checks if the LUT has to be applied in forward or backward
        direction.
    interpolator : object, optional
        Interpolator class type to use as interpolating function.
    interpolator_kwargs : dict_like, optional
        Arguments to use when instantiating the interpolating function.
    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.
    Returns
    -------
    ndarray
        Interpolated *RGB* colourspace array.
    """

    interpolator_kwargs = handle_arguments_deprecation({
        'ArgumentRenamed': [['interpolator_args', 'interpolator_kwargs']],
    }, **kwargs).get('interpolator_kwargs', interpolator_kwargs)

    if interpolator_kwargs is None:
        interpolator_kwargs = {}

    if inverse:
        SIZE = len(self._table)
        LUT_inverse = colour.LUT1D(size=SIZE)
        LUT_inverse.table = colour.Extrapolator(
            colour.LinearInterpolator(self._table, LUT_inverse.table))(LUT_inverse.table)
        RGB_i = LUT_inverse.apply(RGB)
        
        return RGB_i

    else:    
        if self.is_domain_explicit():
            samples = self.domain
        else:
            domain_min, domain_max = self.domain

        samples = np.linspace(domain_min, domain_max, self._table.size)

        RGB_interpolator = interpolator(samples, self._table,
                                            **interpolator_kwargs)
        return RGB_interpolator(RGB)
Пример #4
0
    def test_handle_arguments_deprecation(self):
        """
        Test :func:`colour.utilities.deprecation.handle_arguments_deprecation`
        definition.
        """

        changes = {
            "ArgumentRenamed": [
                [
                    "argument_1_name",
                    "argument_1_new_name",
                ]
            ],
            "ArgumentFutureRename": [
                [
                    "argument_2_name",
                    "argument_2_new_name",
                ]
            ],
            "ArgumentRemoved": ["argument_3_name"],
            "ArgumentFutureRemove": ["argument_4_name"],
        }

        self.assertDictEqual(
            handle_arguments_deprecation(
                changes,
                argument_1_name=True,
                argument_2_name=True,
                argument_3_name=True,
                argument_4_name=True,
                argument_5_name=True,
            ),
            {
                "argument_1_new_name": True,
                "argument_2_new_name": True,
                "argument_4_name": True,
                "argument_5_name": True,
            },
        )
Пример #5
0
def plot_sds_in_chromaticity_diagram_CIE1960UCS(
        sds,
        cmfs='CIE 1931 2 Degree Standard Observer',
        chromaticity_diagram_callable_CIE1960UCS=(
            plot_chromaticity_diagram_CIE1960UCS),
        annotate_kwargs=None,
        plot_kwargs=None,
        **kwargs):
    """
    Plots given spectral distribution chromaticity coordinates into the
    *CIE 1960 UCS Chromaticity Diagram*.

    Parameters
    ----------
    sds : array_like or MultiSpectralDistributions
        Spectral distributions or multi-spectral distributions to
        plot. `sds` can be a single :class:`colour.MultiSpectralDistributions`
        class instance, a list of :class:`colour.MultiSpectralDistributions`
        class instances or a list of :class:`colour.SpectralDistribution` class
        instances.
    cmfs : unicode or XYZ_ColourMatchingFunctions, optional
        Standard observer colour matching functions used for computing the
        spectral locus boundaries. ``cmfs`` can be of any type or form
        supported by the :func:`colour.plotting.filter_cmfs` definition.
    chromaticity_diagram_callable_CIE1960UCS : callable, optional
        Callable responsible for drawing the
        *CIE 1960 UCS Chromaticity Diagram*.
    annotate_kwargs : dict or array_like, optional
        Keyword arguments for the :func:`plt.annotate` definition, used to
        annotate the resulting chromaticity coordinates with their respective
        spectral distribution names. ``annotate_kwargs`` can be either a single
        dictionary applied to all the arrows with same settings or a sequence
        of dictionaries with different settings for each spectral distribution.
        The following special keyword arguments can also be used:

        -   *annotate* : bool, whether to annotate the spectral distributions.
    plot_kwargs : dict or array_like, optional
        Keyword arguments for the :func:`plt.plot` definition, used to control
        the style of the plotted spectral distributions. ``plot_kwargs`` can be
        either a single dictionary applied to all the plotted spectral
        distributions with same settings or a sequence of dictionaries with
        different settings for each plotted spectral distributions.
        The following special keyword arguments can also be used:

        -   *illuminant* : unicode or :class:`colour.SpectralDistribution`, the
            illuminant used to compute the spectral distributions colours. The
            default is the illuminant associated with the whitepoint of the
            default plotting colourspace. ``illuminant`` can be of any type or
            form supported by the :func:`colour.plotting.filter_cmfs`
            definition.
        -   *cmfs* : unicode, the standard observer colour matching functions
            used for computing the spectral distributions colours. ``cmfs`` can
            be of any type or form supported by the
            :func:`colour.plotting.filter_cmfs` definition.
        -   *normalise_sd_colours* : bool, whether to normalise the computed
            spectral distributions colours. The default is *True*.
        -   *use_sd_colours* : bool, whether to use the computed spectral
            distributions colours under the plotting colourspace illuminant.
            Alternatively, it is possible to use the :func:`plt.plot`
            definition ``color`` argument with pre-computed values. The default
            is *True*.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.diagrams.plot_chromaticity_diagram`,
        :func:`colour.plotting.render`},
        Please refer to the documentation of the previously listed definitions.
        Also handles keywords arguments for deprecation management.

    Returns
    -------
    tuple
        Current figure and axes.

    Examples
    --------
    >>> A = SDS_ILLUMINANTS['A']
    >>> D65 = SDS_ILLUMINANTS['D65']
    >>> plot_sds_in_chromaticity_diagram_CIE1960UCS([A, D65])
    ... # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_\
Plot_SDS_In_Chromaticity_Diagram_CIE1960UCS.png
        :align: center
        :alt: plot_sds_in_chromaticity_diagram_CIE1960UCS
    """

    annotate_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['annotate_parameters', 'annotate_kwargs']],
        }, **kwargs).get('annotate_kwargs', annotate_kwargs)

    settings = dict(kwargs)
    settings.update({'method': 'CIE 1960 UCS'})

    return plot_sds_in_chromaticity_diagram(
        sds,
        cmfs,
        chromaticity_diagram_callable_CIE1960UCS,
        annotate_kwargs=annotate_kwargs,
        plot_kwargs=plot_kwargs,
        **settings)
Пример #6
0
def log_decoding_CanonLog2(clog2,
                           bit_depth=10,
                           in_normalised_code_value=True,
                           out_reflection=True,
                           **kwargs):
    """
    Defines the *Canon Log 2* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    clog2 : numeric or array_like
        *Canon Log 2* non-linear data.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the *Canon Log 2* non-linear data is encoded with normalised
        code values.
    out_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`x`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Canona`

    Examples
    --------
    >>> log_decoding_CanonLog2(39.825469498316735 / 100)  # doctest: +ELLIPSIS
    0.1799999...
    """

    in_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
        }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    clog2 = to_domain_1(clog2)

    clog2 = (legal_to_full(clog2, bit_depth)
             if in_normalised_code_value else clog2)

    x = np.where(
        clog2 < 0.035388128,
        -(10**((0.035388128 - clog2) / 0.281863093) - 1) / 87.09937546,
        (10**((clog2 - 0.035388128) / 0.281863093) - 1) / 87.09937546,
    )

    if out_reflection:
        x = x * 0.9

    return as_float(from_range_1(x))
Пример #7
0
def plot_sds_in_chromaticity_diagram(
        sds,
        cmfs='CIE 1931 2 Degree Standard Observer',
        chromaticity_diagram_callable=plot_chromaticity_diagram,
        method='CIE 1931',
        annotate_kwargs=None,
        plot_kwargs=None,
        **kwargs):
    """
    Plots given spectral distribution chromaticity coordinates into the
    *Chromaticity Diagram* using given method.

    Parameters
    ----------
    sds : array_like or MultiSpectralDistributions
        Spectral distributions or multi-spectral distributions to
        plot. `sds` can be a single
        :class:`colour.MultiSpectralDistributions` class instance, a list
        of :class:`colour.MultiSpectralDistributions` class instances or a
        list of :class:`colour.SpectralDistribution` class instances.
    cmfs : unicode or XYZ_ColourMatchingFunctions, optional
        Standard observer colour matching functions used for computing the
        spectral locus boundaries. ``cmfs`` can be of any type or form
        supported by the :func:`colour.plotting.filter_cmfs` definition.
    chromaticity_diagram_callable : callable, optional
        Callable responsible for drawing the *Chromaticity Diagram*.
    method : unicode, optional
        **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**,
        *Chromaticity Diagram* method.
    annotate_kwargs : dict or array_like, optional
        Keyword arguments for the :func:`plt.annotate` definition, used to
        annotate the resulting chromaticity coordinates with their respective
        spectral distribution names. ``annotate_kwargs`` can be either a single
        dictionary applied to all the arrows with same settings or a sequence
        of dictionaries with different settings for each spectral distribution.
        The following special keyword arguments can also be used:

        -   *annotate* : bool, whether to annotate the spectral distributions.
    plot_kwargs : dict or array_like, optional
        Keyword arguments for the :func:`plt.plot` definition, used to control
        the style of the plotted spectral distributions. ``plot_kwargs`` can be
        either a single dictionary applied to all the plotted spectral
        distributions with same settings or a sequence of dictionaries with
        different settings for each plotted spectral distributions.
        The following special keyword arguments can also be used:

        -   *illuminant* : unicode or :class:`colour.SpectralDistribution`, the
            illuminant used to compute the spectral distributions colours. The
            default is the illuminant associated with the whitepoint of the
            default plotting colourspace. ``illuminant`` can be of any type or
            form supported by the :func:`colour.plotting.filter_cmfs`
            definition.
        -   *cmfs* : unicode, the standard observer colour matching functions
            used for computing the spectral distributions colours. ``cmfs`` can
            be of any type or form supported by the
            :func:`colour.plotting.filter_cmfs` definition.
        -   *normalise_sd_colours* : bool, whether to normalise the computed
            spectral distributions colours. The default is *True*.
        -   *use_sd_colours* : bool, whether to use the computed spectral
            distributions colours under the plotting colourspace illuminant.
            Alternatively, it is possible to use the :func:`plt.plot`
            definition ``color`` argument with pre-computed values. The default
            is *True*.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.diagrams.plot_chromaticity_diagram`,
        :func:`colour.plotting.render`},
        Please refer to the documentation of the previously listed definitions.
        Also handles keywords arguments for deprecation management.

    Returns
    -------
    tuple
        Current figure and axes.

    Examples
    --------
    >>> A = SDS_ILLUMINANTS['A']
    >>> D65 = SDS_ILLUMINANTS['D65']
    >>> annotate_kwargs = [
    ...     {'xytext': (-25, 15), 'arrowprops':{'arrowstyle':'-'}},
    ...     {}
    ... ]
    >>> plot_kwargs = [
    ...     {
    ...         'illuminant': SDS_ILLUMINANTS['E'],
    ...         'markersize' : 15,
    ...         'normalise_sd_colours': True,
    ...         'use_sd_colours': True
    ...     },
    ...     {'illuminant': SDS_ILLUMINANTS['E']},
    ... ]
    >>> plot_sds_in_chromaticity_diagram(
    ...     [A, D65], annotate_kwargs=annotate_kwargs, plot_kwargs=plot_kwargs)
    ... # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_Plot_SDS_In_Chromaticity_Diagram.png
        :align: center
        :alt: plot_sds_in_chromaticity_diagram
    """

    annotate_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['annotate_parameters', 'annotate_kwargs']],
        }, **kwargs).get('annotate_kwargs', annotate_kwargs)

    sds = sds_and_msds_to_sds(sds)

    settings = {'uniform': True}
    settings.update(kwargs)

    _figure, axes = artist(**settings)

    method = method.upper()

    settings.update({
        'axes': axes,
        'standalone': False,
        'method': method,
        'cmfs': cmfs,
    })

    chromaticity_diagram_callable(**settings)

    if method == 'CIE 1931':

        def XYZ_to_ij(XYZ):
            """
            Converts given *CIE XYZ* tristimulus values to *ij* chromaticity
            coordinates.
            """

            return XYZ_to_xy(XYZ)

        bounding_box = (-0.1, 0.9, -0.1, 0.9)
    elif method == 'CIE 1960 UCS':

        def XYZ_to_ij(XYZ):
            """
            Converts given *CIE XYZ* tristimulus values to *ij* chromaticity
            coordinates.
            """

            return UCS_to_uv(XYZ_to_UCS(XYZ))

        bounding_box = (-0.1, 0.7, -0.2, 0.6)

    elif method == 'CIE 1976 UCS':

        def XYZ_to_ij(XYZ):
            """
            Converts given *CIE XYZ* tristimulus values to *ij* chromaticity
            coordinates.
            """

            return Luv_to_uv(XYZ_to_Luv(XYZ))

        bounding_box = (-0.1, 0.7, -0.1, 0.7)
    else:
        raise ValueError(
            'Invalid method: "{0}", must be one of '
            '[\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\']'.format(
                method))

    annotate_settings_collection = [{
        'annotate': True,
        'xytext': (-50, 30),
        'textcoords': 'offset points',
        'arrowprops': CONSTANTS_ARROW_STYLE,
    } for _ in range(len(sds))]

    if annotate_kwargs is not None:
        update_settings_collection(annotate_settings_collection,
                                   annotate_kwargs, len(sds))

    plot_settings_collection = [{
        'color':
        CONSTANTS_COLOUR_STYLE.colour.brightest,
        'label':
        '{0}'.format(sd.strict_name),
        'marker':
        'o',
        'markeredgecolor':
        CONSTANTS_COLOUR_STYLE.colour.dark,
        'markeredgewidth':
        CONSTANTS_COLOUR_STYLE.geometry.short * 0.75,
        'markersize': (CONSTANTS_COLOUR_STYLE.geometry.short * 6 +
                       CONSTANTS_COLOUR_STYLE.geometry.short * 0.75),
        'cmfs':
        cmfs,
        'illuminant':
        SDS_ILLUMINANTS[
            CONSTANTS_COLOUR_STYLE.colour.colourspace.whitepoint_name],
        'use_sd_colours':
        False,
        'normalise_sd_colours':
        False,
    } for sd in sds]

    if plot_kwargs is not None:
        update_settings_collection(plot_settings_collection, plot_kwargs,
                                   len(sds))

    for i, sd in enumerate(sds):
        plot_settings = plot_settings_collection[i]

        cmfs = first_item(filter_cmfs(plot_settings.pop('cmfs')).values())
        illuminant = first_item(
            filter_illuminants(plot_settings.pop('illuminant')).values())
        normalise_sd_colours = plot_settings.pop('normalise_sd_colours')
        use_sd_colours = plot_settings.pop('use_sd_colours')

        with domain_range_scale('1'):
            XYZ = sd_to_XYZ(sd, cmfs, illuminant)

        if use_sd_colours:
            if normalise_sd_colours:
                XYZ /= XYZ[..., 1]

            plot_settings['color'] = np.clip(XYZ_to_plotting_colourspace(XYZ),
                                             0, 1)

        ij = XYZ_to_ij(XYZ)

        axes.plot(ij[0], ij[1], **plot_settings)

        if (sd.name is not None
                and annotate_settings_collection[i]['annotate']):
            annotate_settings = annotate_settings_collection[i]
            annotate_settings.pop('annotate')

            axes.annotate(sd.name, xy=ij, **annotate_settings)

    settings.update({'standalone': True, 'bounding_box': bounding_box})
    settings.update(kwargs)

    return render(**settings)
Пример #8
0
def log_decoding_SLog3(y,
                       bit_depth=10,
                       in_normalised_code_value=True,
                       out_reflection=True,
                       **kwargs):
    """
    Defines the *Sony S-Log3* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    y : numeric or array_like
        Non-linear *Sony S-Log3* data :math:`y`.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the non-linear *Sony S-Log3* data :math:`y` is encoded as
        normalised code values.
    out_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Reflection or :math:`IRE / 100` input light level :math:`x` to a
        camera.

    Notes
    -----

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

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

    References
    ----------
    :cite:`SonyCorporationd`

    Examples
    --------
    >>> log_decoding_SLog3(0.410557184750733)  # doctest: +ELLIPSIS
    0.1...
    """

    in_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
        }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    y = to_domain_1(y)

    y = y if in_normalised_code_value else full_to_legal(y, bit_depth)

    x = np.where(
        y >= 171.2102946929 / 1023,
        ((10**((y * 1023 - 420) / 261.5)) * (0.18 + 0.01) - 0.01),
        (y * 1023 - 95) * 0.01125000 / (171.2102946929 - 95),
    )

    if not out_reflection:
        x = x / 0.9

    return as_float(from_range_1(x))
Пример #9
0
def CCT_to_xy_Hernandez1999(CCT, optimisation_kwargs=None, **kwargs):
    """
    Returns the *CIE xy* chromaticity coordinates from given correlated colour
    temperature :math:`T_{cp}` using *Hernandez-Andres et al. (1999)* method.

    Parameters
    ----------
    CCT : numeric or array_like
        Correlated colour temperature :math:`T_{cp}`.
    optimisation_kwargs : dict_like, optional
        Parameters for :func:`scipy.optimize.minimize` definition.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        *CIE xy* chromaticity coordinates.

    Warnings
    --------
    *Hernandez-Andres et al. (1999)* method for computing *CIE xy* chromaticity
    coordinates from given correlated colour temperature is not a bijective
    function and might produce unexpected results. It is given for consistency
    with other correlated colour temperature computation methods but should be
    avoided for practical applications. The current implementation relies on
    optimization using :func:`scipy.optimize.minimize` definition and thus has
    reduced precision and poor performance.

    References
    ----------
    :cite:`Hernandez-Andres1999a`

    Examples
    --------
    >>> CCT_to_xy_Hernandez1999(6500.7420431786531)  # doctest: +ELLIPSIS
    array([ 0.3127...,  0.329...])
    """

    optimisation_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed':
            [['optimisation_parameters', 'optimisation_kwargs']],
        }, **kwargs).get('optimisation_kwargs', optimisation_kwargs)

    usage_warning('"Hernandez-Andres et al. (1999)" method for computing '
                  '"CIE xy" chromaticity coordinates from given correlated '
                  'colour temperature is not a bijective function and and'
                  'might produce unexpected results. It is given for '
                  'consistency with other correlated colour temperature '
                  'computation methods but should be avoided for practical '
                  'applications.')

    CCT = as_float_array(CCT)
    shape = list(CCT.shape)
    CCT = np.atleast_1d(CCT.reshape([-1, 1]))

    def objective_function(xy, CCT):
        """
        Objective function.
        """

        objective = np.linalg.norm(xy_to_CCT_Hernandez1999(xy) - CCT)

        return objective

    optimisation_settings = {
        'method': 'Nelder-Mead',
        'options': {
            'fatol': 1e-10,
        },
    }
    if optimisation_kwargs is not None:
        optimisation_settings.update(optimisation_kwargs)

    CCT = as_float_array([
        minimize(
            objective_function,
            x0=CCS_ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'],
            args=(CCT_i, ),
            **optimisation_settings).x for CCT_i in CCT
    ])

    return as_numeric(CCT.reshape(shape + [2]))
Пример #10
0
def log_decoding_SLog(y,
                      bit_depth=10,
                      in_normalised_code_value=True,
                      out_reflection=True,
                      **kwargs):
    """
    Defines the *Sony S-Log* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    y : numeric or array_like
        Non-linear *Sony S-Log* data :math:`y`.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the non-linear *Sony S-Log* data :math:`y` is encoded as
        normalised code values.
    out_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Reflection or :math:`IRE / 100` input light level :math:`x` to a
        camera.

    Notes
    -----

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

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

    References
    ----------
    :cite:`SonyCorporation2012a`

    Examples
    --------
    >>> log_decoding_SLog(0.384970815928670)  # doctest: +ELLIPSIS
    0.1...
    """

    in_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
        }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    y = to_domain_1(y)

    x = legal_to_full(y, bit_depth) if in_normalised_code_value else y

    with domain_range_scale('ignore'):
        x = np.where(
            y >= log_encoding_SLog(0.0, bit_depth, in_normalised_code_value),
            10**((x - 0.616596 - 0.03) / 0.432699) - 0.037584,
            (x - 0.030001222851889303) / 5.0,
        )

    if out_reflection:
        x = x * 0.9

    return as_float(from_range_1(x))
Пример #11
0
def log_decoding_SLog2(y,
                       bit_depth=10,
                       in_normalised_code_value=True,
                       out_reflection=True,
                       **kwargs):
    """
    Defines the *Sony S-Log2* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    y : numeric or array_like
        Non-linear *Sony S-Log2* data :math:`y`.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the non-linear *Sony S-Log2* data :math:`y` is encoded as
        normalised code values.
    out_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Reflection or :math:`IRE / 100` input light level :math:`x` to a
        camera.

    Notes
    -----

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

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

    References
    ----------
    :cite:`SonyCorporation2012a`

    Examples
    --------
    >>> log_decoding_SLog2(0.339532524633774)  # doctest: +ELLIPSIS
    0.1...
    """

    in_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
        }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    return 219 * log_decoding_SLog(y, bit_depth, in_normalised_code_value,
                                   out_reflection) / 155
Пример #12
0
def log_decoding_CanonLog(clog,
                          bit_depth=10,
                          in_normalised_code_value=True,
                          out_reflection=True,
                          **kwargs):
    """
    Defines the *Canon Log* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    clog : numeric or array_like
        *Canon Log* non-linear data.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the *Canon Log* non-linear data is encoded with normalised
        code values.
    out_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`x`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Thorpe2012a`

    Examples
    --------
    >>> log_decoding_CanonLog(34.338965172606912 / 100)  # doctest: +ELLIPSIS
    0.17999999...
    """

    in_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
        }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    clog = to_domain_1(clog)

    clog = (legal_to_full(clog, bit_depth)
            if in_normalised_code_value else clog)

    x = np.where(
        clog < 0.0730597,
        -(10**((0.0730597 - clog) / 0.529136) - 1) / 10.1596,
        (10**((clog - 0.0730597) / 0.529136) - 1) / 10.1596,
    )

    if out_reflection:
        x = x * 0.9

    return as_float(from_range_1(x))
Пример #13
0
def log_decoding_VLog(V_out,
                      bit_depth=10,
                      in_normalised_code_value=True,
                      out_reflection=True,
                      constants=VLOG_CONSTANTS,
                      **kwargs):
    """
    Defines the *Panasonic V-Log* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    V_out : numeric or array_like
        Non-linear data :math:`V_{out}`.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the non-linear *Panasonic V-Log* data :math:`V_{out}` is
        encoded as normalised code values.
    out_reflection : bool, optional
        Whether the light level :math`L_{in}` to a camera is reflection.
    constants : Structure, optional
        *Panasonic V-Log* constants.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Linear reflection data :math`L_{in}`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Panasonic2014a`

    Examples
    --------
    >>> log_decoding_VLog(0.423311448760136)  # doctest: +ELLIPSIS
    0.1799999...
    """

    in_normalised_code_value = handle_arguments_deprecation({
        'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
    }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    V_out = to_domain_1(V_out)

    V_out = (V_out
             if in_normalised_code_value else full_to_legal(V_out, bit_depth))

    cut2 = constants.cut2
    b = constants.b
    c = constants.c
    d = constants.d

    L_in = np.where(
        V_out < cut2,
        (V_out - 0.125) / 5.6,
        10 ** ((V_out - d) / c) - b,
    )

    if not out_reflection:
        L_in = L_in / 0.9

    return as_float(from_range_1(L_in))
Пример #14
0
def log_decoding(value, function='Cineon', **kwargs):
    """
    Decodes :math:`R'G'B'` video component signal value to linear-light values
    using given *log* function.

    Parameters
    ----------
    value : numeric or array_like
        Value.
    function : unicode, optional
        **{'ACEScc', 'ACEScct', 'ACESproxy', 'ALEXA Log C', 'Canon Log 2',
        'Canon Log 3', 'Canon Log', 'Cineon', 'D-Log', 'ERIMM RGB', 'F-Log',
        'Filmic Pro 6', 'Log2', 'Log3G10', 'Log3G12', 'Panalog', 'PLog',
        'Protune', 'REDLog', 'REDLogFilm', 'S-Log', 'S-Log2', 'S-Log3',
        'T-Log', 'V-Log', 'ViperLog'}**,
        Computation function.

    Other Parameters
    ----------------
    EI : int,  optional
        {:func:`colour.models.log_decoding_ALEXALogC`},
        Ei.
    E_clip : numeric, optional
        {:func:`colour.models.log_decoding_ERIMMRGB`},
        Maximum exposure limit.
    E_min : numeric, optional
        {:func:`colour.models.log_decoding_ERIMMRGB`},
        Minimum exposure limit.
    I_max : numeric, optional
        {:func:`colour.models.log_decoding_ERIMMRGB`},
        Maximum code value: 255, 4095 and 650535 for respectively 8-bit,
        12-bit and 16-bit per channel.
    bit_depth : int, optional
        {:func:`colour.models.log_decoding_ACESproxy`,
        :func:`colour.models.log_decoding_SLog`,
        :func:`colour.models.log_decoding_SLog2`},
        **{8, 10, 12}**,
        Bit depth used for conversion, *ACESproxy* uses **{10, 12}**.
    black_offset : numeric or array_like
        {:func:`colour.models.log_decoding_Cineon`,
        :func:`colour.models.log_decoding_Panalog`,
        :func:`colour.models.log_decoding_REDLog`,
        :func:`colour.models.log_decoding_REDLogFilm`},
        Black offset.
    density_per_code_value : numeric or array_like
        {:func:`colour.models.log_decoding_PivotedLog`},
        Density per code value.
    firmware : unicode, optional
        {:func:`colour.models.log_decoding_ALEXALogC`},
        **{'SUP 3.x', 'SUP 2.x'}**,
        Alexa firmware version.
    in_normalised_code_value : bool, optional
        {:func:`colour.models.log_decoding_SLog`,
        :func:`colour.models.log_decoding_SLog2`,
        :func:`colour.models.log_decoding_SLog3`},
        Whether the non-linear *Sony S-Log*, *Sony S-Log2* or *Sony S-Log3*
        data :math:`y` is encoded as normalised code values.
    linear_reference : numeric or array_like
        {:func:`colour.models.log_decoding_PivotedLog`},
        Linear reference.
    log_reference : numeric or array_like
        {:func:`colour.models.log_decoding_PivotedLog`},
        Log reference.
    method : unicode, optional
        {:func:`colour.models.log_decoding_Log3G10`},
        Whether to use the *Log3G10* *v1* or *v2* log encoding curve.
    negative_gamma : numeric or array_like
        {:func:`colour.models.log_decoding_PivotedLog`},
        Negative gamma.
    out_reflection : bool, optional
        {:func:`colour.models.log_decoding_SLog`,
        :func:`colour.models.log_decoding_SLog2`},
        Whether the light level :math:`x` to a camera is reflection.
    method : unicode, optional
        {:func:`colour.models.log_decoding_ALEXALogC`},
        **{'Linear Scene Exposure Factor', 'Normalised Sensor Signal'}**,
        Conversion method.

    Returns
    -------
    numeric or ndarray
        *Log* value.

    Examples
    --------
    >>> log_decoding(0.457319613085418)  # doctest: +ELLIPSIS
    0.1...
    >>> log_decoding(0.413588402492442, function='ACEScc')
    ... # doctest: +ELLIPSIS
    0.1...
    >>> log_decoding(0.391006842619746, function='PLog', log_reference=400)
    ... # doctest: +ELLIPSIS
    0.1...
    >>> log_decoding(0.376512722254600, function='S-Log')
    ... # doctest: +ELLIPSIS
    0.1...
    """

    function = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['curve', 'function']],
        }, **kwargs).get('function', function)

    function = LOG_DECODINGS[function]

    return function(value, **filter_kwargs(function, **kwargs))
Пример #15
0
def log_encoding_Log3G10(x, method='v2', **kwargs):
    """
    Defines the *Log3G10* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.
    method : unicode, optional
        **{'v1', 'v2'}**,
        Computation method.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`y`.

    Notes
    -----

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

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

    -   The *Log3G10* *v1* log encoding curve is the one used in
        *REDCINE-X Beta 42*. *Resolve 12.5.2* also uses the *v1* curve. *RED*
        is planning to use the *Log3G10* *v2* log encoding curve in the release
        version of the *RED SDK*.
    -   The intent of the *Log3G10* *v1* log encoding curve is that zero maps
        to zero, 0.18 maps to 1/3, and 10 stops above 0.18 maps to 1.0.
        The name indicates this in a similar way to the naming conventions of
        *Sony HyperGamma* curves.

        The constants used in the functions do not in fact quite hit these
        values, but rather than use corrected constants, the functions here
        use the official *RED* values, in order to match the output of the
        *RED SDK*.

        For those interested, solving for constants which exactly hit 1/3
        and 1.0 yields the following values::

            B = 25 * (np.sqrt(4093.0) - 3) / 9
            A = 1 / np.log10(B * 184.32 + 1)

        where the function takes the form::

            Log3G10(x) = A * np.log10(B * x + 1)

        Similarly for *Log3G12*, the values which hit exactly 1/3 and 1.0
        are::

            B = 25 * (np.sqrt(16381.0) - 3) / 9
            A = 1 / np.log10(B * 737.28 + 1)

    References
    ----------
    :cite:`Nattress2016a`

    Examples
    --------
    >>> log_encoding_Log3G10(0.0)  # doctest: +ELLIPSIS
    0.0915514...
    >>> log_encoding_Log3G10(0.18, method='v1')  # doctest: +ELLIPSIS
    0.3333336...
    """

    method = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['legacy_curve', 'method']],
        }, **kwargs).get('method', method)
    method = {True: 'v1', False: 'v2'}.get(method, method)

    return LOG3G10_ENCODING_METHODS[method](x)
Пример #16
0
def log_encoding_CanonLog(x,
                          bit_depth=10,
                          out_normalised_code_value=True,
                          in_reflection=True,
                          **kwargs):
    """
    Defines the *Canon Log* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the *Canon Log* non-linear data is encoded as normalised code
        values.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        *Canon Log* non-linear data.

    References
    ----------
    :cite:`Thorpe2012a`

    Notes
    -----

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

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

    Examples
    --------
    >>> log_encoding_CanonLog(0.18) * 100  # doctest: +ELLIPSIS
    34.3389651...

    The values of *Table 2 Canon-Log Code Values* table in :cite:`Thorpe2012a`
    are obtained as follows:

    >>> x = np.array([0, 2, 18, 90, 720]) / 100
    >>> np.around(log_encoding_CanonLog(x) * (2 ** 10 - 1)).astype(np.int)
    array([ 128,  169,  351,  614, 1016])
    >>> np.around(log_encoding_CanonLog(x, 10, False) * 100, 1)
    array([   7.3,   12. ,   32.8,   62.7,  108.7])
    """

    out_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
        }, **kwargs).get('out_normalised_code_value',
                         out_normalised_code_value)

    x = to_domain_1(x)

    if in_reflection:
        x = x / 0.9

    with domain_range_scale('ignore'):
        clog = np.where(
            x < log_decoding_CanonLog(0.0730597, bit_depth, False),
            -(0.529136 * (np.log10(-x * 10.1596 + 1)) - 0.0730597),
            0.529136 * np.log10(10.1596 * x + 1) + 0.0730597,
        )

    clog = (full_to_legal(clog, bit_depth)
            if out_normalised_code_value else clog)

    return as_float(from_range_1(clog))
Пример #17
0
def log_decoding_CanonLog3(clog3,
                           bit_depth=10,
                           in_normalised_code_value=True,
                           out_reflection=True,
                           **kwargs):
    """
    Defines the *Canon Log 3* log decoding curve / electro-optical transfer
    function.

    Parameters
    ----------
    clog3 : numeric or array_like
        *Canon Log 3* non-linear data.
    bit_depth : int, optional
        Bit depth used for conversion.
    in_normalised_code_value : bool, optional
        Whether the *Canon Log 3* non-linear data is encoded with normalised
        code values.
    out_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Linear data :math:`x`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Canona`

    Examples
    --------
    >>> log_decoding_CanonLog3(34.338936938868677 / 100)  # doctest: +ELLIPSIS
    0.1800000...
    """

    in_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['in_legal', 'in_normalised_code_value']],
        }, **kwargs).get('in_normalised_code_value', in_normalised_code_value)

    clog3 = to_domain_1(clog3)

    clog3 = (legal_to_full(clog3, bit_depth)
             if in_normalised_code_value else clog3)

    x = np.select(
        (clog3 < 0.04076162, clog3 <= 0.105357102, clog3 > 0.105357102),
        (-(10**((0.07623209 - clog3) / 0.42889912) - 1) / 14.98325,
         (clog3 - 0.073059361) / 2.3069815,
         (10**((clog3 - 0.069886632) / 0.42889912) - 1) / 14.98325))

    if out_reflection:
        x = x * 0.9

    return as_float(from_range_1(x))
Пример #18
0
def log_encoding_CanonLog3(x,
                           bit_depth=10,
                           out_normalised_code_value=True,
                           in_reflection=True,
                           **kwargs):
    """
    Defines the *Canon Log 3* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the *Canon Log 3* non-linear data is encoded as normalised code
        values.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        *Canon Log 3* non-linear data.

    Notes
    -----
    -   Introspection of the grafting points by Shaw, N. (2018) shows that the
        *Canon Log 3* IDT was likely derived from its encoding curve as the
        later is grafted at *+/-0.014*::

            >>> clog3 = 0.04076162
            >>> (clog3 - 0.073059361) / 2.3069815
            -0.014000000000000002
            >>> clog3 = 0.105357102
            >>> (clog3 - 0.073059361) / 2.3069815
            0.013999999999999997

    Notes
    -----

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

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

    References
    ----------
    :cite:`Canona`

    Examples
    --------
    >>> log_encoding_CanonLog3(0.18) * 100  # doctest: +ELLIPSIS
    34.3389369...
    """

    out_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
        }, **kwargs).get('out_normalised_code_value',
                         out_normalised_code_value)

    x = to_domain_1(x)

    if in_reflection:
        x = x / 0.9

    with domain_range_scale('ignore'):
        clog3 = np.select(
            (x < log_decoding_CanonLog3(0.04076162, bit_depth, False, False),
             x <= log_decoding_CanonLog3(0.105357102, bit_depth, False, False),
             x > log_decoding_CanonLog3(0.105357102, bit_depth, False, False)),
            (-0.42889912 * np.log10(-x * 14.98325 + 1) + 0.07623209,
             2.3069815 * x + 0.073059361,
             0.42889912 * np.log10(x * 14.98325 + 1) + 0.069886632))

    clog3 = (full_to_legal(clog3, bit_depth)
             if out_normalised_code_value else clog3)

    return as_float(from_range_1(clog3))
Пример #19
0
def xy_to_CCT_Kang2002(xy, optimisation_kwargs=None, **kwargs):
    """
    Returns the correlated colour temperature :math:`T_{cp}` from given
    *CIE xy* chromaticity coordinates using *Kang et al. (2002)* method.

    Parameters
    ----------
    xy : array_like
        *CIE xy* chromaticity coordinates.
    optimisation_kwargs : dict_like, optional
        Parameters for :func:`scipy.optimize.minimize` definition.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        Correlated colour temperature :math:`T_{cp}`.

    Warnings
    --------
    *Kang et al. (2002)* does not give an analytical inverse transformation to
    compute the correlated colour temperature :math:`T_{cp}` from given
    *CIE xy* chromaticity coordinates, the current implementation relies on
    optimization using :func:`scipy.optimize.minimize` definition and thus has
    reduced precision and poor performance.

    References
    ----------
    :cite:`Kang2002a`

    Examples
    --------
    >>> xy_to_CCT_Kang2002(np.array([0.31342600, 0.32359597]))
    ... # doctest: +ELLIPSIS
    6504.3893128...
    """

    optimisation_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed':
            [['optimisation_parameters', 'optimisation_kwargs']],
        }, **kwargs).get('optimisation_kwargs', optimisation_kwargs)

    xy = as_float_array(xy)
    shape = xy.shape
    xy = np.atleast_1d(xy.reshape([-1, 2]))

    def objective_function(CCT, xy):
        """
        Objective function.
        """

        objective = np.linalg.norm(CCT_to_xy_Kang2002(CCT) - xy)

        return objective

    optimisation_settings = {
        'method': 'Nelder-Mead',
        'options': {
            'fatol': 1e-10,
        },
    }
    if optimisation_kwargs is not None:
        optimisation_settings.update(optimisation_kwargs)

    CCT = as_float_array([
        minimize(objective_function,
                 x0=6500,
                 args=(xy_i, ),
                 **optimisation_settings).x for xy_i in xy
    ])

    return as_numeric(CCT.reshape(shape[:-1]))
Пример #20
0
def log_encoding_VLog(L_in,
                      bit_depth=10,
                      out_normalised_code_value=True,
                      in_reflection=True,
                      constants=VLOG_CONSTANTS,
                      **kwargs):
    """
    Defines the *Panasonic V-Log* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    L_in : numeric or array_like
        Linear reflection data :math`L_{in}`.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the non-linear *Panasonic V-Log* data :math:`V_{out}` is
        encoded as normalised code values.
    in_reflection : bool, optional
        Whether the light level :math`L_{in}` to a camera is reflection.
    constants : Structure, optional
        *Panasonic V-Log* constants.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Non-linear data :math:`V_{out}`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Panasonic2014a`

    Examples
    --------
    >>> log_encoding_VLog(0.18)  # doctest: +ELLIPSIS
    0.4233114...

    The values of *Fig.2.2 V-Log Code Value* table in :cite:`Panasonic2014a`
    are obtained as follows:

    >>> L_in = np.array([0, 18, 90]) / 100
    >>> np.around(log_encoding_VLog(L_in, 10, False) * 100).astype(np.int)
    array([ 7, 42, 61])
    >>> np.around(log_encoding_VLog(L_in) * (2 ** 10 - 1)).astype(np.int)
    array([128, 433, 602])
    >>> np.around(log_encoding_VLog(L_in) * (2 ** 12 - 1)).astype(np.int)
    array([ 512, 1733, 2409])

    Note that some values in the last column values of
    *Fig.2.2 V-Log Code Value* table in :cite:`Panasonic2014a` are different
    by a code: [512, 1732, 2408].
    """

    out_normalised_code_value = handle_arguments_deprecation({
        'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
    }, **kwargs).get('out_normalised_code_value', out_normalised_code_value)

    L_in = to_domain_1(L_in)

    if not in_reflection:
        L_in = L_in * 0.9

    cut1 = constants.cut1
    b = constants.b
    c = constants.c
    d = constants.d

    V_out = np.where(
        L_in < cut1,
        5.6 * L_in + 0.125,
        c * np.log10(L_in + b) + d,
    )

    V_out = (V_out
             if out_normalised_code_value else legal_to_full(V_out, bit_depth))

    return as_float(from_range_1(V_out))
Пример #21
0
def OSA_UCS_to_XYZ(Ljg, optimisation_kwargs=None, **kwargs):
    """
    Converts from *OSA UCS* colourspace to *CIE XYZ* tristimulus values under
    the *CIE 1964 10 Degree Standard Observer*.

    Parameters
    ----------
    Ljg : array_like
        *OSA UCS* :math:`Ljg` lightness, jaune (yellowness), and greenness.
    optimisation_kwargs : dict_like, optional
        Parameters for :func:`scipy.optimize.fmin` definition.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        *CIE XYZ* tristimulus values under the
        *CIE 1964 10 Degree Standard Observer*.

    Warnings
    --------
    There is no analytical inverse transformation from *OSA UCS* to :math:`Ljg`
    lightness, jaune (yellowness), and greenness to *CIE XYZ* tristimulus
    values, the current implementation relies on optimization using
    :func:`scipy.optimize.fmin` definition and thus has reduced precision and
    poor performance.

    Notes
    -----

    +------------+-----------------------+--------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**      |
    +============+=======================+====================+
    | ``Ljg``    | ``L`` : [-100, 100]   | ``L`` : [-1, 1]    |
    |            |                       |                    |
    |            | ``j`` : [-100, 100]   | ``j`` : [-1, 1]    |
    |            |                       |                    |
    |            | ``g`` : [-100, 100]   | ``g`` : [-1, 1]    |
    +------------+-----------------------+--------------------+

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

    -   *OSA UCS* uses the *CIE 1964 10 Degree Standard Observer*.

    References
    ----------
    :cite:`Cao2013`, :cite:`Moroney2003`

    Examples
    --------
    >>> import numpy as np
    >>> Ljg = np.array([-3.00499790, 2.99713697, -9.66784231])
    >>> OSA_UCS_to_XYZ(Ljg)  # doctest: +ELLIPSIS
    array([ 20.6540240...,  12.1972369...,   5.1369372...])
    """

    optimisation_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed':
            [['optimisation_parameters', 'optimisation_kwargs']],
        }, **kwargs).get('optimisation_kwargs', optimisation_kwargs)

    Ljg = to_domain_100(Ljg)
    shape = Ljg.shape
    Ljg = np.atleast_1d(Ljg.reshape([-1, 3]))

    optimisation_settings = {'disp': False}
    if optimisation_kwargs is not None:
        optimisation_settings.update(optimisation_kwargs)

    def error_function(XYZ, Ljg):
        """
        Error function.
        """

        # Error must be computed in "reference" domain and range.
        with domain_range_scale('ignore'):
            error = np.linalg.norm(XYZ_to_OSA_UCS(XYZ) - Ljg)

        return error

    x_0 = np.array([30, 30, 30])
    XYZ = as_float_array([
        fmin(error_function, x_0, (Ljg_i, ), **optimisation_settings)
        for Ljg_i in Ljg
    ])

    return from_range_100(XYZ.reshape(shape))
Пример #22
0
def XYZ_to_sRGB(
        XYZ,
        illuminant=CCS_ILLUMINANTS['CIE 1931 2 Degree Standard Observer']
    ['D65'],
        chromatic_adaptation_transform='CAT02',
        apply_cctf_encoding=True,
        **kwargs):
    """
    Converts from *CIE XYZ* tristimulus values to *sRGB* colourspace.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values.
    illuminant : array_like, optional
        Source illuminant chromaticity coordinates.
    chromatic_adaptation_transform : unicode, optional
        **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp',
        'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02 Brill 2008',
        'Bianco 2010', 'Bianco PC 2010'}**,
        *Chromatic adaptation* transform.
    apply_cctf_encoding : bool, optional
        Apply *sRGB* encoding colour component transfer function /
        opto-electronic transfer function.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        *sRGB* colour array.

    Notes
    -----

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

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

    Examples
    --------
    >>> import numpy as np
    >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
    >>> XYZ_to_sRGB(XYZ)  # doctest: +ELLIPSIS
    array([ 0.7057393...,  0.1924826...,  0.2235416...])
    """

    apply_cctf_encoding = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['apply_encoding_cctf', 'apply_cctf_encoding']
                                ],
        }, **kwargs).get('apply_cctf_encoding', apply_cctf_encoding)

    sRGB = RGB_COLOURSPACES['sRGB']

    return XYZ_to_RGB(
        XYZ,
        illuminant,
        sRGB.whitepoint,
        sRGB.matrix_XYZ_to_RGB,
        chromatic_adaptation_transform,
        sRGB.cctf_encoding if apply_cctf_encoding else None,
    )
Пример #23
0
def log_encoding_SLog2(x,
                       bit_depth=10,
                       out_normalised_code_value=True,
                       in_reflection=True,
                       **kwargs):
    """
    Defines the *Sony S-Log2* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Reflection or :math:`IRE / 100` input light level :math:`x` to a
        camera.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the non-linear *Sony S-Log2* data :math:`y` is encoded as
        normalised code values.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Non-linear *Sony S-Log2* data :math:`y`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`SonyCorporation2012a`

    Examples
    --------
    >>> log_encoding_SLog2(0.18)  # doctest: +ELLIPSIS
    0.3395325...

    The values of *IRE and CV of S-Log2 @ISO800* table in
    :cite:`SonyCorporation2012a` are obtained as follows:

    >>> x = np.array([0, 18, 90]) / 100
    >>> np.around(log_encoding_SLog2(x, 10, False) * 100).astype(np.int)
    array([ 3, 32, 59])
    >>> np.around(log_encoding_SLog2(x) * (2 ** 10 - 1)).astype(np.int)
    array([ 90, 347, 582])
    """

    out_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
        }, **kwargs).get('out_normalised_code_value',
                         out_normalised_code_value)

    return log_encoding_SLog(x * 155 / 219, bit_depth,
                             out_normalised_code_value, in_reflection)
Пример #24
0
def plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS(
        illuminants,
        chromaticity_diagram_callable_CIE1960UCS=(
            plot_chromaticity_diagram_CIE1960UCS),
        planckian_locus_callable_CIE1960UCS=plot_planckian_locus_CIE1960UCS,
        annotate_kwargs=None,
        plot_kwargs=None,
        **kwargs):
    """
    Plots the *Planckian Locus* and given illuminants in
    *CIE 1960 UCS Chromaticity Diagram*.

    Parameters
    ----------
    illuminants : unicode or object or array_like
        Illuminants to plot. ``illuminants`` elements can be of any
        type or form supported by the
        :func:`colour.plotting.filter_passthrough` definition.
    chromaticity_diagram_callable_CIE1960UCS : callable, optional
        Callable responsible for drawing the
        *CIE 1960 UCS Chromaticity Diagram*.
    planckian_locus_callable_CIE1960UCS : callable, optional
        Callable responsible for drawing the *Planckian Locus* according to
        *CIE 1960 UCS* method.
    annotate_kwargs : dict or array_like, optional
        Keyword arguments for the :func:`plt.annotate` definition, used to
        annotate the resulting chromaticity coordinates with their respective
        illuminant names. ``annotate_kwargs`` can be either a single dictionary
        applied to all the arrows with same settings or a sequence of
        dictionaries with different settings for each illuminant.
        The following special keyword arguments can also be used:

        -   *annotate* : bool, whether to annotate the illuminants.
    plot_kwargs : dict or array_like, optional
        Keyword arguments for the :func:`plt.plot` definition, used to control
        the style of the plotted illuminants. ``plot_kwargs`` can be either a
        single dictionary applied to all the plotted illuminants with same
        settings or a sequence of dictionaries with different settings for each
        plotted illuminant.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.diagrams.plot_chromaticity_diagram`,
        :func:`colour.plotting.temperature.plot_planckian_locus`,
        :func:`colour.plotting.temperature.\
plot_planckian_locus_in_chromaticity_diagram`,
        :func:`colour.plotting.render`},
        Please refer to the documentation of the previously listed definitions.
        Also handles keywords arguments for deprecation management.

    Returns
    -------
    tuple
        Current figure and axes.

    Examples
    --------
    >>> plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS(
    ...     ['A', 'C', 'E'])  # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_\
Plot_Planckian_Locus_In_Chromaticity_Diagram_CIE1960UCS.png
        :align: center
        :alt: plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS
    """

    annotate_kwargs = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['annotate_parameters', 'annotate_kwargs']],
        }, **kwargs).get('annotate_kwargs', annotate_kwargs)

    settings = dict(kwargs)
    settings.update({'method': 'CIE 1960 UCS'})

    return plot_planckian_locus_in_chromaticity_diagram(
        illuminants,
        chromaticity_diagram_callable_CIE1960UCS,
        planckian_locus_callable_CIE1960UCS,
        annotate_kwargs=annotate_kwargs,
        plot_kwargs=plot_kwargs,
        **settings)
Пример #25
0
def log_encoding_SLog3(x,
                       bit_depth=10,
                       out_normalised_code_value=True,
                       in_reflection=True,
                       **kwargs):
    """
    Defines the *Sony S-Log3* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Reflection or :math:`IRE / 100` input light level :math:`x` to a
        camera.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the non-linear *Sony S-Log3* data :math:`y` is encoded as
        normalised code values.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Non-linear *Sony S-Log3* data :math:`y`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`SonyCorporationd`

    Examples
    --------
    >>> log_encoding_SLog3(0.18)  # doctest: +ELLIPSIS
    0.4105571...

    The values of *S-Log3 10bit code values (18%, 90%)* table in
    :cite:`SonyCorporationd` are obtained as follows:

    >>> x = np.array([0, 18, 90]) / 100
    >>> np.around(log_encoding_SLog3(x, 10, False) * 100).astype(np.int)
    array([ 4, 41, 61])
    >>> np.around(log_encoding_SLog3(x) * (2 ** 10 - 1)).astype(np.int)
    array([ 95, 420, 598])
    """

    out_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
        }, **kwargs).get('out_normalised_code_value',
                         out_normalised_code_value)

    x = to_domain_1(x)

    if not in_reflection:
        x = x * 0.9

    y = np.where(
        x >= 0.01125000,
        (420 + np.log10((x + 0.01) / (0.18 + 0.01)) * 261.5) / 1023,
        (x * (171.2102946929 - 95) / 0.01125000 + 95) / 1023,
    )

    y = y if out_normalised_code_value else legal_to_full(y, bit_depth)

    return as_float(from_range_1(y))
Пример #26
0
def RGB_to_RGB(RGB,
               input_colourspace,
               output_colourspace,
               chromatic_adaptation_transform='CAT02',
               apply_cctf_decoding=False,
               apply_cctf_encoding=False,
               **kwargs):
    """
    Converts given *RGB* colourspace array from given input *RGB* colourspace
    to output *RGB* colourspace using given *chromatic adaptation* method.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    input_colourspace : RGB_Colourspace
        *RGB* input colourspace.
    output_colourspace : RGB_Colourspace
        *RGB* output colourspace.
    chromatic_adaptation_transform : unicode, optional
        **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp',
        'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco',
        'Bianco PC', None}**,
        *Chromatic adaptation* transform, if *None* no chromatic adaptation is
        performed.
    apply_cctf_decoding : bool, optional
        Apply input colourspace decoding colour component transfer function /
        electro-optical transfer function.
    apply_cctf_encoding : bool, optional
        Apply output colourspace encoding colour component transfer function /
        opto-electronic transfer function.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for the colour component transfer functions.

    Returns
    -------
    ndarray
        *RGB* colourspace array.

    Notes
    -----

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

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

    Examples
    --------
    >>> from colour.models import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE
    >>> RGB = np.array([0.45595571, 0.03039702, 0.04087245])
    >>> RGB_to_RGB(RGB, sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE)
    ... # doctest: +ELLIPSIS
    array([ 0.2568891...,  0.0721446...,  0.0465553...])
    """

    apply_cctf_decoding = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['apply_decoding_cctf', 'apply_cctf_decoding']
                                ],
        }, **kwargs).get('apply_cctf_decoding', apply_cctf_decoding)

    apply_cctf_encoding = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['apply_encoding_cctf', 'apply_cctf_encoding']
                                ],
        }, **kwargs).get('apply_cctf_encoding', apply_cctf_encoding)

    RGB = to_domain_1(RGB)

    if apply_cctf_decoding:
        with domain_range_scale('ignore'):
            RGB = input_colourspace.cctf_decoding(
                RGB, **filter_kwargs(input_colourspace.cctf_decoding,
                                     **kwargs))

    M = RGB_to_RGB_matrix(input_colourspace, output_colourspace,
                          chromatic_adaptation_transform)

    RGB = dot_vector(M, RGB)

    if apply_cctf_encoding:
        with domain_range_scale('ignore'):
            RGB = output_colourspace.cctf_encoding(
                RGB, **filter_kwargs(output_colourspace.cctf_encoding,
                                     **kwargs))

    return from_range_1(RGB)
Пример #27
0
def log_encoding_SLog(x,
                      bit_depth=10,
                      out_normalised_code_value=True,
                      in_reflection=True,
                      **kwargs):
    """
    Defines the *Sony S-Log* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Reflection or :math:`IRE / 100` input light level :math:`x` to a
        camera.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the non-linear *Sony S-Log* data :math:`y` is encoded as
        normalised code values.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        Non-linear *Sony S-Log* data :math:`y`.

    Notes
    -----

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

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

    References
    ----------
    :cite:`SonyCorporation2012a`

    Examples
    --------
    >>> log_encoding_SLog(0.18)  # doctest: +ELLIPSIS
    0.3849708...

    The values of *IRE and CV of S-Log2 @ISO800* table in
    :cite:`SonyCorporation2012a` are obtained as follows:

    >>> x = np.array([0, 18, 90]) / 100
    >>> np.around(log_encoding_SLog(x, 10, False) * 100).astype(np.int)
    array([ 3, 38, 65])
    >>> np.around(log_encoding_SLog(x) * (2 ** 10 - 1)).astype(np.int)
    array([ 90, 394, 636])
    """

    out_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
        }, **kwargs).get('out_normalised_code_value',
                         out_normalised_code_value)

    x = to_domain_1(x)

    if in_reflection:
        x = x / 0.9

    y = np.where(
        x >= 0,
        ((0.432699 * np.log10(x + 0.037584) + 0.616596) + 0.03),
        x * 5 + 0.030001222851889303,
    )

    y = full_to_legal(y, bit_depth) if out_normalised_code_value else y

    return as_float(from_range_1(y))
Пример #28
0
def XYZ_to_RGB(XYZ,
               illuminant_XYZ,
               illuminant_RGB,
               XYZ_to_RGB_matrix,
               chromatic_adaptation_transform='CAT02',
               cctf_encoding=None,
               **kwargs):
    """
    Converts from *CIE XYZ* tristimulus values to *RGB* colourspace array.

    Parameters
    ----------
    XYZ : array_like
        *CIE XYZ* tristimulus values.
    illuminant_XYZ : array_like
        *CIE XYZ* tristimulus values *illuminant* *CIE xy* chromaticity
        coordinates or *CIE xyY* colourspace array.
    illuminant_RGB : array_like
        *RGB* colourspace *illuminant* *CIE xy* chromaticity coordinates or
        *CIE xyY* colourspace array.
    XYZ_to_RGB_matrix : array_like
        *Normalised primary matrix*.
    chromatic_adaptation_transform : unicode, optional
        **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp',
        'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco',
        'Bianco PC', None}**,
        *Chromatic adaptation* transform, if *None* no chromatic adaptation is
        performed.
    cctf_encoding : object, optional
        Encoding colour component transfer function (Encoding CCTF) or
        opto-electronic transfer function (OETF / OECF).

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        *RGB* colourspace array.

    Notes
    -----

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

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

    Examples
    --------
    >>> XYZ = np.array([0.21638819, 0.12570000, 0.03847493])
    >>> illuminant_XYZ = np.array([0.34570, 0.35850])
    >>> illuminant_RGB = np.array([0.31270, 0.32900])
    >>> chromatic_adaptation_transform = 'Bradford'
    >>> XYZ_to_RGB_matrix = np.array(
    ...     [[3.24062548, -1.53720797, -0.49862860],
    ...      [-0.96893071, 1.87575606, 0.04151752],
    ...      [0.05571012, -0.20402105, 1.05699594]]
    ... )
    >>> XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix,
    ...            chromatic_adaptation_transform)  # doctest: +ELLIPSIS
    array([ 0.4559557...,  0.0303970...,  0.0408724...])
    """

    cctf_encoding = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['encoding_cctf', 'cctf_encoding']],
        }, **kwargs).get('cctf_encoding', cctf_encoding)

    XYZ = to_domain_1(XYZ)

    if chromatic_adaptation_transform is not None:
        M_CAT = chromatic_adaptation_matrix_VonKries(
            xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)),
            xyY_to_XYZ(xy_to_xyY(illuminant_RGB)),
            transform=chromatic_adaptation_transform)

        XYZ = dot_vector(M_CAT, XYZ)

    RGB = dot_vector(XYZ_to_RGB_matrix, XYZ)

    if cctf_encoding is not None:
        with domain_range_scale('ignore'):
            RGB = cctf_encoding(RGB)

    return from_range_1(RGB)
Пример #29
0
def RGB_to_XYZ(RGB,
               illuminant_RGB,
               illuminant_XYZ,
               RGB_to_XYZ_matrix,
               chromatic_adaptation_transform='CAT02',
               cctf_decoding=None,
               **kwargs):
    """
    Converts given *RGB* colourspace array to *CIE XYZ* tristimulus values.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    illuminant_RGB : array_like
        *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY*
        colourspace array.
    illuminant_XYZ : array_like
        *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or
        *CIE xyY* colourspace array.
    RGB_to_XYZ_matrix : array_like
        *Normalised primary matrix*.
    chromatic_adaptation_transform : unicode, optional
        **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp',
        'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco',
        'Bianco PC', None}**,
        *Chromatic adaptation* transform, if *None* no chromatic adaptation is
        performed.
    cctf_decoding : object, optional
        Decoding colour component transfer function (Decoding CCTF) or
        electro-optical transfer function (EOTF / EOCF).

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    ndarray
        *CIE XYZ* tristimulus values.

    Notes
    -----

    +--------------------+-----------------------+---------------+
    | **Domain**         | **Scale - Reference** | **Scale - 1** |
    +====================+=======================+===============+
    | ``RGB``            | [0, 1]                | [0, 1]        |
    +--------------------+-----------------------+---------------+
    | ``illuminant_XYZ`` | [0, 1]                | [0, 1]        |
    +--------------------+-----------------------+---------------+
    | ``illuminant_RGB`` | [0, 1]                | [0, 1]        |
    +--------------------+-----------------------+---------------+

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

    Examples
    --------
    >>> RGB = np.array([0.45595571, 0.03039702, 0.04087245])
    >>> illuminant_RGB = np.array([0.31270, 0.32900])
    >>> illuminant_XYZ = np.array([0.34570, 0.35850])
    >>> chromatic_adaptation_transform = 'Bradford'
    >>> RGB_to_XYZ_matrix = np.array(
    ...     [[0.41240000, 0.35760000, 0.18050000],
    ...      [0.21260000, 0.71520000, 0.07220000],
    ...      [0.01930000, 0.11920000, 0.95050000]]
    ... )
    >>> RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix,
    ...            chromatic_adaptation_transform)  # doctest: +ELLIPSIS
    array([ 0.2163881...,  0.1257    ,  0.0384749...])
    """

    cctf_decoding = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['decoding_cctf', 'cctf_decoding']],
        }, **kwargs).get('cctf_decoding', cctf_decoding)

    RGB = to_domain_1(RGB)

    if cctf_decoding is not None:
        with domain_range_scale('ignore'):
            RGB = cctf_decoding(RGB)

    XYZ = dot_vector(RGB_to_XYZ_matrix, RGB)

    if chromatic_adaptation_transform is not None:
        M_CAT = chromatic_adaptation_matrix_VonKries(
            xyY_to_XYZ(xy_to_xyY(illuminant_RGB)),
            xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)),
            transform=chromatic_adaptation_transform)

        XYZ = dot_vector(M_CAT, XYZ)

    return from_range_1(XYZ)
Пример #30
0
def log_encoding_CanonLog2(x,
                           bit_depth=10,
                           out_normalised_code_value=True,
                           in_reflection=True,
                           **kwargs):
    """
    Defines the *Canon Log 2* log encoding curve / opto-electronic transfer
    function.

    Parameters
    ----------
    x : numeric or array_like
        Linear data :math:`x`.
    bit_depth : int, optional
        Bit depth used for conversion.
    out_normalised_code_value : bool, optional
        Whether the *Canon Log 2* non-linear data is encoded as normalised
        code values.
    in_reflection : bool, optional
        Whether the light level :math:`x` to a camera is reflection.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        Keywords arguments for deprecation management.

    Returns
    -------
    numeric or ndarray
        *Canon Log 2* non-linear data.

    Notes
    -----

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

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

    References
    ----------
    :cite:`Canona`

    Examples
    --------
    >>> log_encoding_CanonLog2(0.18) * 100  # doctest: +ELLIPSIS
    39.8254694...
    """

    out_normalised_code_value = handle_arguments_deprecation(
        {
            'ArgumentRenamed': [['out_legal', 'out_normalised_code_value']],
        }, **kwargs).get('out_normalised_code_value',
                         out_normalised_code_value)

    x = to_domain_1(x)

    if in_reflection:
        x = x / 0.9

    with domain_range_scale('ignore'):
        clog2 = np.where(
            x < log_decoding_CanonLog2(0.035388128, bit_depth, False),
            -(0.281863093 * (np.log10(-x * 87.09937546 + 1)) - 0.035388128),
            0.281863093 * np.log10(x * 87.09937546 + 1) + 0.035388128,
        )

    clog2 = (full_to_legal(clog2, bit_depth)
             if out_normalised_code_value else clog2)

    return as_float(from_range_1(clog2))