Exemplo n.º 1
0
    def test_n_dimensional_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.rgb_colourspace.RGB_to_XYZ` definition
        n-dimensions support.
        """

        RGB = np.array([0.00109657, 0.01282168, 0.01173596])
        W_R = np.array([0.31270, 0.32900])
        W_T = np.array([0.34570, 0.35850])
        M = np.array([[0.41240000, 0.35760000,
                       0.18050000], [0.21260000, 0.71520000, 0.07220000],
                      [0.01930000, 0.11920000, 0.95050000]])
        XYZ = np.array([0.00710593, 0.01016064, 0.00963478])  # yapf: disable
        np.testing.assert_almost_equal(
            RGB_to_XYZ(RGB, W_R, W_T, M), XYZ, decimal=7)

        RGB = np.tile(RGB, (6, 1))
        XYZ = np.tile(XYZ, (6, 1))
        np.testing.assert_almost_equal(
            RGB_to_XYZ(RGB, W_R, W_T, M), XYZ, decimal=7)

        W_R = np.tile(W_R, (6, 1))
        W_T = np.tile(W_T, (6, 1))
        np.testing.assert_almost_equal(
            RGB_to_XYZ(RGB, W_R, W_T, M), XYZ, decimal=7)

        RGB = np.reshape(RGB, (2, 3, 3))
        W_R = np.reshape(W_R, (2, 3, 2))
        W_T = np.reshape(W_T, (2, 3, 2))
        XYZ = np.reshape(XYZ, (2, 3, 3))
        np.testing.assert_almost_equal(
            RGB_to_XYZ(RGB, W_R, W_T, M), XYZ, decimal=7)
Exemplo n.º 2
0
    def test_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.RGB_to_XYZ` definition.
        """

        for xyY, XYZ, RGB in sRGB_LINEAR_COLORCHECKER_2005:
            np.testing.assert_almost_equal(RGB_to_XYZ(
                RGB, (0.31271, 0.32902), (0.34567, 0.35850),
                np.array([
                    0.41238656, 0.35759149, 0.18045049, 0.21263682, 0.71518298,
                    0.0721802, 0.01933062, 0.11919716, 0.95037259
                ]), 'Bradford', sRGB_INVERSE_TRANSFER_FUNCTION),
                                           np.array(XYZ),
                                           decimal=7)

        for xyY, XYZ, RGB in ACES_COLORCHECKER_2005:
            np.testing.assert_almost_equal(RGB_to_XYZ(
                RGB, (0.32168, 0.33767), (0.34567, 0.35850),
                np.array([
                    9.52552396e-01, 0.00000000e+00, 9.36786317e-05,
                    3.43966450e-01, 7.28166097e-01, -7.21325464e-02,
                    0.00000000e+00, 0.00000000e+00, 1.00882518e+00
                ])),
                                           np.array(XYZ),
                                           decimal=7)
Exemplo n.º 3
0
    def test_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.rgb_colourspace.RGB_to_XYZ` definition.
        """

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.70556599, 0.19109268, 0.22340812]),
                np.array([0.31270, 0.32900]), np.array([0.34570, 0.35850]),
                np.array([
                    [0.41240000, 0.35760000, 0.18050000],
                    [0.21260000, 0.71520000, 0.07220000],
                    [0.01930000, 0.11920000, 0.95050000],
                ]), 'Bradford', eotf_sRGB),
            np.array([0.21638819, 0.12570000, 0.03847493]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.72794579, 0.18180021, 0.17951580]),
                np.array([0.31270, 0.32900]), np.array([0.34570, 0.35850]),
                np.array([
                    [0.41240000, 0.35760000, 0.18050000],
                    [0.21260000, 0.71520000, 0.07220000],
                    [0.01930000, 0.11920000, 0.95050000],
                ]), None, eotf_sRGB),
            np.array([0.21638819, 0.12570000, 0.03847493]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.21959099, 0.06985815, 0.04703704]),
                np.array([0.32168, 0.33767]), np.array([0.34570, 0.35850]),
                np.array([
                    [0.95255240, 0.00000000, 0.00009368],
                    [0.34396645, 0.72816610, -0.07213255],
                    [0.00000000, 0.00000000, 1.00882518],
                ])),
            np.array([0.21638819, 0.12570000, 0.03847493]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.45620801, 0.03079991, 0.04091883]),
                np.array([0.31270, 0.32900, 1.00000]),
                np.array([0.34570, 0.35850]),
                np.array([
                    [0.41240000, 0.35760000, 0.18050000],
                    [0.21260000, 0.71520000, 0.07220000],
                    [0.01930000, 0.11920000, 0.95050000],
                ])),
            np.array([0.21638819, 0.12570000, 0.03847493]),
            decimal=7)
Exemplo n.º 4
0
def get_secondaries(name='ITU-R BT.2020'):
    """
    secondary color の座標を求める

    Parameters
    ----------
    name : str
        a name of the color space.

    Returns
    -------
    array_like
        secondaries. the order is magenta, yellow, cyan.

    """
    secondary_rgb = np.array([[1.0, 0.0, 1.0],
                              [1.0, 1.0, 0.0],
                              [0.0, 1.0, 1.0]])
    illuminant_XYZ = D65_WHITE
    illuminant_RGB = D65_WHITE
    chromatic_adaptation_transform = 'CAT02'
    rgb_to_xyz_matrix = get_rgb_to_xyz_matrix(name)
    large_xyz = RGB_to_XYZ(secondary_rgb, illuminant_RGB,
                           illuminant_XYZ, rgb_to_xyz_matrix,
                           chromatic_adaptation_transform)

    xy = XYZ_to_xy(large_xyz, illuminant_XYZ)

    return xy, secondary_rgb.reshape((3, 3))
Exemplo n.º 5
0
    def test_plot_hull_section_colours(self):
        """
        Test :func:`colour.plotting.section.plot_hull_section_colours`
        definition.
        """

        if not is_trimesh_installed:  # pragma: no cover
            return

        import trimesh

        vertices, faces, _outline = primitive_cube(1, 1, 1, 64, 64, 64)
        XYZ_vertices = RGB_to_XYZ(
            vertices["position"] + 0.5,
            RGB_COLOURSPACE_sRGB.whitepoint,
            RGB_COLOURSPACE_sRGB.whitepoint,
            RGB_COLOURSPACE_sRGB.matrix_RGB_to_XYZ,
        )
        hull = trimesh.Trimesh(XYZ_vertices, faces, process=False)

        figure, axes = plot_hull_section_colours(hull)

        self.assertIsInstance(figure, Figure)
        self.assertIsInstance(axes, Axes)

        figure, axes = plot_hull_section_colours(hull, axis="+x")

        self.assertIsInstance(figure, Figure)
        self.assertIsInstance(axes, Axes)

        figure, axes = plot_hull_section_colours(hull, axis="+y")

        self.assertIsInstance(figure, Figure)
        self.assertIsInstance(axes, Axes)
Exemplo n.º 6
0
def RGB_chromaticity_coordinates_CIE_1976_UCS_chromaticity_diagram_plot(
        RGB,
        colourspace,
        **kwargs):
    """
    Plots given *RGB* colourspace array in *CIE 1976 UCS Chromaticity Diagram*.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    colourspace : RGB_Colourspace
        *RGB* colourspace of the *RGB* array.
    \**kwargs : dict, optional
        Keywords arguments.

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> RGB = np.random.random((10, 10, 3))
    >>> c = 'Rec. 709'
    >>> RGB_chromaticity_coordinates_CIE_1976_UCS_chromaticity_diagram_plot(
    ...     RGB, c)  # doctest: +SKIP
    True
    """

    settings = {}
    settings.update(kwargs)
    settings.update({'standalone': False})

    settings['colourspaces'] = (
        [colourspace.name] + settings.get('colourspaces', []))

    RGB_colourspaces_CIE_1976_UCS_chromaticity_diagram_plot(**settings)

    alpha_p, colour_p = 0.85, 'black'

    uv = Luv_to_uv(XYZ_to_Luv(RGB_to_XYZ(RGB,
                                         colourspace.whitepoint,
                                         colourspace.whitepoint,
                                         colourspace.RGB_to_XYZ_matrix),
                              colourspace.whitepoint),
                   colourspace.whitepoint)

    pylab.scatter(uv[..., 0],
                  uv[..., 1],
                  alpha=alpha_p / 2,
                  color=colour_p,
                  marker='+')

    settings.update({'standalone': True})

    boundaries(**settings)
    decorate(**settings)

    return display(**settings)
Exemplo n.º 7
0
        def optimize(ijkL: ArrayLike, coefficients_0: ArrayLike) -> NDArray:
            """
            Solve for a specific lightness and stores the result in the
            appropriate cell.
            """

            i, j, k, L = tsplit(ijkL, dtype=DEFAULT_INT_DTYPE)

            RGB = self._lightness_scale[L] * chroma

            XYZ = RGB_to_XYZ(
                RGB,
                colourspace.whitepoint,
                xy_n,
                colourspace.matrix_RGB_to_XYZ,
            )

            coefficients, _error = find_coefficients_Jakob2019(
                XYZ, cmfs, illuminant, coefficients_0, dimensionalise=False
            )

            self._coefficients[i, L, j, k, :] = dimensionalise_coefficients(
                coefficients, shape
            )

            return coefficients
