Skip to content

arvkevi/img2cmap

Repository files navigation

img2cmap

Usage

Create colormaps from images in three lines of code!

First, ImageConverter class converts images to arrays of RGB values.
Then, generate_cmap creates a matplotlib ListedColormap.
from img2cmap import ImageConverter

# Can be a local file or URL
converter = ImageConverter("tests/images/south_beach_sunset.jpg")
cmap = converter.generate_cmap(n_colors=5, palette_name="south_beach_sunset", random_state=42)

Now, use the colormap in your plots!

import matplotlib.pyplot as plt

colors = cmap.colors

with plt.style.context("dark_background"):
    for i, color in enumerate(colors):
        plt.plot(range(10), [_+i+1 for _ in range(10)], color=color, linewidth=4)

image

Plot the image and a colorbar side by side.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

fig, ax = plt.subplots(figsize=(7, 5))

ax.axis("off")
img = plt.imread("tests/images/south_beach_sunset.jpg")
im = ax.imshow(img, cmap=cmap)

divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="10%", pad=0.05)

cb = fig.colorbar(im, cax=cax, orientation="vertical", label=cmap.name)
cb.set_ticks([])

image

Advanced

generate_optimal_cmap

You can extract the optimal number of colors from the image using the generate_optimal_cmap method. Under the hood this performs the elbow method <https://en.wikipedia.org/wiki/Elbow_method_(clustering)> to determine the optimal number of clusters based on the sum of the squared distances between each pixel and it's cluster center.

cmaps, best_n_colors, ssd = converter.generate_optimal_cmap(max_colors=10, random_state=42)

best_cmap = cmaps[best_n_colors]

remove_transparent

In an image of the Los Angeles Lakers logo, the background is transparent. These pixels contribute to noise when generating the colors. Running the remove_transparent method will remove transparent pixels. Here's a comparison of the colormaps generated by the same image, without and with transparency removed.

Make two ImageConverter objects:

from img2cmap import ImageConverter

image_url = "https://loodibee.com/wp-content/uploads/nba-los-angeles-lakers-logo.png"

# Create two ImageConverters, one with transparency removed and one without
converter_with_transparent = ImageConverter(image_url)
converter_with_transparent.remove_transparent()

converter_no_transparent = ImageConverter(image_url)

cmap_with_transparent = converter_with_transparent.generate_cmap(
    n_colors=3, palette_name="with_transparent", random_state=42
)
cmap_no_transparent = converter_no_transparent.generate_cmap(
    n_colors=3, palette_name="no_transparent", random_state=42
)

Plot both colormaps with the image:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

for cmap in [cmap_with_transparent, cmap_no_transparent]:
    fig, ax = plt.subplots(figsize=(7, 5))

    ax.axis("off")
    img = converter_no_transparent.image
    im = ax.imshow(img, cmap=cmap)

    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", size="10%", pad=0.05)

    cb = fig.colorbar(im, cax=cax, orientation="vertical", label=cmap.name)
    cb.set_ticks([])

image

image

Notice, only after removing the transparent pixels, does the classic purple and gold show in the colormap.

resize

There is a method of the ImageConverter class to resize images. It will preserve the aspect ratio, but reduce the size of the image.

def test_resize():
    imageconverter = ImageConverter("tests/images/south_beach_sunset.jpg")
    imageconverter.resize(size=(512, 512))
    # preserves aspect ratio
    assert imageconverter.image.size == (512, 361)

hexcodes

When running the generate_cmap or the generate_optimal_cmap methods the ImageConverter object will automatically capture the resulting hexcodes from the colormap and store them as an attribute.

from img2cmap import ImageConverter

image_url = "https://static1.bigstockphoto.com/3/2/3/large1500/323952496.jpg"

converter = ImageConverter(image_url)
converter.generate_cmap(n_colors=4, palette_name="with_transparent", random_state=42)
print(converter.hexcodes)

Output:

['#ba7469', '#dfd67d', '#5d536a', '#321e28']

Installation

pip install img2cmap

You can also install the in-development version with:

pip install https://github.com/arvkevi/img2cmap/archive/main.zip

Documentation

https://img2cmap.readthedocs.io/

Web App

Check out the web app at https://img2cmap.fly.dev

image

Status

docs Documentation Status
tests
GitHub Actions Build Status
Coverage Status
package
PyPI Package latest release PyPI Wheel Supported versions Supported implementations

Development

Install the development requirements:

pip install img2cmap[dev]

To run all the tests run:

tox

Note, to combine the coverage data from all the tox environments run:

Windows
set PYTEST_ADDOPTS=--cov-append
tox
Other
PYTEST_ADDOPTS=--cov-append tox