kwimage.im_color module¶
A class to make it easier to work with single colors.
- class kwimage.im_color.Color(color, alpha=None, space=None, coerce=True)[source]¶
Bases:
NiceRepr
Used for converting a single color between spaces and encodings. This should only be used when handling small numbers of colors(e.g. 1), don’t use this to represent an image.
- Parameters:
space (str) – colorspace of wrapped color. Assume RGB if not specified and it cannot be inferred
CommandLine
xdoctest -m ~/code/kwimage/kwimage/im_color.py Color
Example
>>> print(Color('g')) >>> print(Color('orangered')) >>> print(Color('#AAAAAA').as255()) >>> print(Color([0, 255, 0])) >>> print(Color([1, 1, 1.])) >>> print(Color([1, 1, 1])) >>> print(Color(Color([1, 1, 1])).as255()) >>> print(Color(Color([1., 0, 1, 0])).ashex()) >>> print(Color([1, 1, 1], alpha=255)) >>> print(Color([1, 1, 1], alpha=255, space='lab'))
- Parameters:
color (Color | Iterable[int | float] | str) – something coercable into a color
alpha (float | None) – if psecified adds an alpha value
space (str) – The colorspace to interpret this color as. Defaults to rgb.
coerce (bool) – The exsting init is not lightweight. This is a design problem that will need to be fixed in future versions. Setting coerce=False will disable all magic and use imputed color and space args directly. Alpha will be ignored.
- forimage(image, space='auto')[source]¶
Return a numeric value for this color that can be used in the given image.
Create a numeric color tuple that agrees with the format of the input image (i.e. float or int, with 3 or 4 channels).
- Parameters:
image (ndarray) – image to return color for
space (str) – colorspace of the input image. Defaults to ‘auto’, which will choose rgb or rgba
- Returns:
the color value
- Return type:
Tuple[Number, …]
Example
>>> import kwimage >>> img_f3 = np.zeros([8, 8, 3], dtype=np.float32) >>> img_u3 = np.zeros([8, 8, 3], dtype=np.uint8) >>> img_f4 = np.zeros([8, 8, 4], dtype=np.float32) >>> img_u4 = np.zeros([8, 8, 4], dtype=np.uint8) >>> kwimage.Color('red').forimage(img_f3) (1.0, 0.0, 0.0) >>> kwimage.Color('red').forimage(img_f4) (1.0, 0.0, 0.0, 1.0) >>> kwimage.Color('red').forimage(img_u3) (255, 0, 0) >>> kwimage.Color('red').forimage(img_u4) (255, 0, 0, 255) >>> kwimage.Color('red', alpha=0.5).forimage(img_f4) (1.0, 0.0, 0.0, 0.5) >>> kwimage.Color('red', alpha=0.5).forimage(img_u4) (255, 0, 0, 127) >>> kwimage.Color('red').forimage(np.uint8) (255, 0, 0)
- ashex(space=None)[source]¶
Convert to hex values
- Parameters:
space (None | str) – if specified convert to this colorspace before returning
- Returns:
the hex representation
- Return type:
- as01(space=None)[source]¶
Convert to float values
- Parameters:
space (None | str) – if specified convert to this colorspace before returning
- Returns:
The float tuple of color values between 0 and 1
- Return type:
Tuple[float, float, float] | Tuple[float, float, float, float]
Note
This function is only guarenteed to return 0-1 values for rgb values. For HSV and LAB, the native spaces are used. This is not ideal, and we may create a new function that fixes this - at least conceptually - and deprate this for that in the future.
For HSV, H is between 0 and 360. S, and V are in [0, 1]
- classmethod _is_base255(channels)[source]¶
there is a one corner case where all pixels are 1 or less
- classmethod named_colors()[source]¶
- Returns:
names of colors that Color accepts
- Return type:
List[str]
Example
>>> import kwimage >>> named_colors = kwimage.Color.named_colors() >>> color_lut = {name: kwimage.Color(name).as01() for name in named_colors} >>> # xdoctest: +REQUIRES(module:kwplot) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> # This is a very big table if we let it be, reduce it >>> color_lut =dict(list(color_lut.items())[0:10]) >>> canvas = kwplot.make_legend_img(color_lut) >>> kwplot.imshow(canvas)
- classmethod distinct(num, existing=None, space='rgb', legacy='auto', exclude_black=True, exclude_white=True)[source]¶
Make multiple distinct colors.
The legacy variant is based on a stack overflow post [HowToDistinct], but the modern variant is based on the
distinctipy
package.References
[HowToDistinct]https://stackoverflow.com/questions/470690/how-to-automatically-generate-n-distinct-colors
Todo
- [ ] If num is more than a threshold we should switch to
a different strategy to generating colors that just samples uniformly from some colormap and then shuffles. We have no hope of making things distinguishable when num starts going over 10 or so. See [ColorLimits] [WikiDistinguish] [Disinct2] for more ideas.
- Returns:
list of distinct float color values
- Return type:
List[Tuple]
Example
>>> # xdoctest: +REQUIRES(module:matplotlib) >>> from kwimage.im_color import * # NOQA >>> import kwimage >>> colors1 = kwimage.Color.distinct(5, legacy=False) >>> colors2 = kwimage.Color.distinct(3, existing=colors1) >>> # xdoctest: +REQUIRES(module:kwplot) >>> # xdoctest: +REQUIRES(--show) >>> from kwimage.im_color import _draw_color_swatch >>> swatch1 = _draw_color_swatch(colors1, cellshape=9) >>> swatch2 = _draw_color_swatch(colors1 + colors2, cellshape=9) >>> import kwplot >>> kwplot.autompl() >>> kwplot.imshow(swatch1, pnum=(1, 2, 1), fnum=1) >>> kwplot.imshow(swatch2, pnum=(1, 2, 2), fnum=1) >>> kwplot.show_if_requested()
- distance(other, space='lab')[source]¶
Distance between self an another color
- Parameters:
other (Color) – the color to compare
space (str) – the colorspace to comapre in
- Returns:
float
- interpolate(other, alpha=0.5, ispace=None, ospace=None)[source]¶
Interpolate between colors
- Parameters:
other (Color) – A coercable Color
alpha (float | List[float]) – one or more interpolation values
ispace (str | None) – colorspace to interpolate in
ospace (str | None) – colorspace of returned color
- Returns:
Color | List[Color]
Example
>>> import kwimage >>> color1 = self = kwimage.Color.coerce('orangered') >>> color2 = other = kwimage.Color.coerce('dodgerblue') >>> alpha = np.linspace(0, 1, 6) >>> ispace = 'rgb' >>> ospace = 'rgb' >>> colorBs = self.interpolate(other, alpha, ispace=ispace, ospace=ospace) >>> # xdoctest: +REQUIRES(module:kwplot) >>> # xdoctest: +REQUIRES(--show) >>> from kwimage.im_color import _draw_color_swatch >>> swatch_colors = [color1] + colorBs + [color2] >>> print('swatch_colors = {}'.format(ub.urepr(swatch_colors, nl=1))) >>> swatch1 = _draw_color_swatch(swatch_colors, cellshape=(8, 8)) >>> import kwplot >>> kwplot.autompl() >>> kwplot.imshow(swatch1, pnum=(1, 1, 1), fnum=1) >>> kwplot.show_if_requested()
- to_image(dsize=(8, 8))[source]¶
Create an solid-color image with this color
- Parameters:
dsize (Tuple[int, int]) – the desired width / height of the image (defaults to 8x8)
- adjust(saturate=0, lighten=0)[source]¶
Adjust the saturation or value of a color.
Requires that
colormath
is installed.- Parameters:
saturate (float) – between +1 and -1, when positive saturates the color, when negative desaturates the color.
lighten (float) – between +1 and -1, when positive lightens the color, when negative darkens the color.
Example
>>> # xdoctest: +REQUIRES(module:colormath) >>> import kwimage >>> self = kwimage.Color.coerce('salmon') >>> new = self.adjust(saturate=+0.2) >>> cell1 = self.to_image() >>> cell2 = new.to_image() >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> canvas = kwimage.stack_images([cell1, cell2], axis=1) >>> kwplot.imshow(canvas)
Example
>>> # xdoctest: +REQUIRES(module:colormath) >>> import kwimage >>> self = kwimage.Color.coerce('salmon', alpha=0.5) >>> new = self.adjust(saturate=+0.2) >>> cell1 = self.to_image() >>> cell2 = new.to_image() >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> canvas = kwimage.stack_images([cell1, cell2], axis=1) >>> kwplot.imshow(canvas)
Example
>>> # xdoctest: +REQUIRES(module:colormath) >>> import kwimage >>> adjustments = [ >>> {'saturate': -0.2}, >>> {'saturate': +0.2}, >>> {'lighten': +0.2}, >>> {'lighten': -0.2}, >>> {'saturate': -0.9}, >>> {'saturate': +0.9}, >>> {'lighten': +0.9}, >>> {'lighten': -0.9}, >>> ] >>> self = kwimage.Color.coerce('kitware_green') >>> dsize = (256, 64) >>> to_show = [] >>> to_show.append(self.to_image(dsize)) >>> for kwargs in adjustments: >>> new = self.adjust(**kwargs) >>> cell = new.to_image(dsize=dsize) >>> text = ub.urepr(kwargs, compact=1, nobr=1) >>> cell, info = kwimage.draw_text_on_image(cell, text, return_info=1, border={'thickness': 2}, color='white', fontScale=1.0) >>> to_show.append(cell) >>> # xdoctest: +REQUIRES(--show) >>> # xdoctest: +REQUIRES(module:kwplot) >>> import kwplot >>> kwplot.autompl() >>> canvas = kwimage.stack_images_grid(to_show) >>> canvas = kwimage.draw_header_text(canvas, 'kwimage.Color.adjust') >>> kwplot.imshow(canvas)