Exemplo n.º 8
0
    def test_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.rgb_colourspace.RGB_to_XYZ` definition.
        """

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.45286611, 0.31735742, 0.26418007]),
                np.array([0.31270, 0.32900]),
                np.array([0.34570, 0.35850]),
                np.array([
                    [0.41240000, 0.35760000, 0.18050000],
                    [0.21260000, 0.71520000, 0.07220000],
                    [0.01930000, 0.11920000, 0.95050000],
                ]), 'Bradford', oetf_reverse_sRGB),
            np.array([0.11518475, 0.10080000, 0.05089373]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.11757966, 0.08781514, 0.06185473]),
                np.array([0.32168, 0.33767]),
                np.array([0.34570, 0.35850]),
                np.array([
                    [0.95255240, 0.00000000, 0.00009368],
                    [0.34396645, 0.72816610, -0.07213255],
                    [0.00000000, 0.00000000, 1.00882518],
                ])),
            np.array([0.11518475, 0.10080000, 0.05089373]),
            decimal=7)

        np.testing.assert_almost_equal(
            RGB_to_XYZ(
                np.array([0.00109657, 0.01282168, 0.01173596]),
                np.array([0.31270, 0.32900, 0.10080]),
                np.array([0.34570, 0.35850]),
                np.array([
                    [0.41240000, 0.35760000, 0.18050000],
                    [0.21260000, 0.71520000, 0.07220000],
                    [0.01930000, 0.11920000, 0.95050000],
                ])),
            np.array([0.07049534, 0.10080000, 0.09558313]),
            decimal=7)
Exemplo n.º 9
0
def RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot(
        RGB, colourspace, **kwargs):
    """
    Plots given *RGB* colourspace array in *CIE 1931 Chromaticity Diagram*.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    colourspace : unicode
        *RGB* colourspace of the *RGB* array.
    \**kwargs : dict, optional
        Keywords arguments.

    Returns
    -------
    Figure
        Current figure or None.

    Examples
    --------
    >>> RGB = np.random.random((10, 10, 3))
    >>> c = 'Rec. 709'
    >>> RGB_chromaticity_coordinates_CIE_1931_chromaticity_diagram_plot(
    ...     RGB, c)  # doctest: +SKIP
    """

    settings = {}
    settings.update(kwargs)
    settings.update({'standalone': False})

    colourspace, name = get_RGB_colourspace(colourspace), colourspace
    settings['colourspaces'] = ([name] + settings.get('colourspaces', []))

    RGB_colourspaces_CIE_1931_chromaticity_diagram_plot(**settings)

    alpha_p, colour_p = 0.85, 'black'

    xy = XYZ_to_xy(
        RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint,
                   colourspace.RGB_to_XYZ_matrix), colourspace.whitepoint)

    pylab.scatter(xy[..., 0],
                  xy[..., 1],
                  alpha=alpha_p / 2,
                  color=colour_p,
                  marker='+')

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

    boundaries(**settings)
    decorate(**settings)

    return display(**settings)
Exemplo n.º 10
0
    def test_n_dimensional_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.rgb_colourspace.RGB_to_XYZ` definition
        n-dimensions support.
        """

        RGB = np.array([0.70556599, 0.19109268, 0.22340812])
        W_R = np.array([0.31270, 0.32900])
        W_T = np.array([0.34570, 0.35850])
        M = np.array([
            [0.41240000, 0.35760000, 0.18050000],
            [0.21260000, 0.71520000, 0.07220000],
            [0.01930000, 0.11920000, 0.95050000],
        ])
        XYZ = np.array([0.21638819, 0.12570000, 0.03847493])
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M, 'Bradford',
                                                  oetf_reverse_sRGB),
                                       XYZ,
                                       decimal=7)

        RGB = np.tile(RGB, (6, 1))
        XYZ = np.tile(XYZ, (6, 1))
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M, 'Bradford',
                                                  oetf_reverse_sRGB),
                                       XYZ,
                                       decimal=7)

        W_R = np.tile(W_R, (6, 1))
        W_T = np.tile(W_T, (6, 1))
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M, 'Bradford',
                                                  oetf_reverse_sRGB),
                                       XYZ,
                                       decimal=7)

        RGB = np.reshape(RGB, (2, 3, 3))
        W_R = np.reshape(W_R, (2, 3, 2))
        W_T = np.reshape(W_T, (2, 3, 2))
        XYZ = np.reshape(XYZ, (2, 3, 3))
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M, 'Bradford',
                                                  oetf_reverse_sRGB),
                                       XYZ,
                                       decimal=7)
Exemplo n.º 11
0
def highlights_recovery_LCHab(RGB,
                              threshold=None,
                              RGB_colourspace=sRGB_COLOURSPACE):
    """
    Performs highlights recovery in *CIE L\\*C\\*Hab* colourspace.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    threshold : numeric, optional
        Threshold for highlights selection, automatically computed
        if not given.
    RGB_colourspace : RGB_Colourspace, optional
        Working *RGB* colourspace to perform the *CIE L\\*C\\*Hab* to and from.

    Returns
    -------
    ndarray
         Highlights recovered *RGB* colourspace array.
    """

    L, _C, H = tsplit(
        Lab_to_LCHab(
            XYZ_to_Lab(
                RGB_to_XYZ(RGB, RGB_colourspace.whitepoint,
                           RGB_colourspace.whitepoint,
                           RGB_colourspace.RGB_to_XYZ_matrix),
                RGB_colourspace.whitepoint)))
    _L_c, C_c, _H_c = tsplit(
        Lab_to_LCHab(
            XYZ_to_Lab(
                RGB_to_XYZ(np.clip(RGB, 0,
                                   threshold), RGB_colourspace.whitepoint,
                           RGB_colourspace.whitepoint,
                           RGB_colourspace.RGB_to_XYZ_matrix),
                RGB_colourspace.whitepoint)))

    return XYZ_to_RGB(
        Lab_to_XYZ(LCHab_to_Lab(tstack([L, C_c, H])),
                   RGB_colourspace.whitepoint), RGB_colourspace.whitepoint,
        RGB_colourspace.whitepoint, RGB_colourspace.XYZ_to_RGB_matrix)
Exemplo n.º 12
0
def RGB_colourspace_limits(colourspace: RGB_Colourspace) -> NDArray:
    """
    Compute given *RGB* colourspace volume limits in *CIE L\\*a\\*b\\**
    colourspace.

    Parameters
    ----------
    colourspace
        *RGB* colourspace to compute the volume of.

    Returns
    -------
    :class:`numpy.ndarray`
        *RGB* colourspace volume limits.

    Notes
    -----
    The limits are computed for the given *RGB* colourspace illuminant. This is
    important to account for, if the intent is to compare various *RGB*
    colourspaces together. In this instance, they must be chromatically adapted
    to the same illuminant before-hand.
    See :meth:`colour.RGB_Colourspace.chromatically_adapt` method for more
    information.

    Examples
    --------
    >>> from colour.models import RGB_COLOURSPACE_sRGB as sRGB
    >>> RGB_colourspace_limits(sRGB)  # doctest: +ELLIPSIS
    array([[   0.       ...,  100.       ...],
           [ -86.182855 ...,   98.2563272...],
           [-107.8503557...,   94.4894974...]])
    """

    Lab_c = []
    for combination in list(itertools.product([0, 1], repeat=3)):
        Lab_c.append(
            XYZ_to_Lab(
                RGB_to_XYZ(
                    combination,
                    colourspace.whitepoint,
                    colourspace.whitepoint,
                    colourspace.matrix_RGB_to_XYZ,
                ),
                colourspace.whitepoint,
            ))
    Lab = np.array(Lab_c)

    limits = []
    for i in np.arange(3):
        limits.append((np.min(Lab[..., i]), np.max(Lab[..., i])))

    return np.array(limits)
Exemplo n.º 13
0
    def test_nan_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.RGB_to_XYZ` definition nan support.
        """

        cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
        cases = set(permutations(cases * 3, r=3))
        for case in cases:
            RGB = np.array(case)
            W_R = np.array(case[0:2])
            W_T = np.array(case[0:2])
            M = np.vstack((case, case, case)).reshape((3, 3))
            RGB_to_XYZ(RGB, W_R, W_T, M)
