colour.models.derivation — Colour 0.3.0 documentation

# Source code for colour.models.derivation

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    """
    RGB Colourspace Derivation
    ==========================

    Defines objects related to *RGB* colourspace derivation, essentially
    calculating the normalised primary matrix for given *RGB* colourspace primaries
    and whitepoint.

    See Also
    --------
    `RGB Colourspaces IPython Notebook
    <http://nbviewer.ipython.org/github/colour-science/colour-ipython/blob/master/notebooks/models/rgb.ipynb>`_  # noqa

    References
    ----------
    .. [1]  `RP 177-1993 SMPTE RECOMMENDED PRACTICE - Television Color Equations
            <http://car.france3.mars.free.fr/HD/INA-%2026%20jan%2006/SMPTE%20normes%20et%20confs/rp177.pdf>`_  # noqa
            (Last accessed 24 February 2014)
    """

    from __future__ import division, unicode_literals

    import numpy as np

    __author__ = 'Colour Developers'
    __copyright__ = 'Copyright (C) 2013 - 2014 - Colour Developers'
    __license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
    __maintainer__ = 'Colour Developers'
    __email__ = 'colour-science@googlegroups.com'
    __status__ = 'Production'

    __all__ = ['xy_to_z',
               'normalised_primary_matrix',
               'RGB_luminance_equation',
               'RGB_luminance']

    def xy_to_z(xy):
        """
        Returns the *z* coordinate using given *xy* chromaticity coordinates.

        Parameters
        ----------
        xy : array_like
            *xy* chromaticity coordinates.

        Returns
        -------
        numeric
            *z* coordinate.

        References
        ----------
        .. [2]  `RP 177-1993 SMPTE RECOMMENDED PRACTICE -
                Television Color Equations: 3.3.2
                <http://car.france3.mars.free.fr/HD/INA-%2026%20jan%2006/SMPTE%20normes%20et%20confs/rp177.pdf>`_  # noqa

        Examples
        --------
        >>> xy_to_z((0.25, 0.25))
        0.5
        """

        return 1 - xy[0] - xy[1]

    def normalised_primary_matrix(primaries, whitepoint):
        """
        Returns the *normalised primary matrix* using given *primaries* and
        *whitepoint* matrices.

        Parameters
        ----------
        primaries : array_like
            Primaries chromaticity coordinate matrix, (3, 2).
        whitepoint : array_like
            Illuminant / whitepoint chromaticity coordinates.

        Returns
        -------
        ndarray, (3, 3)
            Normalised primary matrix.

        References
        ----------
        .. [3]  `RP 177-1993 SMPTE RECOMMENDED PRACTICE -
                Television Color Equations: 3.3.2 - 3.3.6
                <http://car.france3.mars.free.fr/HD/INA-%2026%20jan%2006/SMPTE%20normes%20et%20confs/rp177.pdf>`_  # noqa

        Examples
        --------
        >>> pms = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700])
        >>> whitepoint = (0.32168, 0.33767)
        >>> normalised_primary_matrix(pms, whitepoint)  # doctest: +ELLIPSIS
        array([[  9.5255239...e-01,   0.0000000...e+00,   9.3678631...e-05],
               [  3.4396645...e-01,   7.2816609...e-01,  -7.2132546...e-02],
               [  0.0000000...e+00,   0.0000000...e+00,   1.0088251...e+00]])
        """

        # Add *z* coordinates to the primaries and transposing the matrix.
        primaries = primaries.reshape((3, 2))
        z = np.array([xy_to_z(np.ravel(primary)) for primary in primaries])
        primaries = np.hstack((primaries, z.reshape((3, 1))))

        primaries = np.transpose(primaries)

        whitepoint = np.array([
            whitepoint[0] / whitepoint[1],
            1,
            xy_to_z(whitepoint) / whitepoint[1]]).reshape((3, 1))

        coefficients = np.dot(np.linalg.inv(primaries), whitepoint)
        coefficients = np.diagflat(coefficients)

        npm = np.dot(primaries, coefficients)

        return npm

    def RGB_luminance_equation(primaries, whitepoint):
        """
        Returns the *luminance equation* from given *primaries* and *whitepoint*
        matrices.

        Parameters
        ----------
        primaries : array_like, (3, 2)
            Primaries chromaticity coordinate matrix.
        whitepoint : array_like
            Illuminant / whitepoint chromaticity coordinates.

        Returns
        -------
        unicode
            *Luminance* equation.

        References
        ----------
        .. [4]  `RP 177-1993 SMPTE RECOMMENDED PRACTICE -
                Television Color Equations: 3.3.8
                <http://car.france3.mars.free.fr/HD/INA-%2026%20jan%2006/SMPTE%20normes%20et%20confs/rp177.pdf>`_  # noqa

        Examples
        --------
        >>> pms = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700])
        >>> whitepoint = (0.32168, 0.33767)
        >>> # Doctests skip for Python 2.x compatibility.
        >>> RGB_luminance_equation(pms, whitepoint)  # doctest: +SKIP
        'Y = 0.3439664...(R) + 0.7281660...(G) + -0.0721325...(B)'
        """

        return 'Y = {0}(R) + {1}(G) + {2}(B)'.format(
            *np.ravel(normalised_primary_matrix(primaries, whitepoint))[3:6])

    def RGB_luminance(RGB, primaries, whitepoint):
        """
        Returns the *luminance* :math:`y` of given *RGB* components from given
        *primaries* and *whitepoint* matrices.

        Parameters
        ----------
        RGB : array_like, (3,)
            *RGB* chromaticity coordinate matrix.
        primaries : array_like, (3, 2)
            Primaries chromaticity coordinate matrix.
        whitepoint : array_like
            Illuminant / whitepoint chromaticity coordinates.

        Returns
        -------
        numeric
            *Luminance* :math:`y`.

        References
        ----------
        .. [5]  `RP 177-1993 SMPTE RECOMMENDED PRACTICE -
                Television Color Equations: 3.3.3 - 3.3.6
                <http://car.france3.mars.free.fr/HD/INA-%2026%20jan%2006/SMPTE%20normes%20et%20confs/rp177.pdf>`_  # noqa
        Examples
        --------
        >>> RGB = np.array([40.6, 4.2, 67.4])
        >>> pms = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700])
        >>> whitepoint = (0.32168, 0.33767)
        >>> RGB_luminance(RGB, pms, whitepoint)  # doctest: +ELLIPSIS
        12.1616018...
        """

        R, G, B = np.ravel(RGB)
        X, Y, Z = np.ravel(normalised_primary_matrix(primaries,
                                                     whitepoint))[3:6]

        return X * R + Y * G + Z * B