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)
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)
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)
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))
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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))
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)
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)
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)
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)
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)
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)
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)
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)
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)