def test_filter_RGB_colourspaces(self): """ Test :func:`colour.plotting.common.filter_RGB_colourspaces` definition. """ self.assertListEqual( sorted(colourspace.name for colourspace in filter_RGB_colourspaces( ["^ACES.*"]).values()), ["ACES2065-1", "ACEScc", "ACEScct", "ACEScg", "ACESproxy"], )
def test_filter_RGB_colourspaces(self): """ Tests :func:`colour.plotting.common.filter_RGB_colourspaces` definition. """ self.assertListEqual( sorted([ colourspace.name for colourspace in filter_RGB_colourspaces( ['^ACES.*']).values() ]), ['ACES2065-1', 'ACEScc', 'ACEScct', 'ACEScg', 'ACESproxy'])
def RGB_colourspace_volume_visual(colourspace=PRIMARY_COLOURSPACE, colourspace_model=COLOURSPACE_MODEL, segments=16, wireframe=False): """ Returns a RGB colourspace volume visual geometry formatted as *JSON*. Parameters ---------- colourspace : unicode, optional RGB colourspace used to generate the visual geometry. colourspace_model : unicode, optional Colourspace model used to generate the visual geometry. segments : int, optional Segments count per side of the *box* used to generate the visual geometry. wireframe : bool, optional Whether the visual geometry must represent a wireframe visual. Returns ------- unicode RGB colourspace volume visual geometry formatted as *JSON*. """ colourspace = first_item( filter_RGB_colourspaces(re.escape(colourspace)).values()) cube = conform_primitive_dtype( primitive_cube(width_segments=segments, height_segments=segments, depth_segments=segments)) vertices = cube[0]['position'] + 0.5 faces = colourspace_model_faces_reorder(np.reshape(cube[1], (-1, 1)), colourspace_model) RGB = cube[0]['colour'] XYZ = RGB_to_XYZ( vertices, colourspace.whitepoint, colourspace.whitepoint, colourspace.matrix_RGB_to_XYZ, ) vertices = colourspace_model_axis_reorder( XYZ_to_colourspace_model( XYZ, colourspace.whitepoint, colourspace_model, ), colourspace_model) return buffer_geometry(position=vertices, color=RGB, index=faces)
def RGB_colourspace_triangle_visual(colourspace='ITU-R BT.709', diagram='CIE 1931', uniform_colour=None, uniform_opacity=1.0, width=4.0, parent=None): """ Returns a :class:`vispy.scene.visuals.Line` class instance representing a *RGB* colourspace triangle visual. Parameters ---------- colourspace : unicode, optional See :func:`RGB_colourspace_volume_visual` argument for possible values. :class:`colour.RGB_Colourspace` class instance name defining the *RGB* colourspace triangle to draw. diagram : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, Chromaticity diagram to use. uniform_colour : array_like, optional Uniform triangle colour. uniform_opacity : numeric, optional Uniform mesh opacity. width : numeric, optional Triangle edge width. parent : Node, optional Parent of the *RGB* colourspace volume visual in the `SceneGraph`. """ if uniform_colour is None: uniform_colour = (0.8, 0.8, 0.8) colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) illuminant = DEFAULT_PLOTTING_ILLUMINANT XYZ_to_ij = CHROMATICITY_DIAGRAM_TRANSFORMATIONS[diagram]['XYZ_to_ij'] ij = XYZ_to_ij(xy_to_XYZ(colourspace.primaries), illuminant) # TODO: Remove following hack dealing with 'agg' method issues. ij = np.vstack([ij[-1, ...], ij, ij[0, ...]]) ij[np.isnan(ij)] = 0 RGB = np.hstack([uniform_colour, uniform_opacity]) line = Line(ij, RGB, width=width, method='agg', parent=parent) return line
def RGB_colourspace_whitepoint_axis_visual(colourspace='ITU-R BT.709', reference_colourspace='CIE xyY', width=2.0, method='gl', parent=None): """ Returns a :class:`vispy.scene.visuals.Line` class instance representing a given RGB colourspace whitepoint axis. Parameters ---------- colourspace : unicode, optional See :func:`RGB_colourspace_volume_visual` argument for possible values. :class:`colour.RGB_Colourspace` class instance name defining the *RGB* colourspace whitepoint axis to draw. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace to use for colour conversions / transformations. width : numeric, optional Line width. method : unicode, optional **{'gl', 'agg'}**, Line drawing method. parent : Node, optional Parent of the spectral locus visual in the `SceneGraph`. Returns ------- Line RGB colourspace whitepoint axis. """ colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) XYZ_o = xy_to_XYZ(colourspace.whitepoint + (0, )) XYZ_f = xy_to_XYZ(colourspace.whitepoint + (1.1, )) XYZ_l = np.vstack([XYZ_o, XYZ_f]) illuminant = DEFAULT_PLOTTING_ILLUMINANT points = common_colourspace_model_axis_reorder( XYZ_to_colourspace_model(XYZ_l, illuminant, reference_colourspace), reference_colourspace) line = Line(points, (1, 1, 1), width=width, method=method, parent=parent) return line
def spectral_locus_visual(colourspace=PRIMARY_COLOURSPACE, colourspace_model=COLOURSPACE_MODEL, cmfs='CIE 1931 2 Degree Standard Observer'): """ Returns the spectral locus visual geometry formatted as *JSON*. Parameters ---------- colourspace : unicode, optional RGB colourspace used to generate the visual geometry. colourspace_model : unicode, optional Colourspace model used to generate the visual geometry. cmfs : unicode, optional Standard observer colour matching functions used to draw the spectral locus. Returns ------- unicode Spectral locus visual geometry formatted as *JSON*. """ colourspace = first_item( filter_RGB_colourspaces(re.escape(colourspace)).values()) cmfs = first_item(filter_cmfs(cmfs).values()) XYZ = cmfs.values XYZ = np.vstack([XYZ, XYZ[0, ...]]) vertices = colourspace_model_axis_reorder( XYZ_to_colourspace_model( XYZ, colourspace.whitepoint, colourspace_model, ), colourspace_model) RGB = normalise_maximum(XYZ_to_RGB( XYZ, colourspace.whitepoint, colourspace.whitepoint, colourspace.matrix_XYZ_to_RGB, ), axis=-1) return buffer_geometry(position=vertices, color=RGB)
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_colourspace_volume_visual(colourspace='ITU-R BT.709', reference_colourspace='CIE xyY', segments=16, uniform_colour=None, uniform_opacity=0.5, wireframe=True, wireframe_colour=None, wireframe_opacity=1.0, parent=None): """ Returns a :class:`vispy.scene.visuals.Node` class instance with one or two :class:`colour_analysis.visuals.Box` class instance children representing a *RGB* colourspace volume visual. Parameters ---------- colourspace : unicode, optional **{'ITU-R BT.709', 'ACES2065-1', 'ACEScc', 'ACEScg', 'ACESproxy', 'ALEXA Wide Gamut', 'Adobe RGB (1998)', 'Adobe Wide Gamut RGB', 'Apple RGB', 'Best RGB', 'Beta RGB', 'CIE RGB', 'Cinema Gamut', 'ColorMatch RGB', 'DCI-P3', 'DCI-P3+', 'DRAGONcolor', 'DRAGONcolor2', 'Don RGB 4', 'ECI RGB v2', 'ERIMM RGB', 'Ekta Space PS 5', 'Max RGB', 'NTSC', 'Pal/Secam', 'ProPhoto RGB', 'REDcolor', 'REDcolor2', 'REDcolor3', 'REDcolor4', 'RIMM RGB', 'ROMM RGB', 'ITU-R BT.2020', 'Russell RGB', 'S-Gamut', 'S-Gamut3', 'S-Gamut3.Cine', 'SMPTE-C RGB', 'V-Gamut', 'Xtreme RGB', 'sRGB'}**, :class:`colour.RGB_Colourspace` class instance name defining the *RGB* colourspace volume to draw. reference_colourspace : unicode **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace to convert the *CIE XYZ* tristimulus values to. segments : int, optional Box segments. uniform_colour : array_like, optional Uniform mesh colour. uniform_opacity : numeric, optional Uniform mesh opacity. wireframe : bool, optional Use wireframe display. Uniform mesh opacity. wireframe_colour : array_like, optional Wireframe mesh colour. wireframe_opacity : numeric, optional Wireframe mesh opacity. parent : Node, optional Parent of the *RGB* colourspace volume visual in the `SceneGraph`. """ node = Node(parent) colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) RGB_cube_f = RGB_identity_cube(width_segments=segments, height_segments=segments, depth_segments=segments, uniform_colour=uniform_colour, uniform_opacity=uniform_opacity, vertex_colours=not uniform_colour, parent=node) vertices = RGB_cube_f.mesh_data.get_vertices() XYZ = RGB_to_XYZ(vertices, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) value = common_colourspace_model_axis_reorder( XYZ_to_colourspace_model(XYZ, colourspace.whitepoint, reference_colourspace), reference_colourspace) value[np.isnan(value)] = 0 RGB_cube_f.mesh_data.set_vertices(value) if wireframe: RGB_cube_w = RGB_identity_cube(width_segments=segments, height_segments=segments, depth_segments=segments, uniform_colour=wireframe_colour, uniform_opacity=wireframe_opacity, vertex_colours=not wireframe_colour, wireframe=True, parent=node) RGB_cube_w.mesh_data.set_vertices(value) return node
def RGB_scatter_visual(RGB, colourspace='ITU-R BT.709', reference_colourspace='CIE xyY', symbol='disc', size=4.0, edge_size=0.5, uniform_colour=None, uniform_opacity=1.0, uniform_edge_colour=None, uniform_edge_opacity=1.0, resampling='auto', parent=None): """ Returns a :class:`vispy.scene.visuals.Symbol` class instance representing *RGB* data using given symbols. Parameters ---------- RGB : array_like *RGB* data to draw. colourspace : unicode, optional **{'ITU-R BT.709', 'ACES2065-1', 'ACEScc', 'ACEScg', 'ACESproxy', 'ALEXA Wide Gamut', 'Adobe RGB (1998)', 'Adobe Wide Gamut RGB', 'Apple RGB', 'Best RGB', 'Beta RGB', 'CIE RGB', 'Cinema Gamut', 'ColorMatch RGB', 'DCI-P3', 'DCI-P3+', 'DRAGONcolor', 'DRAGONcolor2', 'Don RGB 4', 'ECI RGB v2', 'ERIMM RGB', 'Ekta Space PS 5', 'Max RGB', 'NTSC', 'Pal/Secam', 'ProPhoto RGB', 'REDcolor', 'REDcolor2', 'REDcolor3', 'REDcolor4', 'RIMM RGB', 'ROMM RGB', 'ITU-R BT.2020', 'Russell RGB', 'S-Gamut', 'S-Gamut3', 'S-Gamut3.Cine', 'SMPTE-C RGB', 'V-Gamut', 'Xtreme RGB', 'sRGB'}**, :class:`colour.RGB_Colourspace` class instance name defining the *RGB* colourspace of the data to draw. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace to use for colour conversions / transformations. symbol : unicode, optional Symbol type to draw. size : numeric, optional Symbol size. edge_size : numeric, optional Symbol edge size. uniform_colour : array_like, optional Uniform symbol colour. uniform_opacity : numeric, optional Uniform symbol opacity. uniform_edge_colour : array_like, optional Uniform symbol edge colour. uniform_edge_opacity : numeric, optional Uniform symbol edge opacity. resampling : numeric or unicode, optional Resampling value, if numeric input, one pixel every `resampling` argument value will be kept. parent : Node, optional Parent of the *RGB* scatter visual in the `SceneGraph`. Returns ------- Symbol *RGB* scatter visual. """ colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) RGB = np.asarray(RGB) if resampling == 'auto': resampling = max(int((0.0078125 * np.average(RGB.shape[0:1])) // 2), 1) RGB = RGB[::resampling, ::resampling].reshape([-1, 3]) 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) points[np.isnan(points)] = 0 RGB = np.clip(RGB, 0, 1) if uniform_colour is None: RGB = np.hstack([RGB, np.full((RGB.shape[0], 1), uniform_opacity, DEFAULT_FLOAT_DTYPE)]) else: RGB = ColorArray(uniform_colour, alpha=uniform_opacity).rgba if uniform_edge_colour is None: RGB_e = RGB else: RGB_e = ColorArray( uniform_edge_colour, alpha=uniform_edge_opacity).rgba markers = Symbol( symbol=symbol, positions=points, size=size, edge_size=edge_size, face_colour=RGB, edge_colour=RGB_e, parent=parent) return markers
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 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_chromaticities_in_chromaticity_diagram( RGB, colourspace='sRGB', chromaticity_diagram_callable=( plot_RGB_colourspaces_in_chromaticity_diagram), method='CIE 1931', scatter_parameters=None, **kwargs): """ Plots given *RGB* colourspace array in the *Chromaticity Diagram* according to given method. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : optional, unicode *RGB* colourspace of the *RGB* array. chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. scatter_parameters : dict, optional Parameters for the :func:`plt.scatter` definition, if ``c`` is set to *RGB*, the scatter will use given ``RGB`` colours. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> RGB = np.random.random((128, 128, 3)) >>> plot_RGB_chromaticities_in_chromaticity_diagram( ... RGB, 'ITU-R BT.709') ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Chromaticities_In_Chromaticity_Diagram_Plot.png :align: center :alt: plot_RGB_chromaticities_in_chromaticity_diagram """ RGB = as_float_array(RGB).reshape(-1, 3) settings = {'uniform': True} settings.update(kwargs) figure, axes = artist(**settings) method = method.upper() scatter_settings = { 's': 40, 'c': 'RGB', 'marker': 'o', 'alpha': 0.85, } if scatter_parameters is not None: scatter_settings.update(scatter_parameters) settings = dict(kwargs) settings.update({'axes': axes, 'standalone': False}) colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) settings['colourspaces'] = (['^{0}$'.format(colourspace.name)] + settings.get('colourspaces', [])) chromaticity_diagram_callable(**settings) use_RGB_colours = scatter_settings['c'].upper() == 'RGB' if use_RGB_colours: RGB = RGB[RGB[:, 1].argsort()] scatter_settings['c'] = np.clip( RGB_to_RGB(RGB, colourspace, COLOUR_STYLE_CONSTANTS.colour.colourspace, apply_encoding_cctf=True).reshape(-1, 3), 0, 1) XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) if method == 'CIE 1931': ij = XYZ_to_xy(XYZ, colourspace.whitepoint) elif method == 'CIE 1960 UCS': ij = UCS_to_uv(XYZ_to_UCS(XYZ)) elif method == 'CIE 1976 UCS': ij = Luv_to_uv(XYZ_to_Luv(XYZ, colourspace.whitepoint), colourspace.whitepoint) axes.scatter(ij[..., 0], ij[..., 1], **scatter_settings) settings.update({'standalone': True}) settings.update(kwargs) return render(**settings)
def RGB_scatter_visual(RGB, colourspace='ITU-R BT.709', reference_colourspace='CIE xyY', symbol='disc', size=4.0, edge_size=0.5, uniform_colour=None, uniform_opacity=1.0, uniform_edge_colour=None, uniform_edge_opacity=1.0, resampling='auto', parent=None): """ Returns a :class:`vispy.scene.visuals.Symbol` class instance representing *RGB* data using given symbols. Parameters ---------- RGB : array_like *RGB* data to draw. colourspace : unicode, optional **{'ITU-R BT.709', 'ACES2065-1', 'ACEScc', 'ACEScg', 'ACESproxy', 'ALEXA Wide Gamut', 'Adobe RGB (1998)', 'Adobe Wide Gamut RGB', 'Apple RGB', 'Best RGB', 'Beta RGB', 'CIE RGB', 'Cinema Gamut', 'ColorMatch RGB', 'DCI-P3', 'DCI-P3+', 'DRAGONcolor', 'DRAGONcolor2', 'Don RGB 4', 'ECI RGB v2', 'ERIMM RGB', 'Ekta Space PS 5', 'Max RGB', 'NTSC', 'Pal/Secam', 'ProPhoto RGB', 'REDcolor', 'REDcolor2', 'REDcolor3', 'REDcolor4', 'RIMM RGB', 'ROMM RGB', 'ITU-R BT.2020', 'Russell RGB', 'S-Gamut', 'S-Gamut3', 'S-Gamut3.Cine', 'SMPTE-C RGB', 'V-Gamut', 'Xtreme RGB', 'sRGB'}**, :class:`colour.RGB_Colourspace` class instance name defining the *RGB* colourspace of the data to draw. reference_colourspace : unicode, optional **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace to use for colour conversions / transformations. symbol : unicode, optional Symbol type to draw. size : numeric, optional Symbol size. edge_size : numeric, optional Symbol edge size. uniform_colour : array_like, optional Uniform symbol colour. uniform_opacity : numeric, optional Uniform symbol opacity. uniform_edge_colour : array_like, optional Uniform symbol edge colour. uniform_edge_opacity : numeric, optional Uniform symbol edge opacity. resampling : numeric or unicode, optional Resampling value, if numeric input, one pixel every `resampling` argument value will be kept. parent : Node, optional Parent of the *RGB* scatter visual in the `SceneGraph`. Returns ------- Symbol *RGB* scatter visual. """ colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) RGB = np.asarray(RGB) if resampling == 'auto': resampling = max(int((0.0078125 * np.average(RGB.shape[0:1])) // 2), 1) RGB = RGB[::resampling, ::resampling].reshape([-1, 3]) 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) points[np.isnan(points)] = 0 RGB = np.clip(RGB, 0, 1) if uniform_colour is None: RGB = np.hstack([ RGB, np.full((RGB.shape[0], 1), uniform_opacity, DEFAULT_FLOAT_DTYPE) ]) else: RGB = ColorArray(uniform_colour, alpha=uniform_opacity).rgba if uniform_edge_colour is None: RGB_e = RGB else: RGB_e = ColorArray(uniform_edge_colour, alpha=uniform_edge_opacity).rgba markers = Symbol(symbol=symbol, positions=points, size=size, edge_size=edge_size, face_colour=RGB, edge_colour=RGB_e, parent=parent) return markers
from colormath.color_objects import LabColor, sRGBColor from colour.models import (RGB_to_HSL, RGB_to_HSV, RGB_to_XYZ, XYZ_to_Lab, XYZ_to_RGB, XYZ_to_xy) from colour.plotting import filter_RGB_colourspaces from colour.utilities import first_item from comet_ml import Optimizer from lightgbm import LGBMRegressor from six.moves import zip from sklearn.metrics.scorer import make_scorer from sklearn.model_selection import cross_val_score, train_test_split from sklearn.multioutput import MultiOutputRegressor from sklearn.preprocessing import StandardScaler from ..utils.descriptornames import * # pylint:disable=unused-wildcard-import colourspace = first_item(filter_RGB_colourspaces('sRGB').values()) def get_delta_e(rgba, rgbb): color1_rgb = sRGBColor(rgba[0], rgba[1], rgba[2]) color2_rgb = sRGBColor(rgbb[0], rgbb[1], rgbb[2]) # Convert from RGB to Lab Color Space color1_lab = convert_color(color1_rgb, LabColor) # Convert from RGB to Lab Color Space color2_lab = convert_color(color2_rgb, LabColor) # Find the color difference delta_e = delta_e_cie2000(color1_lab, color2_lab)
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 image_data(path, primary_colourspace=PRIMARY_COLOURSPACE, secondary_colourspace=SECONDARY_COLOURSPACE, image_colourspace=IMAGE_COLOURSPACE, image_decoding_cctf=IMAGE_DECODING_CCTF, out_of_primary_colourspace_gamut=False, out_of_secondary_colourspace_gamut=False, out_of_pointer_gamut=False, saturate=False): """ Returns given image RGB data or its out of gamut values formatted as *JSON*. Parameters ---------- path : unicode Server side path of the image to read. primary_colourspace : unicode, optional Primary RGB colourspace used to generate out of gamut values. secondary_colourspace: unicode, optional Secondary RGB colourspace used to generate out of gamut values. image_colourspace: unicode, optional **{'Primary', 'Secondary'}**, Analysed image RGB colourspace. image_decoding_cctf : unicode, optional Analysed image decoding colour component transfer function (Decoding CCTF) / electro-optical transfer function (EOTF / EOCF) that maps an :math:`R'G'B'` video component signal value to tristimulus values at the display. out_of_primary_colourspace_gamut : bool, optional Whether to only generate the out of primary RGB colourspace gamut values. out_of_secondary_colourspace_gamut : bool, optional Whether to only generate the out of secondary RGB colourspace gamut values. out_of_pointer_gamut : bool, optional Whether to only generate the out of *Pointer's Gamut* values. saturate : bool, optional Whether to clip the image in domain [0, 1]. Returns ------- unicode RGB image data or its out of gamut values formatted as *JSON*. """ primary_colourspace = first_item( filter_RGB_colourspaces('^{0}$'.format( re.escape(primary_colourspace)))) secondary_colourspace = first_item( filter_RGB_colourspaces('^{0}$'.format( re.escape(secondary_colourspace)))) colourspace = (primary_colourspace if image_colourspace == 'Primary' else secondary_colourspace) RGB = load_image(path, image_decoding_cctf) if saturate: RGB = np.clip(RGB, 0, 1) if out_of_primary_colourspace_gamut: if image_colourspace == 'Secondary': RGB = RGB_to_RGB(RGB, secondary_colourspace, primary_colourspace) RGB[np.logical_and(RGB >= 0, RGB <= 1)] = 0 RGB[RGB != 0] = 1 RGB[np.any(RGB == 1, axis=-1)] = 1 if out_of_secondary_colourspace_gamut: if image_colourspace == 'Primary': RGB = RGB_to_RGB(RGB, primary_colourspace, secondary_colourspace) RGB[np.logical_and(RGB >= 0, RGB <= 1)] = 0 RGB[RGB != 0] = 1 RGB[np.any(RGB == 1, axis=-1)] = 1 if out_of_pointer_gamut: O_PG = is_within_pointer_gamut( RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix)).astype(np.int_) O_PG = 1 - O_PG RGB[O_PG != 1] = 0 RGB[O_PG == 1] = 1 shape = RGB.shape RGB = np.ravel(RGB[..., 0:3].reshape(-1, 3)) RGB = np.around(RGB, np.finfo(COLOUR_DTYPE).precision) return json.dumps({ 'width': shape[1], 'height': shape[0], 'data': RGB.tolist() })
def plot_RGB_chromaticities_in_chromaticity_diagram( RGB, colourspace='sRGB', chromaticity_diagram_callable=( plot_RGB_colourspaces_in_chromaticity_diagram), method='CIE 1931', scatter_parameters=None, **kwargs): """ Plots given *RGB* colourspace array in the *Chromaticity Diagram* according to given method. Parameters ---------- RGB : array_like *RGB* colourspace array. colourspace : optional, unicode *RGB* colourspace of the *RGB* array. chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. scatter_parameters : dict, optional Parameters for the :func:`plt.scatter` definition, if ``c`` is set to *RGB*, the scatter will use given ``RGB`` colours. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.diagrams.\ plot_RGB_colourspaces_in_chromaticity_diagram`, :func:`colour.plotting.render`}, 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_chromaticities_in_chromaticity_diagram( ... RGB, 'ITU-R BT.709') ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Chromaticities_In_Chromaticity_Diagram_Plot.png :align: center :alt: plot_RGB_chromaticities_in_chromaticity_diagram """ RGB = as_float_array(RGB).reshape(-1, 3) settings = {'uniform': True} settings.update(kwargs) _figure, axes = artist(**settings) method = method.upper() scatter_settings = { 's': 40, 'c': 'RGB', 'marker': 'o', 'alpha': 0.85, } if scatter_parameters is not None: scatter_settings.update(scatter_parameters) settings = dict(kwargs) settings.update({'axes': axes, 'standalone': False}) colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) settings['colourspaces'] = ( ['^{0}$'.format(colourspace.name)] + settings.get('colourspaces', [])) chromaticity_diagram_callable(**settings) use_RGB_colours = scatter_settings['c'].upper() == 'RGB' if use_RGB_colours: RGB = RGB[RGB[:, 1].argsort()] scatter_settings['c'] = np.clip( RGB_to_RGB( RGB, colourspace, COLOUR_STYLE_CONSTANTS.colour.colourspace, apply_encoding_cctf=True).reshape(-1, 3), 0, 1) XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) if method == 'CIE 1931': ij = XYZ_to_xy(XYZ, colourspace.whitepoint) elif method == 'CIE 1960 UCS': ij = UCS_to_uv(XYZ_to_UCS(XYZ)) elif method == 'CIE 1976 UCS': ij = Luv_to_uv( XYZ_to_Luv(XYZ, colourspace.whitepoint), colourspace.whitepoint) axes.scatter(ij[..., 0], ij[..., 1], **scatter_settings) settings.update({'standalone': True}) settings.update(kwargs) return render(**settings)
def plot_RGB_colourspaces_in_chromaticity_diagram( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', chromaticity_diagram_callable=plot_chromaticity_diagram, method='CIE 1931', show_whitepoints=True, show_pointer_gamut=False, **kwargs): """ Plots given *RGB* colourspaces in the *Chromaticity Diagram* according to given method. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. show_whitepoints : bool, optional Whether to display the *RGB* colourspaces whitepoints. show_pointer_gamut : bool, optional Whether to display the *Pointer's Gamut*. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.plot_pointer_gamut`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_RGB_colourspaces_in_chromaticity_diagram( ... ['ITU-R BT.709', 'ACEScg', 'S-Gamut']) ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Colourspaces_In_Chromaticity_Diagram.png :align: center :alt: plot_RGB_colourspaces_in_chromaticity_diagram """ if colourspaces is None: colourspaces = ['ITU-R BT.709', 'ACEScg', 'S-Gamut'] colourspaces = filter_RGB_colourspaces(colourspaces).values() settings = {'uniform': True} settings.update(kwargs) _figure, axes = artist(**settings) method = method.upper() cmfs = first_item(filter_cmfs(cmfs).values()) title = '{0}\n{1} - {2} Chromaticity Diagram'.format( ', '.join([colourspace.name for colourspace in colourspaces]), cmfs.name, method) settings = {'axes': axes, 'title': title, 'method': method} settings.update(kwargs) settings['standalone'] = False chromaticity_diagram_callable(**settings) if show_pointer_gamut: settings = {'axes': axes, 'method': method} settings.update(kwargs) settings['standalone'] = False plot_pointer_gamut(**settings) if method == 'CIE 1931': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy x_limit_min, x_limit_max = [-0.1], [0.9] y_limit_min, y_limit_max = [-0.1], [0.9] elif method == 'CIE 1960 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_UCS_uv(xy) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.2], [0.6] elif method == 'CIE 1976 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_Luv_uv(xy) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.1], [0.7] else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}}'.format( method)) settings = {'colour_cycle_count': len(colourspaces)} settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: R, G, B, _A = next(cycle) # RGB colourspaces such as *ACES2065-1* have primaries with # chromaticity coordinates set to 0 thus we prevent nan from being # yield by zero division in later colour transformations. P = np.where( colourspace.primaries == 0, EPSILON, colourspace.primaries, ) P = xy_to_ij(P) W = xy_to_ij(colourspace.whitepoint) axes.plot( (W[0], W[0]), (W[1], W[1]), color=(R, G, B), label=colourspace.name) if show_whitepoints: axes.plot((W[0], W[0]), (W[1], W[1]), 'o', color=(R, G, B)) axes.plot( (P[0, 0], P[1, 0]), (P[0, 1], P[1, 1]), 'o-', color=(R, G, B)) axes.plot( (P[1, 0], P[2, 0]), (P[1, 1], P[2, 1]), 'o-', color=(R, G, B)) axes.plot( (P[2, 0], P[0, 0]), (P[2, 1], P[0, 1]), 'o-', color=(R, G, B)) x_limit_min.append(np.amin(P[..., 0]) - 0.1) y_limit_min.append(np.amin(P[..., 1]) - 0.1) x_limit_max.append(np.amax(P[..., 0]) + 0.1) y_limit_max.append(np.amax(P[..., 1]) + 0.1) bounding_box = ( min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max), ) settings.update({ 'standalone': True, 'legend': True, 'bounding_box': bounding_box, }) settings.update(kwargs) return render(**settings)
def RGB_image_scatter_visual(path, primary_colourspace=PRIMARY_COLOURSPACE, secondary_colourspace=SECONDARY_COLOURSPACE, image_colourspace=IMAGE_COLOURSPACE, image_decoding_cctf=IMAGE_DECODING_CCTF, colourspace_model=COLOURSPACE_MODEL, out_of_primary_colourspace_gamut=False, out_of_secondary_colourspace_gamut=False, out_of_pointer_gamut=False, sub_sampling=25, saturate=False): """ Returns a RGB image scatter visual geometry formatted as *JSON* for given image. Parameters ---------- path : unicode Server side path of the image to read to generate the scatter points. primary_colourspace : unicode, optional Primary RGB colourspace used to generate the visual geometry. secondary_colourspace: unicode, optional Secondary RGB colourspace used to generate the visual geometry. image_colourspace: unicode, optional **{'Primary', 'Secondary'}**, Analysed image RGB colourspace. image_decoding_cctf : unicode, optional Analysed image decoding colour component transfer function (Decoding CCTF) / electro-optical transfer function (EOTF / EOCF) that maps an :math:`R'G'B'` video component signal value to tristimulus values at the display. colourspace_model : unicode, optional Colourspace model used to generate the visual geometry. out_of_primary_colourspace_gamut : bool, optional Whether to only generate the out of primary RGB colourspace gamut visual geometry. out_of_secondary_colourspace_gamut : bool, optional Whether to only generate the out of secondary RGB colourspace gamut visual geometry. out_of_pointer_gamut : bool, optional Whether to only generate the out of *Pointer's Gamut* visual geometry. sub_sampling : int, optional Consider every ``sub_sampling`` pixels of the image to generate the visual geometry. Using a low number will yield a large quantity of points, e.g. *1* yields *2073600* points for a *1080p* image. saturate : bool, optional Whether to clip the image in domain [0, 1]. Returns ------- unicode RGB image scatter visual geometry formatted as *JSON*. """ primary_colourspace = first_item( filter_RGB_colourspaces('^{0}$'.format( re.escape(primary_colourspace)))) secondary_colourspace = first_item( filter_RGB_colourspaces('^{0}$'.format( re.escape(secondary_colourspace)))) colourspace = (primary_colourspace if image_colourspace == 'Primary' else secondary_colourspace) RGB = load_image(path, image_decoding_cctf) if saturate: RGB = np.clip(RGB, 0, 1) RGB = RGB[..., 0:3].reshape(-1, 3)[::sub_sampling] if out_of_primary_colourspace_gamut: RGB_c = np.copy(RGB) if image_colourspace == 'Secondary': RGB_c = RGB_to_RGB(RGB, secondary_colourspace, primary_colourspace) RGB = RGB[np.any(np.logical_or(RGB_c < 0, RGB_c > 1), axis=-1)] if out_of_secondary_colourspace_gamut: RGB_c = np.copy(RGB) if image_colourspace == 'Primary': RGB_c = RGB_to_RGB(RGB, primary_colourspace, secondary_colourspace) RGB = RGB[np.any(np.logical_or(RGB_c < 0, RGB_c > 1), axis=-1)] if out_of_pointer_gamut: O_PG = is_within_pointer_gamut( RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix)).astype(np.int_) O_PG = 1 - O_PG RGB = RGB[O_PG == 1] XYZ = RGB_to_XYZ(RGB, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) vertices = colourspace_model_axis_reorder( XYZ_to_colourspace_model_normalised(XYZ, colourspace.whitepoint, colourspace_model), colourspace_model) if (out_of_primary_colourspace_gamut or out_of_secondary_colourspace_gamut or out_of_pointer_gamut): RGB = np.ones(RGB.shape) return buffer_geometry(position=vertices, color=RGB)
def RGB_colourspace_volume_visual(colourspace='ITU-R BT.709', reference_colourspace='CIE xyY', segments=16, uniform_colour=None, uniform_opacity=0.5, wireframe=True, wireframe_colour=None, wireframe_opacity=1.0, parent=None): """ Returns a :class:`vispy.scene.visuals.Node` class instance with one or two :class:`colour_analysis.visuals.Box` class instance children representing a *RGB* colourspace volume visual. Parameters ---------- colourspace : unicode, optional **{'ITU-R BT.709', 'ACES2065-1', 'ACEScc', 'ACEScg', 'ACESproxy', 'ALEXA Wide Gamut', 'Adobe RGB (1998)', 'Adobe Wide Gamut RGB', 'Apple RGB', 'Best RGB', 'Beta RGB', 'CIE RGB', 'Cinema Gamut', 'ColorMatch RGB', 'DCI-P3', 'DCI-P3+', 'DRAGONcolor', 'DRAGONcolor2', 'Don RGB 4', 'ECI RGB v2', 'ERIMM RGB', 'Ekta Space PS 5', 'Max RGB', 'NTSC', 'Pal/Secam', 'ProPhoto RGB', 'REDcolor', 'REDcolor2', 'REDcolor3', 'REDcolor4', 'RIMM RGB', 'ROMM RGB', 'ITU-R BT.2020', 'Russell RGB', 'S-Gamut', 'S-Gamut3', 'S-Gamut3.Cine', 'SMPTE-C RGB', 'V-Gamut', 'Xtreme RGB', 'sRGB'}**, :class:`colour.RGB_Colourspace` class instance name defining the *RGB* colourspace volume to draw. reference_colourspace : unicode **{'CIE XYZ', 'CIE xyY', 'CIE Lab', 'CIE Luv', 'CIE UCS', 'CIE UVW', 'IPT', 'Hunter Lab', 'Hunter Rdab'}**, Reference colourspace to convert the *CIE XYZ* tristimulus values to. segments : int, optional Box segments. uniform_colour : array_like, optional Uniform mesh colour. uniform_opacity : numeric, optional Uniform mesh opacity. wireframe : bool, optional Use wireframe display. Uniform mesh opacity. wireframe_colour : array_like, optional Wireframe mesh colour. wireframe_opacity : numeric, optional Wireframe mesh opacity. parent : Node, optional Parent of the *RGB* colourspace volume visual in the `SceneGraph`. """ node = Node(parent) colourspace = first_item(filter_RGB_colourspaces(colourspace).values()) RGB_cube_f = RGB_identity_cube( width_segments=segments, height_segments=segments, depth_segments=segments, uniform_colour=uniform_colour, uniform_opacity=uniform_opacity, vertex_colours=not uniform_colour, parent=node) vertices = RGB_cube_f.mesh_data.get_vertices() XYZ = RGB_to_XYZ(vertices, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix) value = common_colourspace_model_axis_reorder( XYZ_to_colourspace_model(XYZ, colourspace.whitepoint, reference_colourspace), reference_colourspace) value[np.isnan(value)] = 0 RGB_cube_f.mesh_data.set_vertices(value) if wireframe: RGB_cube_w = RGB_identity_cube( width_segments=segments, height_segments=segments, depth_segments=segments, uniform_colour=wireframe_colour, uniform_opacity=wireframe_opacity, vertex_colours=not wireframe_colour, wireframe=True, parent=node) RGB_cube_w.mesh_data.set_vertices(value) return node
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_in_chromaticity_diagram( colourspaces=None, cmfs='CIE 1931 2 Degree Standard Observer', chromaticity_diagram_callable=plot_chromaticity_diagram, method='CIE 1931', show_whitepoints=True, show_pointer_gamut=False, **kwargs): """ Plots given *RGB* colourspaces in the *Chromaticity Diagram* according to given method. Parameters ---------- colourspaces : array_like, optional *RGB* colourspaces to plot. cmfs : unicode, optional Standard observer colour matching functions used for *Chromaticity Diagram* bounds. chromaticity_diagram_callable : callable, optional Callable responsible for drawing the *Chromaticity Diagram*. method : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, *Chromaticity Diagram* method. show_whitepoints : bool, optional Whether to display the *RGB* colourspaces whitepoints. show_pointer_gamut : bool, optional Whether to display the *Pointer's Gamut*. Other Parameters ---------------- \\**kwargs : dict, optional {:func:`colour.plotting.artist`, :func:`colour.plotting.diagrams.plot_chromaticity_diagram`, :func:`colour.plotting.plot_pointer_gamut`, :func:`colour.plotting.render`}, Please refer to the documentation of the previously listed definitions. Returns ------- tuple Current figure and axes. Examples -------- >>> plot_RGB_colourspaces_in_chromaticity_diagram( ... ['ITU-R BT.709', 'ACEScg', 'S-Gamut']) ... # doctest: +SKIP .. image:: ../_static/Plotting_\ Plot_RGB_Colourspaces_In_Chromaticity_Diagram.png :align: center :alt: plot_RGB_colourspaces_in_chromaticity_diagram """ if colourspaces is None: colourspaces = ['ITU-R BT.709', 'ACEScg', 'S-Gamut'] colourspaces = filter_RGB_colourspaces(colourspaces).values() settings = {'uniform': True} settings.update(kwargs) figure, axes = artist(**settings) method = method.upper() cmfs = first_item(filter_cmfs(cmfs).values()) title = '{0}\n{1} - {2} Chromaticity Diagram'.format( ', '.join([colourspace.name for colourspace in colourspaces]), cmfs.name, method) settings = {'axes': axes, 'title': title, 'method': method} settings.update(kwargs) settings['standalone'] = False chromaticity_diagram_callable(**settings) if show_pointer_gamut: settings = {'axes': axes, 'method': method} settings.update(kwargs) settings['standalone'] = False plot_pointer_gamut(**settings) if method == 'CIE 1931': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy x_limit_min, x_limit_max = [-0.1], [0.9] y_limit_min, y_limit_max = [-0.1], [0.9] elif method == 'CIE 1960 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_UCS_uv(xy) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.2], [0.6] elif method == 'CIE 1976 UCS': def xy_to_ij(xy): """ Converts given *xy* chromaticity coordinates to *ij* chromaticity coordinates. """ return xy_to_Luv_uv(xy) x_limit_min, x_limit_max = [-0.1], [0.7] y_limit_min, y_limit_max = [-0.1], [0.7] else: raise ValueError( 'Invalid method: "{0}", must be one of ' '{\'CIE 1931\', \'CIE 1960 UCS\', \'CIE 1976 UCS\'}'.format( method)) settings = {'colour_cycle_count': len(colourspaces)} settings.update(kwargs) cycle = colour_cycle(**settings) for colourspace in colourspaces: R, G, B, _A = next(cycle) # RGB colourspaces such as *ACES2065-1* have primaries with # chromaticity coordinates set to 0 thus we prevent nan from being # yield by zero division in later colour transformations. P = np.where( colourspace.primaries == 0, EPSILON, colourspace.primaries, ) P = xy_to_ij(P) W = xy_to_ij(colourspace.whitepoint) axes.plot((W[0], W[0]), (W[1], W[1]), color=(R, G, B), label=colourspace.name) if show_whitepoints: axes.plot((W[0], W[0]), (W[1], W[1]), 'o', color=(R, G, B)) axes.plot((P[0, 0], P[1, 0]), (P[0, 1], P[1, 1]), 'o-', color=(R, G, B)) axes.plot((P[1, 0], P[2, 0]), (P[1, 1], P[2, 1]), 'o-', color=(R, G, B)) axes.plot((P[2, 0], P[0, 0]), (P[2, 1], P[0, 1]), 'o-', color=(R, G, B)) x_limit_min.append(np.amin(P[..., 0]) - 0.1) y_limit_min.append(np.amin(P[..., 1]) - 0.1) x_limit_max.append(np.amax(P[..., 0]) + 0.1) y_limit_max.append(np.amax(P[..., 1]) + 0.1) bounding_box = ( min(x_limit_min), max(x_limit_max), min(y_limit_min), max(y_limit_max), ) settings.update({ 'standalone': True, 'legend': True, 'bounding_box': bounding_box, }) settings.update(kwargs) return render(**settings)