Exemplo n.º 14
0
    def test_domain_range_scale_XYZ_to_RGB(self):
        """
        Tests :func:`colour.models.rgb.rgb_colourspace.RGB_to_XYZ` definition
        domain and range scale support.
        """

        RGB = np.array([0.45620801, 0.03079991, 0.04091883])
        W_R = np.array([0.31270, 0.32900])
        W_T = np.array([0.34570, 0.35850])
        M = np.array([
            [3.24062548, -1.53720797, -0.49862860],
            [-0.96893071, 1.87575606, 0.04151752],
            [0.05571012, -0.20402105, 1.05699594],
        ])
        XYZ = RGB_to_XYZ(RGB, W_R, W_T, M)

        d_r = (('reference', 1), (1, 1), (100, 100))
        for scale, factor in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(RGB_to_XYZ(
                    RGB * factor, W_R, W_T, M),
                                               XYZ * factor,
                                               decimal=7)
Exemplo n.º 15
0
    def test_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.RGB_to_XYZ` definition.
        """

        for xyY, XYZ, RGB in sRGB_LINEAR_COLORCHECKER_2005:
            np.testing.assert_almost_equal(RGB_to_XYZ(
                RGB, np.array([0.31271, 0.32902]), np.array([0.34567,
                                                             0.35850]),
                np.array([[0.41238656, 0.35759149, 0.18045049],
                          [0.21263682, 0.71518298, 0.07218020],
                          [0.01933062, 0.11919716, 0.95037259]]), 'Bradford',
                sRGB_EOCF),
                                           np.array(XYZ),
                                           decimal=7)

        for xyY, XYZ, RGB in ACES_COLORCHECKER_2005:
            np.testing.assert_almost_equal(RGB_to_XYZ(
                RGB, np.array([0.32168, 0.33767]), np.array([0.34567,
                                                             0.35850]),
                np.array([[9.52552396e-01, 0.00000000e+00, 9.36786317e-05],
                          [3.43966450e-01, 7.28166097e-01, -7.21325464e-02],
                          [0.00000000e+00, 0.00000000e+00, 1.00882518e+00]])),
                                           np.array(XYZ),
                                           decimal=7)

        RGB = np.array([0.86969452, 1.00516431, 1.41715848])
        W_R = np.array([0.31271, 0.32902])
        W_T = np.array([0.34567, 0.35850, 0.10080])
        M = np.array([[0.41238656, 0.35759149, 0.18045049],
                      [0.21263682, 0.71518298, 0.07218020],
                      [0.01933062, 0.11919716, 0.95037259]])
        np.testing.assert_almost_equal(
            RGB_to_XYZ(RGB, W_R, W_T, M),
            np.array([0.09757065, 0.10063053, 0.11347848]),
            decimal=7)
Exemplo n.º 16
0
    def test_n_dimensional_RGB_to_XYZ(self):
        """
        Tests :func:`colour.models.rgb.RGB_to_XYZ` definition n-dimensions
        support.
        """

        RGB = np.array([0.86969452, 1.00516431, 1.41715848])
        W_R = np.array([0.31271, 0.32902])
        W_T = np.array([0.34567, 0.35850])
        M = np.array([[0.41238656, 0.35759149, 0.18045049],
                      [0.21263682, 0.71518298, 0.07218020],
                      [0.01933062, 0.11919716, 0.95037259]])
        XYZ = np.array([0.96796280, 0.99831871, 1.12577854])
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M),
                                       XYZ,
                                       decimal=7)

        RGB = np.tile(RGB, (6, 1))
        XYZ = np.tile(XYZ, (6, 1))
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M),
                                       XYZ,
                                       decimal=7)

        W_R = np.tile(W_R, (6, 1))
        W_T = np.tile(W_T, (6, 1))
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M),
                                       XYZ,
                                       decimal=7)

        RGB = np.reshape(RGB, (2, 3, 3))
        W_R = np.reshape(W_R, (2, 3, 2))
        W_T = np.reshape(W_T, (2, 3, 2))
        XYZ = np.reshape(XYZ, (2, 3, 3))
        np.testing.assert_almost_equal(RGB_to_XYZ(RGB, W_R, W_T, M),
                                       XYZ,
                                       decimal=7)
Exemplo n.º 17
0
def sRGB_to_XYZ(RGB,
                illuminant=RGB_COLOURSPACES.get('sRGB').whitepoint,
                chromatic_adaptation_method='CAT02',
                apply_EOCF=True):
    """
    Converts from *sRGB* colourspace to *CIE XYZ* tristimulus values.

    Parameters
    ----------
    RGB : array_like
        *sRGB* colourspace array.
    illuminant : array_like, optional
        Source illuminant chromaticity coordinates.
    chromatic_adaptation_method : unicode, optional
        **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp',
        'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco',
        'Bianco PC'}**,
        *Chromatic adaptation* method.
    apply_EOCF : bool, optional
        Apply *sRGB* *electro-optical conversion function*.

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

    Notes
    -----
    -   Input *RGB* colourspace array is in domain [0, 1].

    Examples
    --------
    >>> import numpy as np
    >>> RGB = np.array([0.17501358, 0.38818795, 0.32161955])
    >>> sRGB_to_XYZ(RGB)  # doctest: +ELLIPSIS
    array([ 0.0704953...,  0.1008    ,  0.0955831...])
    """

    sRGB = RGB_COLOURSPACES.get('sRGB')
    return RGB_to_XYZ(RGB, sRGB.whitepoint, illuminant, sRGB.RGB_to_XYZ_matrix,
                      chromatic_adaptation_method,
                      sRGB.EOCF if apply_EOCF else None)
Exemplo n.º 18
0
def RGB_colourspace_limits(
        colourspace,
        illuminant=CCS_ILLUMINANTS['CIE 1931 2 Degree Standard Observer']
    ['D65']):
    """
    Computes given *RGB* colourspace volume limits in *CIE L\\*a\\*b\\**
    colourspace.

    Parameters
    ----------
    colourspace : RGB_Colourspace
        *RGB* colourspace to compute the volume of.
    illuminant : array_like, optional
        *CIE L\\*a\\*b\\** colourspace *illuminant* chromaticity coordinates.

    Returns
    -------
    ndarray
        *RGB* colourspace volume limits.

    Examples
    --------
    >>> from colour.models import RGB_COLOURSPACE_sRGB as sRGB
    >>> RGB_colourspace_limits(sRGB)  # doctest: +ELLIPSIS
    array([[   0.       ...,  100.       ...],
           [ -86.182855 ...,   98.2563272...],
           [-107.8503557...,   94.4894974...]])
    """

    Lab = []
    for combination in list(itertools.product([0, 1], repeat=3)):
        Lab.append(
            XYZ_to_Lab(
                RGB_to_XYZ(combination, colourspace.whitepoint, illuminant,
                           colourspace.matrix_RGB_to_XYZ)))
    Lab = np.array(Lab)

    limits = []
    for i in np.arange(3):
        limits.append((np.min(Lab[..., i]), np.max(Lab[..., i])))

    return np.array(limits)
Exemplo n.º 19
0
        def optimize(ijkL, coefficients_0):
            """
            Solves for a specific lightness and stores the result in the
            appropriate cell.
            """

            i, j, k, L = ijkL

            RGB = self._lightness_scale[L] * chroma

            XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, xy_n,
                             colourspace.matrix_RGB_to_XYZ)

            coefficients, error = find_coefficients_Jakob2019(
                XYZ, cmfs, illuminant, coefficients_0, dimensionalise=False)

            self._coefficients[i, L, j, k, :] = dimensionalise_coefficients(
                coefficients, shape)

            return coefficients
Exemplo n.º 20
0
def RGB_colourspace_limits(
    colourspace,
    illuminant=ILLUMINANTS.get('CIE 1931 2 Degree Standard Observer').get(
        'D50')):
    """
    Computes given *RGB* colourspace volume limits in *Lab* colourspace.

    Parameters
    ----------
    colourspace : RGB_Colourspace
        *RGB* colourspace to compute the volume of.
    illuminant : array_like, optional
        *Lab* colourspace *illuminant* chromaticity coordinates.

    Returns
    -------
    ndarray
        *RGB* colourspace volume limits.

    Examples
    --------
    >>> from colour import sRGB_COLOURSPACE as sRGB
    >>> RGB_colourspace_limits(sRGB)  # doctest: +ELLIPSIS
    array([[   0...        ,  100...        ],
           [ -79.2263741...,   94.6657491...],
           [-114.7846271...,   96.7135199...]])
    """

    Lab = []
    for combination in list(itertools.product([0, 1], repeat=3)):
        Lab.append(
            XYZ_to_Lab(
                RGB_to_XYZ(combination, colourspace.whitepoint, illuminant,
                           colourspace.RGB_to_XYZ_matrix)))
    Lab = np.array(Lab)

    limits = []
    for i in np.arange(3):
        limits.append((np.min(Lab[..., i]), np.max(Lab[..., i])))

    return np.array(limits)
Exemplo n.º 21
0
    def test_LUT3D_Jakob2019(self):
        """
        Tests the entirety of the
        :class:`colour.recovery.jakob2019.LUT3D_Jakob2019`class.
        """

        LUT = LUT3D_Jakob2019()
        LUT.generate(self._RGB_colourspace, self._cmfs, self._sd_D65, 5)

        path = os.path.join(self._temporary_directory, 'Test_Jakob2019.coeff')

        LUT.write(path)
        LUT.read(path)

        for RGB in [
                np.array([1, 0, 0]),
                np.array([0, 1, 0]),
                np.array([0, 0, 1]),
                zeros(3),
                full(3, 0.5),
                ones(3),
        ]:
            XYZ = RGB_to_XYZ(RGB, self._RGB_colourspace.whitepoint,
                             self._xy_D65,
                             self._RGB_colourspace.matrix_RGB_to_XYZ)
            Lab = XYZ_to_Lab(XYZ, self._xy_D65)

            recovered_sd = LUT.RGB_to_sd(RGB)
            recovered_XYZ = sd_to_XYZ(recovered_sd, self._cmfs,
                                      self._sd_D65) / 100
            recovered_Lab = XYZ_to_Lab(recovered_XYZ, self._xy_D65)

            error = delta_E_CIE1976(Lab, recovered_Lab)

            if error > 2 * JND_CIE1976 / 100:
                self.fail(
                    'Delta E for RGB={0} in colourspace {1} is {2}!'.format(
                        RGB, self._RGB_colourspace.name, error))
Exemplo n.º 22
0
def RGB_to_Lab(RGB, colourspace):
    """
    Converts given *RGB* value from given colourspace to *CIE Lab* colourspace.

    Parameters
    ----------
    RGB : array_like
        *RGB* value.
    colourspace : RGB_Colourspace
        *RGB* colourspace.

    Returns
    -------
    bool
        Definition success.
    """

    return XYZ_to_Lab(
        RGB_to_XYZ(
            np.array(RGB), colourspace.whitepoint,
            ILLUMINANTS.get('CIE 1931 2 Degree Standard Observer').get('E'),
            colourspace.to_XYZ, 'Bradford', colourspace.cctf_decoding),
        colourspace.whitepoint)
Exemplo n.º 23
0
def plot_RGB_scatter(RGB,
                     colourspace,
                     reference_colourspace='CIE xyY',
                     colourspaces=None,
                     segments=8,
                     show_grid=True,
                     grid_segments=10,
                     show_spectral_locus=False,
                     spectral_locus_colour=None,
                     points_size=12,
                     cmfs='CIE 1931 2 Degree Standard Observer',
                     **kwargs):
    """
    Plots given *RGB* colourspace array in a scatter plot.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    colourspace : RGB_Colourspace
        *RGB* colourspace of the *RGB* array.
    reference_colourspace : unicode, optional
        **{'CIE XYZ', 'CIE xyY', 'CIE xy', 'CIE Lab', 'CIE LCHab', 'CIE Luv',
        'CIE Luv uv', 'CIE LCHuv', 'CIE UCS', 'CIE UCS uv', 'CIE UVW',
        'DIN 99', 'Hunter Lab', 'Hunter Rdab', 'IPT', 'JzAzBz', 'OSA UCS',
        'hdr-CIELAB', 'hdr-IPT'}**,
        Reference colourspace for colour conversion.
    colourspaces : array_like, optional
        *RGB* colourspaces to plot the gamuts.
    segments : int, optional
        Edge segments count for each *RGB* colourspace cubes.
    show_grid : bool, optional
        Whether to show a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments : bool, optional
        Edge segments count for the grid.
    show_spectral_locus : bool, optional
        Whether to show the spectral locus.
    spectral_locus_colour : array_like, optional
        Spectral locus colour.
    points_size : numeric, optional
        Scatter points size.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectral locus.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.plot_RGB_colourspaces_gamuts`},
        Please refer to the documentation of the previously listed definitions.

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

    Examples
    --------
    >>> RGB = np.random.random((128, 128, 3))
    >>> plot_RGB_scatter(RGB, 'ITU-R BT.709')  # doctest: +SKIP

    .. image:: ../_static/Plotting_Plot_RGB_Scatter.png
        :align: center
        :alt: plot_RGB_scatter
    """

    colourspace = first_item(filter_RGB_colourspaces(colourspace).values())

    if colourspaces is None:
        colourspaces = (colourspace.name, )

    count_c = len(colourspaces)
    settings = Structure(
        **{
            'face_colours': [None] * count_c,
            'edge_colours': [(0.25, 0.25, 0.25)] * count_c,
            'face_alpha': [0.0] * count_c,
            'edge_alpha': [0.1] * count_c,
        })
    settings.update(kwargs)
    settings['standalone'] = False

    plot_RGB_colourspaces_gamuts(
        colourspaces=colourspaces,
        reference_colourspace=reference_colourspace,
        segments=segments,
        show_grid=show_grid,
        grid_segments=grid_segments,
        show_spectral_locus=show_spectral_locus,
        spectral_locus_colour=spectral_locus_colour,
        cmfs=cmfs,
        **settings)

    XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint,
                     colourspace.RGB_to_XYZ_matrix)

    points = common_colourspace_model_axis_reorder(
        XYZ_to_colourspace_model(XYZ, colourspace.whitepoint,
                                 reference_colourspace), reference_colourspace)

    axes = plt.gca()
    axes.scatter(
        points[..., 0],
        points[..., 1],
        points[..., 2],
        color=np.reshape(RGB, (-1, 3)),
        s=points_size)

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

    return render(**settings)
Exemplo n.º 24
0
def plot_RGB_colourspaces_gamuts(colourspaces=None,
                                 reference_colourspace='CIE xyY',
                                 segments=8,
                                 show_grid=True,
                                 grid_segments=10,
                                 show_spectral_locus=False,
                                 spectral_locus_colour=None,
                                 cmfs='CIE 1931 2 Degree Standard Observer',
                                 **kwargs):
    """
    Plots given *RGB* colourspaces gamuts in given reference colourspace.

    Parameters
    ----------
    colourspaces : array_like, optional
        *RGB* colourspaces to plot the gamuts.
    reference_colourspace : unicode, optional
        **{'CIE XYZ', 'CIE xyY', 'CIE xy', 'CIE Lab', 'CIE LCHab', 'CIE Luv',
        'CIE Luv uv', 'CIE LCHuv', 'CIE UCS', 'CIE UCS uv', 'CIE UVW',
        'DIN 99', 'Hunter Lab', 'Hunter Rdab', 'IPT', 'JzAzBz', 'OSA UCS',
        'hdr-CIELAB', 'hdr-IPT'}**,
        Reference colourspace to plot the gamuts into.
    segments : int, optional
        Edge segments count for each *RGB* colourspace cubes.
    show_grid : bool, optional
        Whether to show a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments : bool, optional
        Edge segments count for the grid.
    show_spectral_locus : bool, optional
        Whether to show the spectral locus.
    spectral_locus_colour : array_like, optional
        Spectral locus colour.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectral locus.

    Other Parameters
    ----------------
    \\**kwargs : dict, optional
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.volume.nadir_grid`},
        Please refer to the documentation of the previously listed definitions.
    face_colours : array_like, optional
        Face colours array such as `face_colours = (None, (0.5, 0.5, 1.0))`.
    edge_colours : array_like, optional
        Edge colours array such as `edge_colours = (None, (0.5, 0.5, 1.0))`.
    face_alpha : numeric, optional
        Face opacity value such as `face_alpha = (0.5, 1.0)`.
    edge_alpha : numeric, optional
        Edge opacity value such as `edge_alpha = (0.0, 1.0)`.

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

    Examples
    --------
    >>> plot_RGB_colourspaces_gamuts(['ITU-R BT.709', 'ACEScg', 'S-Gamut'])
    ... # doctest: +SKIP

    .. image:: ../_static/Plotting_Plot_RGB_Colourspaces_Gamuts.png
        :align: center
        :alt: plot_RGB_colourspaces_gamuts
    """

    if colourspaces is None:
        colourspaces = ('ITU-R BT.709', 'ACEScg')

    colourspaces = filter_RGB_colourspaces(colourspaces).values()

    count_c = len(colourspaces)

    title = '{0} - {1} Reference Colourspace'.format(
        ', '.join([colourspace.name for colourspace in colourspaces]),
        reference_colourspace,
    )

    settings = Structure(
        **{
            'face_colours': [None] * count_c,
            'edge_colours': [None] * count_c,
            'face_alpha': [1] * count_c,
            'edge_alpha': [1] * count_c,
            'title': title,
        })
    settings.update(kwargs)

    figure = plt.figure()
    axes = figure.add_subplot(111, projection='3d')

    illuminant = COLOUR_STYLE_CONSTANTS.colour.colourspace.whitepoint

    points = np.zeros((4, 3))
    if show_spectral_locus:
        cmfs = first_item(filter_cmfs(cmfs).values())
        XYZ = cmfs.values

        points = common_colourspace_model_axis_reorder(
            XYZ_to_colourspace_model(XYZ, illuminant, reference_colourspace),
            reference_colourspace)

        points[np.isnan(points)] = 0

        c = ((0.0, 0.0, 0.0, 0.5)
             if spectral_locus_colour is None else spectral_locus_colour)

        axes.plot(
            points[..., 0], points[..., 1], points[..., 2], color=c, zorder=1)
        axes.plot(
            (points[-1][0], points[0][0]), (points[-1][1], points[0][1]),
            (points[-1][2], points[0][2]),
            color=c,
            zorder=1)

    quads, RGB_f, RGB_e = [], [], []
    for i, colourspace in enumerate(colourspaces):
        quads_c, RGB = RGB_identity_cube(
            width_segments=segments,
            height_segments=segments,
            depth_segments=segments)

        XYZ = RGB_to_XYZ(
            quads_c,
            colourspace.whitepoint,
            colourspace.whitepoint,
            colourspace.RGB_to_XYZ_matrix,
        )

        quads.extend(
            common_colourspace_model_axis_reorder(
                XYZ_to_colourspace_model(
                    XYZ,
                    colourspace.whitepoint,
                    reference_colourspace,
                ), reference_colourspace))

        if settings.face_colours[i] is not None:
            RGB = np.ones(RGB.shape) * settings.face_colours[i]

        RGB_f.extend(
            np.hstack([
                RGB,
                np.full((RGB.shape[0], 1), settings.face_alpha[i],
                        DEFAULT_FLOAT_DTYPE)
            ]))

        if settings.edge_colours[i] is not None:
            RGB = np.ones(RGB.shape) * settings.edge_colours[i]

        RGB_e.extend(
            np.hstack([
                RGB,
                np.full((RGB.shape[0], 1), settings.edge_alpha[i],
                        DEFAULT_FLOAT_DTYPE)
            ]))

    quads = as_float_array(quads)
    quads[np.isnan(quads)] = 0

    if quads.size != 0:
        for i, axis in enumerate('xyz'):
            min_a = min(np.min(quads[..., i]), np.min(points[..., i]))
            max_a = max(np.max(quads[..., i]), np.max(points[..., i]))
            getattr(axes, 'set_{}lim'.format(axis))((min_a, max_a))

    labels = COLOURSPACE_MODELS_LABELS[reference_colourspace]
    for i, axis in enumerate('xyz'):
        getattr(axes, 'set_{}label'.format(axis))(labels[i])

    if show_grid:
        if reference_colourspace == 'CIE Lab':
            limits = np.array([[-450, 450], [-450, 450]])
        elif reference_colourspace == 'CIE Luv':
            limits = np.array([[-650, 650], [-650, 650]])
        elif reference_colourspace == 'CIE UVW':
            limits = np.array([[-850, 850], [-850, 850]])
        elif reference_colourspace in ('Hunter Lab', 'Hunter Rdab'):
            limits = np.array([[-250, 250], [-250, 250]])
        else:
            limits = np.array([[-1.5, 1.5], [-1.5, 1.5]])

        quads_g, RGB_gf, RGB_ge = nadir_grid(limits, grid_segments, labels,
                                             axes, **settings)
        quads = np.vstack([quads_g, quads])
        RGB_f = np.vstack([RGB_gf, RGB_f])
        RGB_e = np.vstack([RGB_ge, RGB_e])

    collection = Poly3DCollection(quads)
    collection.set_facecolors(RGB_f)
    collection.set_edgecolors(RGB_e)

    axes.add_collection3d(collection)

    settings.update({
        'axes': axes,
        'axes_visible': False,
        'camera_aspect': 'equal'
    })
    settings.update(kwargs)

    return render(**settings)
Exemplo n.º 25
0
def RGB_scatter_plot(RGB,
                     colourspace,
                     reference_colourspace='CIE xyY',
                     colourspaces=None,
                     segments=8,
                     display_grid=True,
                     grid_segments=10,
                     spectral_locus=False,
                     spectral_locus_colour=None,
                     points_size=12,
                     cmfs='CIE 1931 2 Degree Standard Observer',
                     **kwargs):
    """
    Plots given *RGB* colourspace array in a scatter plot.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    colourspace : RGB_Colourspace
        *RGB* colourspace of the *RGB* array.
    reference_colourspace : unicode, optional
        **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW',
        'IPT'}**,
        Reference colourspace for colour conversion.
    colourspaces : array_like, optional
        *RGB* colourspaces to plot the gamuts.
    segments : int, optional
        Edge segments count for each *RGB* colourspace cubes.
    display_grid : bool, optional
        Display a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments : bool, optional
        Edge segments count for the grid.
    spectral_locus : bool, optional
        Is spectral locus line plotted.
    spectral_locus_colour : array_like, optional
        Spectral locus line colour.
    points_size : numeric, optional
        Scatter points size.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectral locus.
    \**kwargs : dict, optional
        **{'face_colours', 'edge_colours', 'edge_alpha', 'face_alpha'}**,
        Arguments for each given colourspace where each key has an array_like
        value such as: ``{ 'face_colours': (None, (0.5, 0.5, 1.0)),
        'edge_colours': (None, (0.5, 0.5, 1.0)), 'edge_alpha': (0.5, 1.0),
        'face_alpha': (0.0, 1.0)}``

        **{'grid_face_colours', 'grid_edge_colours', 'grid_face_alpha',
        'grid_edge_alpha', 'x_axis_colour', 'y_axis_colour', 'x_ticks_colour',
        'y_ticks_colour', 'x_label_colour', 'y_label_colour',
        'ticks_and_label_location'}**,
        Arguments for the nadir grid such as ``{'grid_face_colours':
        (0.25, 0.25, 0.25), 'grid_edge_colours': (0.50, 0.50, 0.50),
        'grid_face_alpha': 0.1, 'grid_edge_alpha': 0.5, 'x_axis_colour':
        (0.0, 0.0, 0.0, 1.0), 'y_axis_colour': (0.0, 0.0, 0.0, 1.0),
        'x_ticks_colour': (0.0, 0.0, 0.0, 0.85), 'y_ticks_colour':
        (0.0, 0.0, 0.0, 0.85), 'x_label_colour': (0.0, 0.0, 0.0, 0.85),
        'y_label_colour': (0.0, 0.0, 0.0, 0.85), 'ticks_and_label_location':
        ('-x', '-y')}``

    Returns
    -------
    bool
        Definition success.

    Examples
    --------
    >>> c = 'Rec. 709'
    >>> RGB_scatter_plot(c)  # doctest: +SKIP
    True
    """

    colourspace = get_RGB_colourspace(colourspace)

    if colourspaces is None:
        colourspaces = (colourspace.name, )

    count_c = len(colourspaces)
    settings = Structure(
        **{
            'face_colours': [None] * count_c,
            'edge_colours': [(0.25, 0.25, 0.25)] * count_c,
            'face_alpha': [0.0] * count_c,
            'edge_alpha': [0.1] * count_c,
            'standalone': False
        })
    settings.update(kwargs)

    RGB_colourspaces_gamuts_plot(colourspaces=colourspaces,
                                 reference_colourspace=reference_colourspace,
                                 segments=segments,
                                 display_grid=display_grid,
                                 grid_segments=grid_segments,
                                 spectral_locus=spectral_locus,
                                 spectral_locus_colour=spectral_locus_colour,
                                 cmfs=cmfs,
                                 **settings)

    XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint,
                     colourspace.RGB_to_XYZ_matrix)

    points = XYZ_to_reference_colourspace(XYZ, colourspace.whitepoint,
                                          reference_colourspace)

    axes = matplotlib.pyplot.gca()
    axes.scatter(points[..., 0],
                 points[..., 1],
                 points[..., 2],
                 color=np.reshape(RGB, (-1, 3)),
                 s=points_size)

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

    camera(**settings)
    decorate(**settings)

    return display(**settings)
Exemplo n.º 26
0
def RGB_colourspaces_gamuts_plot(colourspaces=None,
                                 reference_colourspace='CIE xyY',
                                 segments=8,
                                 display_grid=True,
                                 grid_segments=10,
                                 spectral_locus=False,
                                 spectral_locus_colour=None,
                                 cmfs='CIE 1931 2 Degree Standard Observer',
                                 **kwargs):
    """
    Plots given *RGB* colourspaces gamuts in given reference colourspace.

    Parameters
    ----------
    colourspaces : array_like, optional
        *RGB* colourspaces to plot the gamuts.
    reference_colourspace : unicode, optional
        **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW',
        'IPT', 'Hunter Lab', 'Hunter Rdab'}**,
        Reference colourspace to plot the gamuts into.
    segments : int, optional
        Edge segments count for each *RGB* colourspace cubes.
    display_grid : bool, optional
        Display a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments : bool, optional
        Edge segments count for the grid.
    spectral_locus : bool, optional
        Is spectral locus line plotted.
    spectral_locus_colour : array_like, optional
        Spectral locus line colour.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectral locus.

    Other Parameters
    ----------------
    \**kwargs : dict, optional
        {:func:`nadir_grid`},
        Please refer to the documentation of the previously listed definitions.
    face_colours : array_like, optional
        Face colours array such as `face_colours = (None, (0.5, 0.5, 1.0))`.
    edge_colours : array_like, optional
        Edge colours array such as `edge_colours = (None, (0.5, 0.5, 1.0))`.
    face_alpha : numeric, optional
        Face opacity value such as `face_alpha = (0.5, 1.0)`.
    edge_alpha : numeric, optional
        Edge opacity value such as `edge_alpha = (0.0, 1.0)`.

    Returns
    -------
    Figure
        Current figure or None.

    Examples
    --------
    >>> c = ['Rec. 709', 'ACEScg', 'S-Gamut']
    >>> RGB_colourspaces_gamuts_plot(c)  # doctest: +SKIP
    """

    if colourspaces is None:
        colourspaces = ('Rec. 709', 'ACEScg')

    count_c = len(colourspaces)
    settings = Structure(
        **{
            'face_colours': [None] * count_c,
            'edge_colours': [None] * count_c,
            'face_alpha': [1] * count_c,
            'edge_alpha': [1] * count_c,
            'title':
            '{0} - {1} Reference Colourspace'.format(', '.join(colourspaces),
                                                     reference_colourspace)
        })
    settings.update(kwargs)

    figure = matplotlib.pyplot.figure()
    axes = figure.add_subplot(111, projection='3d')

    illuminant = DEFAULT_PLOTTING_ILLUMINANT

    points = np.zeros((4, 3))
    if spectral_locus:
        cmfs = get_cmfs(cmfs)
        XYZ = cmfs.values

        points = common_colourspace_model_axis_reorder(
            XYZ_to_colourspace_model(XYZ, illuminant, reference_colourspace),
            reference_colourspace)

        points[np.isnan(points)] = 0

        c = ((0.0, 0.0, 0.0,
              0.5) if spectral_locus_colour is None else spectral_locus_colour)

        pylab.plot(points[..., 0],
                   points[..., 1],
                   points[..., 2],
                   color=c,
                   linewidth=2,
                   zorder=1)
        pylab.plot((points[-1][0], points[0][0]),
                   (points[-1][1], points[0][1]),
                   (points[-1][2], points[0][2]),
                   color=c,
                   linewidth=2,
                   zorder=1)

    quads, RGB_f, RGB_e = [], [], []
    for i, colourspace in enumerate(colourspaces):
        colourspace = get_RGB_colourspace(colourspace)
        quads_c, RGB = RGB_identity_cube(width_segments=segments,
                                         height_segments=segments,
                                         depth_segments=segments)

        XYZ = RGB_to_XYZ(quads_c, colourspace.whitepoint,
                         colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix)

        quads.extend(
            common_colourspace_model_axis_reorder(
                XYZ_to_colourspace_model(XYZ, colourspace.whitepoint,
                                         reference_colourspace),
                reference_colourspace))

        if settings.face_colours[i] is not None:
            RGB = np.ones(RGB.shape) * settings.face_colours[i]

        RGB_f.extend(
            np.hstack((RGB,
                       np.full((RGB.shape[0], 1), settings.face_alpha[i],
                               np.float_))))

        if settings.edge_colours[i] is not None:
            RGB = np.ones(RGB.shape) * settings.edge_colours[i]

        RGB_e.extend(
            np.hstack((RGB,
                       np.full((RGB.shape[0], 1), settings.edge_alpha[i],
                               np.float_))))

    quads = np.asarray(quads)
    quads[np.isnan(quads)] = 0

    if quads.size != 0:
        for i, axis in enumerate('xyz'):
            min_a = np.min(np.vstack((quads[..., i], points[..., i])))
            max_a = np.max(np.vstack((quads[..., i], points[..., i])))
            getattr(axes, 'set_{}lim'.format(axis))((min_a, max_a))

    labels = COLOURSPACE_MODELS_LABELS[reference_colourspace]
    for i, axis in enumerate('xyz'):
        getattr(axes, 'set_{}label'.format(axis))(labels[i])

    if display_grid:
        if reference_colourspace == 'CIE Lab':
            limits = np.array([[-450, 450], [-450, 450]])
        elif reference_colourspace == 'CIE Luv':
            limits = np.array([[-650, 650], [-650, 650]])
        elif reference_colourspace == 'CIE UVW':
            limits = np.array([[-850, 850], [-850, 850]])
        elif reference_colourspace in ('Hunter Lab', 'Hunter Rdab'):
            limits = np.array([[-250, 250], [-250, 250]])
        else:
            limits = np.array([[-1.5, 1.5], [-1.5, 1.5]])

        quads_g, RGB_gf, RGB_ge = nadir_grid(limits, grid_segments, labels,
                                             axes, **settings)
        quads = np.vstack((quads_g, quads))
        RGB_f = np.vstack((RGB_gf, RGB_f))
        RGB_e = np.vstack((RGB_ge, RGB_e))

    collection = Poly3DCollection(quads)
    collection.set_facecolors(RGB_f)
    collection.set_edgecolors(RGB_e)

    axes.add_collection3d(collection)

    settings.update({'camera_aspect': 'equal', 'no_axes': True})
    settings.update(kwargs)

    camera(**settings)
    decorate(**settings)

    return display(**settings)
Exemplo n.º 27
0
def plot_RGB_colourspace_section(
    colourspace: Union[RGB_Colourspace, str, Sequence[Union[RGB_Colourspace,
                                                            str]]],
    model: Union[Literal["CAM02LCD", "CAM02SCD", "CAM02UCS", "CAM16LCD",
                         "CAM16SCD", "CAM16UCS", "CIE XYZ", "CIE xyY",
                         "CIE Lab", "CIE Luv", "CIE UCS", "CIE UVW", "DIN99",
                         "Hunter Lab", "Hunter Rdab", "ICaCb", "ICtCp", "IPT",
                         "IgPgTg", "Jzazbz", "OSA UCS", "Oklab", "hdr-CIELAB",
                         "hdr-IPT", ], str, ] = "CIE xyY",
    axis: Union[Literal["+z", "+x", "+y"], str] = "+z",
    origin: Floating = 0.5,
    normalise: Boolean = True,
    show_section_colours: Boolean = True,
    show_section_contour: Boolean = True,
    **kwargs: Any,
) -> Tuple[plt.Figure, plt.Axes]:
    """
    Plot given *RGB* colourspace section colours along given axis and origin.

    Parameters
    ----------
    colourspace
        *RGB* colourspace of the *RGB* array. ``colourspace`` can be of any
        type or form supported by the
        :func:`colour.plotting.filter_RGB_colourspaces` definition.
    model
        Colourspace model, see :attr:`colour.COLOURSPACE_MODELS` attribute for
        the list of supported colourspace models.
    axis
        Axis the hull section will be normal to.
    origin
        Coordinate along ``axis`` at which to plot the hull section.
    normalise
        Whether to normalise ``axis`` to the extent of the hull along it.
    show_section_colours
        Whether to show the hull section colours.
    show_section_contour
        Whether to show the hull section contour.

    Other Parameters
    ----------------
    kwargs
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.render`,
        :func:`colour.plotting.section.plot_hull_section_colours`
        :func:`colour.plotting.section.plot_hull_section_contour`},
        See the documentation of the previously listed definitions.

    Returns
    -------
    :class:`tuple`
        Current figure and axes.

    Examples
    --------
    >>> from colour.utilities import is_trimesh_installed
    >>> if is_trimesh_installed:
    ...     plot_RGB_colourspace_section(
    ...         'sRGB', section_colours='RGB', section_opacity=0.15)
    ...     # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...AxesSubplot...>)

    .. image:: ../_static/Plotting_Plot_RGB_Colourspace_Section.png
        :align: center
        :alt: plot_RGB_colourspace_section
    """

    import trimesh

    settings: Dict[str, Any] = {"uniform": True}
    settings.update(kwargs)

    _figure, axes = artist(**settings)

    colourspace = cast(
        RGB_Colourspace,
        first_item(filter_RGB_colourspaces(colourspace).values()),
    )

    vertices, faces, _outline = primitive_cube(1, 1, 1, 64, 64, 64)
    XYZ_vertices = RGB_to_XYZ(
        vertices["position"] + 0.5,
        colourspace.whitepoint,
        colourspace.whitepoint,
        colourspace.matrix_RGB_to_XYZ,
    )
    hull = trimesh.Trimesh(XYZ_vertices, faces, process=False)

    if show_section_colours:
        settings = {"axes": axes}
        settings.update(kwargs)
        settings["standalone"] = False

        plot_hull_section_colours(hull, model, axis, origin, normalise,
                                  **settings)

    if show_section_contour:
        settings = {"axes": axes}
        settings.update(kwargs)
        settings["standalone"] = False

        plot_hull_section_contour(hull, model, axis, origin, normalise,
                                  **settings)

    title = (f"{colourspace.name} Section - "
             f"{f'{origin * 100}%' if normalise else origin} - "
             f"{model}")

    plane = MAPPING_AXIS_TO_PLANE[axis]

    labels = np.array(COLOURSPACE_MODELS_AXIS_LABELS[model])[as_int_array(
        colourspace_model_axis_reorder([0, 1, 2], model))]
    x_label, y_label = labels[plane[0]], labels[plane[1]]

    settings.update({
        "axes": axes,
        "standalone": True,
        "title": title,
        "x_label": x_label,
        "y_label": y_label,
    })
    settings.update(kwargs)

    return render(**settings)
Exemplo n.º 28
0
def plot_RGB_scatter(
    RGB: ArrayLike,
    colourspace: Union[RGB_Colourspace, str, Sequence[Union[RGB_Colourspace,
                                                            str]]],
    reference_colourspace: Union[Literal["CAM02LCD", "CAM02SCD", "CAM02UCS",
                                         "CAM16LCD", "CAM16SCD", "CAM16UCS",
                                         "CIE XYZ", "CIE xyY", "CIE Lab",
                                         "CIE Luv", "CIE UCS", "CIE UVW",
                                         "DIN99", "Hunter Lab", "Hunter Rdab",
                                         "ICaCb", "ICtCp", "IPT", "IgPgTg",
                                         "Jzazbz", "OSA UCS", "Oklab",
                                         "hdr-CIELAB", "hdr-IPT", ],
                                 str, ] = "CIE xyY",
    colourspaces: Optional[Union[RGB_Colourspace, str,
                                 Sequence[Union[RGB_Colourspace,
                                                str]]]] = None,
    segments: Integer = 8,
    show_grid: Boolean = True,
    grid_segments: Integer = 10,
    show_spectral_locus: Boolean = False,
    spectral_locus_colour: Optional[Union[ArrayLike, str]] = None,
    points_size: Floating = 12,
    cmfs: Union[MultiSpectralDistributions, str, Sequence[Union[
        MultiSpectralDistributions,
        str]], ] = "CIE 1931 2 Degree Standard Observer",
    chromatically_adapt: Boolean = False,
    convert_kwargs: Optional[Dict] = None,
    **kwargs: Any,
) -> Tuple[plt.Figure, plt.Axes]:
    """
    Plot given *RGB* colourspace array in a scatter plot.

    Parameters
    ----------
    RGB
        *RGB* colourspace array.
    colourspace
        *RGB* colourspace of the *RGB* array. ``colourspace`` can be of any
        type or form supported by the
        :func:`colour.plotting.filter_RGB_colourspaces` definition.
    reference_colourspace
        Reference colourspace model to plot the gamuts into, see
        :attr:`colour.COLOURSPACE_MODELS` attribute for the list of supported
        colourspace models.
    colourspaces
        *RGB* colourspaces to plot the gamuts. ``colourspaces`` elements
        can be of any type or form supported by the
        :func:`colour.plotting.filter_RGB_colourspaces` definition.
    segments
        Edge segments count for each *RGB* colourspace cubes.
    show_grid
        Whether to show a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments
        Edge segments count for the grid.
    show_spectral_locus
        Whether to show the spectral locus.
    spectral_locus_colour
        Spectral locus colour.
    points_size
        Scatter points size.
    cmfs
        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.
    chromatically_adapt
        Whether to chromatically adapt the *RGB* colourspaces given in
        ``colourspaces`` to the whitepoint of the default plotting colourspace.
    convert_kwargs
        Keyword arguments for the :func:`colour.convert` definition.

    Other Parameters
    ----------------
    kwargs
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.plot_RGB_colourspaces_gamuts`},
        See the documentation of the previously listed definitions.

    Returns
    -------
    :class:`tuple`
        Current figure and axes.

    Examples
    --------
    >>> RGB = np.random.random((128, 128, 3))
    >>> plot_RGB_scatter(RGB, 'ITU-R BT.709')  # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...Axes3DSubplot...>)

    .. image:: ../_static/Plotting_Plot_RGB_Scatter.png
        :align: center
        :alt: plot_RGB_scatter
    """

    colourspace = cast(
        RGB_Colourspace,
        first_item(filter_RGB_colourspaces(colourspace).values()),
    )
    colourspaces = cast(List[str], optional(colourspaces, [colourspace.name]))

    convert_kwargs = optional(convert_kwargs, {})

    count_c = len(colourspaces)
    settings = Structure(
        **{
            "face_colours": [None] * count_c,
            "edge_colours": [(0.25, 0.25, 0.25)] * count_c,
            "face_alpha": [0.0] * count_c,
            "edge_alpha": [0.1] * count_c,
        })
    settings.update(kwargs)
    settings["standalone"] = False

    plot_RGB_colourspaces_gamuts(
        colourspaces=colourspaces,
        reference_colourspace=reference_colourspace,
        segments=segments,
        show_grid=show_grid,
        grid_segments=grid_segments,
        show_spectral_locus=show_spectral_locus,
        spectral_locus_colour=spectral_locus_colour,
        cmfs=cmfs,
        chromatically_adapt=chromatically_adapt,
        **settings,
    )

    XYZ = RGB_to_XYZ(
        RGB,
        colourspace.whitepoint,
        colourspace.whitepoint,
        colourspace.matrix_RGB_to_XYZ,
    )

    convert_settings = {"illuminant": colourspace.whitepoint}
    convert_settings.update(convert_kwargs)

    points = colourspace_model_axis_reorder(
        convert(XYZ, "CIE XYZ", reference_colourspace, **convert_settings),
        reference_colourspace,
    )

    axes = plt.gca()
    axes.scatter(
        points[..., 0],
        points[..., 1],
        points[..., 2],
        color=np.reshape(RGB, (-1, 3)),
        s=points_size,
        zorder=CONSTANTS_COLOUR_STYLE.zorder.midground_scatter,
    )

    settings.update({"axes": axes, "standalone": True})
    settings.update(kwargs)

    return render(**settings)
Exemplo n.º 29
0
def plot_RGB_colourspaces_gamuts(
    colourspaces: Union[RGB_Colourspace, str, Sequence[Union[RGB_Colourspace,
                                                             str]]],
    reference_colourspace: Union[Literal["CAM02LCD", "CAM02SCD", "CAM02UCS",
                                         "CAM16LCD", "CAM16SCD", "CAM16UCS",
                                         "CIE XYZ", "CIE xyY", "CIE Lab",
                                         "CIE Luv", "CIE UCS", "CIE UVW",
                                         "DIN99", "Hunter Lab", "Hunter Rdab",
                                         "ICaCb", "ICtCp", "IPT", "IgPgTg",
                                         "Jzazbz", "OSA UCS", "Oklab",
                                         "hdr-CIELAB", "hdr-IPT", ],
                                 str, ] = "CIE xyY",
    segments: Integer = 8,
    show_grid: Boolean = True,
    grid_segments: Integer = 10,
    show_spectral_locus: Boolean = False,
    spectral_locus_colour: Optional[Union[ArrayLike, str]] = None,
    cmfs: Union[MultiSpectralDistributions, str, Sequence[Union[
        MultiSpectralDistributions,
        str]], ] = "CIE 1931 2 Degree Standard Observer",
    chromatically_adapt: Boolean = False,
    convert_kwargs: Optional[Dict] = None,
    **kwargs: Any,
) -> Tuple[plt.Figure, plt.Axes]:
    """
    Plot given *RGB* colourspaces gamuts in given reference colourspace.

    Parameters
    ----------
    colourspaces
        *RGB* colourspaces to plot the gamuts. ``colourspaces`` elements
        can be of any type or form supported by the
        :func:`colour.plotting.filter_RGB_colourspaces` definition.
    reference_colourspace
        Reference colourspace model to plot the gamuts into, see
        :attr:`colour.COLOURSPACE_MODELS` attribute for the list of supported
        colourspace models.
    segments
        Edge segments count for each *RGB* colourspace cubes.
    show_grid
        Whether to show a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments
        Edge segments count for the grid.
    show_spectral_locus
        Whether to show the spectral locus.
    spectral_locus_colour
        Spectral locus colour.
    cmfs
        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.
    chromatically_adapt
        Whether to chromatically adapt the *RGB* colourspaces given in
        ``colourspaces`` to the whitepoint of the default plotting colourspace.
    convert_kwargs
        Keyword arguments for the :func:`colour.convert` definition.

    Other Parameters
    ----------------
    edge_colours
        Edge colours array such as `edge_colours = (None, (0.5, 0.5, 1.0))`.
    edge_alpha
        Edge opacity value such as `edge_alpha = (0.0, 1.0)`.
    face_alpha
        Face opacity value such as `face_alpha = (0.5, 1.0)`.
    face_colours
        Face colours array such as `face_colours = (None, (0.5, 0.5, 1.0))`.
    kwargs
        {:func:`colour.plotting.artist`,
        :func:`colour.plotting.volume.nadir_grid`},
        See the documentation of the previously listed definitions.

    Returns
    -------
    :class:`tuple`
        Current figure and axes.

    Examples
    --------
    >>> plot_RGB_colourspaces_gamuts(['ITU-R BT.709', 'ACEScg', 'S-Gamut'])
    ... # doctest: +ELLIPSIS
    (<Figure size ... with 1 Axes>, <...Axes3DSubplot...>)

    .. image:: ../_static/Plotting_Plot_RGB_Colourspaces_Gamuts.png
        :align: center
        :alt: plot_RGB_colourspaces_gamuts
    """

    colourspaces = cast(
        List[RGB_Colourspace],
        list(filter_RGB_colourspaces(colourspaces).values()),
    )

    convert_kwargs = optional(convert_kwargs, {})

    count_c = len(colourspaces)

    title = (
        f"{', '.join([colourspace.name for colourspace in colourspaces])} "
        f"- {reference_colourspace} Reference Colourspace")

    illuminant = CONSTANTS_COLOUR_STYLE.colour.colourspace.whitepoint

    convert_settings = {"illuminant": illuminant}
    convert_settings.update(convert_kwargs)

    settings = Structure(
        **{
            "face_colours": [None] * count_c,
            "edge_colours": [None] * count_c,
            "face_alpha": [1] * count_c,
            "edge_alpha": [1] * count_c,
            "title": title,
        })
    settings.update(kwargs)

    figure = plt.figure()
    axes = figure.add_subplot(111, projection="3d")

    points = zeros((4, 3))
    if show_spectral_locus:
        cmfs = cast(MultiSpectralDistributions,
                    first_item(filter_cmfs(cmfs).values()))
        XYZ = cmfs.values

        points = colourspace_model_axis_reorder(
            convert(XYZ, "CIE XYZ", reference_colourspace, **convert_settings),
            reference_colourspace,
        )

        points[np.isnan(points)] = 0

        c = ((0.0, 0.0, 0.0,
              0.5) if spectral_locus_colour is None else spectral_locus_colour)

        axes.plot(
            points[..., 0],
            points[..., 1],
            points[..., 2],
            color=c,
            zorder=CONSTANTS_COLOUR_STYLE.zorder.midground_line,
        )
        axes.plot(
            (points[-1][0], points[0][0]),
            (points[-1][1], points[0][1]),
            (points[-1][2], points[0][2]),
            color=c,
            zorder=CONSTANTS_COLOUR_STYLE.zorder.midground_line,
        )

    plotting_colourspace = CONSTANTS_COLOUR_STYLE.colour.colourspace

    quads_c: List = []
    RGB_cf: List = []
    RGB_ce: List = []
    for i, colourspace in enumerate(colourspaces):

        if chromatically_adapt and not np.array_equal(
                colourspace.whitepoint, plotting_colourspace.whitepoint):
            colourspace = colourspace.chromatically_adapt(
                plotting_colourspace.whitepoint,
                plotting_colourspace.whitepoint_name,
            )

        quads_cb, RGB = RGB_identity_cube(
            width_segments=segments,
            height_segments=segments,
            depth_segments=segments,
        )

        XYZ = RGB_to_XYZ(
            quads_cb,
            colourspace.whitepoint,
            colourspace.whitepoint,
            colourspace.matrix_RGB_to_XYZ,
        )

        convert_settings = {"illuminant": colourspace.whitepoint}
        convert_settings.update(convert_kwargs)

        quads_c.extend(
            colourspace_model_axis_reorder(
                convert(XYZ, "CIE XYZ", reference_colourspace,
                        **convert_settings),
                reference_colourspace,
            ))

        if settings.face_colours[i] is not None:
            RGB = ones(RGB.shape) * settings.face_colours[i]

        RGB_cf.extend(
            np.hstack([RGB,
                       full((RGB.shape[0], 1), settings.face_alpha[i])]))

        if settings.edge_colours[i] is not None:
            RGB = ones(RGB.shape) * settings.edge_colours[i]

        RGB_ce.extend(
            np.hstack([RGB,
                       full((RGB.shape[0], 1), settings.edge_alpha[i])]))

    quads = as_float_array(quads_c)
    RGB_f = as_float_array(RGB_cf)
    RGB_e = as_float_array(RGB_ce)

    quads[np.isnan(quads)] = 0

    if quads.size != 0:
        for i, axis in enumerate("xyz"):
            min_a = np.minimum(np.min(quads[..., i]), np.min(points[..., i]))
            max_a = np.maximum(np.max(quads[..., i]), np.max(points[..., i]))
            getattr(axes, f"set_{axis}lim")((min_a, max_a))

    labels = np.array(
        COLOURSPACE_MODELS_AXIS_LABELS[reference_colourspace])[as_int_array(
            colourspace_model_axis_reorder([0, 1, 2], reference_colourspace))]
    for i, axis in enumerate("xyz"):
        getattr(axes, f"set_{axis}label")(labels[i])

    if show_grid:
        limits = np.array([[-1.5, 1.5], [-1.5, 1.5]])

        quads_g, RGB_gf, RGB_ge = nadir_grid(limits, grid_segments, labels,
                                             axes, **settings)
        quads = np.vstack([quads_g, quads])
        RGB_f = np.vstack([RGB_gf, RGB_f])
        RGB_e = np.vstack([RGB_ge, RGB_e])

    collection = Poly3DCollection(quads)
    collection.set_facecolors(RGB_f)
    collection.set_edgecolors(RGB_e)

    axes.add_collection3d(collection)

    settings.update({
        "axes": axes,
        "axes_visible": False,
        "camera_aspect": "equal"
    })
    settings.update(kwargs)

    return render(**settings)
Exemplo n.º 30
0
def RGB_scatter_plot(RGB,
                     colourspace,
                     reference_colourspace='CIE xyY',
                     colourspaces=None,
                     segments=8,
                     display_grid=True,
                     grid_segments=10,
                     spectral_locus=False,
                     spectral_locus_colour=None,
                     points_size=12,
                     cmfs='CIE 1931 2 Degree Standard Observer',
                     **kwargs):
    """
    Plots given *RGB* colourspace array in a scatter plot.

    Parameters
    ----------
    RGB : array_like
        *RGB* colourspace array.
    colourspace : RGB_Colourspace
        *RGB* colourspace of the *RGB* array.
    reference_colourspace : unicode, optional
        **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW',
        'IPT', 'Hunter Lab', 'Hunter Rdab'}**,
        Reference colourspace for colour conversion.
    colourspaces : array_like, optional
        *RGB* colourspaces to plot the gamuts.
    segments : int, optional
        Edge segments count for each *RGB* colourspace cubes.
    display_grid : bool, optional
        Display a grid at the bottom of the *RGB* colourspace cubes.
    grid_segments : bool, optional
        Edge segments count for the grid.
    spectral_locus : bool, optional
        Is spectral locus line plotted.
    spectral_locus_colour : array_like, optional
        Spectral locus line colour.
    points_size : numeric, optional
        Scatter points size.
    cmfs : unicode, optional
        Standard observer colour matching functions used for spectral locus.

    Other Parameters
    ----------------
    \**kwargs : dict, optional
        {:func:`RGB_colourspaces_gamuts_plot`},
        Please refer to the documentation of the previously listed definitions.

    Returns
    -------
    Figure
        Current figure or None.

    Examples
    --------
    >>> c = 'Rec. 709'
    >>> RGB_scatter_plot(c)  # doctest: +SKIP
    """

    colourspace = get_RGB_colourspace(colourspace)

    if colourspaces is None:
        colourspaces = (colourspace.name, )

    count_c = len(colourspaces)
    settings = Structure(
        **{
            'face_colours': [None] * count_c,
            'edge_colours': [(0.25, 0.25, 0.25)] * count_c,
            'face_alpha': [0.0] * count_c,
            'edge_alpha': [0.1] * count_c,
            'standalone': False
        })
    settings.update(kwargs)

    RGB_colourspaces_gamuts_plot(colourspaces=colourspaces,
                                 reference_colourspace=reference_colourspace,
                                 segments=segments,
                                 display_grid=display_grid,
                                 grid_segments=grid_segments,
                                 spectral_locus=spectral_locus,
                                 spectral_locus_colour=spectral_locus_colour,
                                 cmfs=cmfs,
                                 **settings)

    XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint,
                     colourspace.RGB_to_XYZ_matrix)

    points = common_colourspace_model_axis_reorder(
        XYZ_to_colourspace_model(XYZ, colourspace.whitepoint,
                                 reference_colourspace), reference_colourspace)

    axes = matplotlib.pyplot.gca()
    axes.scatter(points[..., 0],
                 points[..., 1],
                 points[..., 2],
                 color=np.reshape(RGB, (-1, 3)),
                 s=points_size)

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

    camera(**settings)
    decorate(**settings)

    return display(**settings)