Reference

Candidate Image Pool

photomosaic.make_pool(glob_string, *, pool=None, skip_read_failures=True, analyzer=None, sample_size=1000)[source]

Analyze a collection of images.

For each file: (1) Read image. (2) Convert to perceptually-uniform color space. (3) Characterize the colors in the image as a vector.

A progress bar is displayed and then hidden after completion.

Parameters
glob_stringstring

a filepath with optional wildcards, like ‘*.jpg’

pooldict-like, optional

dict-like data structure to hold results; if None, dict is used

skip_read_failures: bool, optional

If True (default), convert any exceptions that occur while reading a file into warnings and continue.

analyzercallable, optional

Function with signature: f(img) -> arr where arr is a vector. The default analyzer is numpy.mean() along the 0th axis.

sample_sizeint or None, optional

Number of pixels to randomly sample before converting to perceptual colorspace and passing to analyzer; if None, do not subsample. Default is 1000.

Returns
pooldict-like

mapping arguments for opening file to analyzer’s result, e.g.: {(filename,): [1, 2, 3]}

photomosaic.import_pool(filepath)[source]

Import pool from json.

This is a thin convenience wrapper around json.load. It puts the data into the expected data structures, which don’t directly translate to JSON.

Unlike the rest of this package, the export and import functions assume that the pool is keyed on a tuple with a string (e.g., a filepath) as its only element.

Parameters
filepathstring
Returns
pooldict
photomosaic.export_pool(pool, filepath, abspath=True)[source]

Export pool to json.

This is a thin convenience wrapper around json.dump. The pool is just a dict, but it contains numpy arrays, which must be converted to plain lists before being exported to JSON.

Unlike the rest of this package, the export and import functions assume that the pool is keyed on a tuple with a string (e.g., a filepath) as its only element.

Parameters
pooldict
filepathstring
abspathboolean, optional

Convert pool keys (assumed to be filenames) to absolute paths if True.

photomosaic.rainbow_of_squares(target_dir, shape=(10, 10), range_params=(0, 256, 15))[source]

Generate 5832 small solid-color tiles for experimentation and testing.

Parameters
target_dirstring
shapetuple, optional

default is (10, 10)

range_paramstuple, optional

Passed to range() to stride through each color channel. Default is (0, 256, 15).

Color Conversion

photomosaic.perceptual(image)[source]

Convert color from RGB (sRGB1) to a perceptually uniform colorspace.

This is a convenience function wrapping colorspacious.csapce_convert. To configure the specific perceptual colorspace used, change photomosaic.options['colorspace'].

Parameters
imagearray
photomosaic.rgb(image, clip=True)[source]

Convert color from a perceptually uniform colorspace to RGB.

This is a convenience function wrapping colorspacious.csapce_convert. To configure the specific perceptual colorspace used, change photomosaic.options['perceptual'] and photomosaic.options['rgb'].

Parameters
imagearray
clipbool, option

Clip values out of the gamut [0, 1]. True by default.

photomosaic.set_options(imread=None, perceptual=None, rgb=None, flickr_api_key=None)[source]

Set global options

Parameters
imreaddict

keyword arguments passed through to every call to imread e.g., {'plugin': 'matplotlib'}

perceptualstring or dict

perceptually-uniform colorspace used for color comparisions; see colorspacious documentation for details

rgbstring or dict

specific RGB colorspace used for color conversion

flickr_api_keystring

API key used by photomosaic.flickr module

Utilities

photomosaic.standardize_image(image)[source]

Ensure that image is float 0-1 RGB with no alpha.

Parameters
imagearray
Returns
imagearray

may or may not be a copy of the original

photomosaic.rescale_commensurate(image, grid_dims, depth=0)[source]

For given grid dimensions and grid subdivision depth, scale image.

The image is rescaled so that its shape can be evenly split into tiles. If necessary, one dimension is cropped to fit.

Parameters
imagearray
grid_dimstuple

Number of tiles along height, width.

depthint, optional

Each tile can be subdivided this many times. Default is 0.

Returns
rescaled_imagearray
photomosaic.crop_to_fit(image, shape)[source]

Return a copy of image resized and cropped to precisely fill a shape.

To resize a colored 2D image, pass in a shape with two entries. When len(shape) < image.ndim, higher dimensions are ignored.

Parameters
imagearray
shapetuple

e.g., (height, width) but any length <= image.ndim is allowed

Returns
cropped_imagearray
photomosaic.sample_pixels(image, size, replace=True)[source]

Randomly sample pixels from an image.

This is a wrapper around np.random.choice (which only works directly on 1-dimensional arrays).

Parameters
imagearray
sizeint

number of pixels to sample

replaceboolean, optional

whether to sample with or without replacement; default True

Color Palettes

photomosaic.adapt_to_pool(image, pool, mask=None)[source]

Adjust the color timing of an image to use colors available in the pool.

For meaningful results, image and pool must be in the same colorspace.

This is a convenience function wrapping color_palette and palette_map.

Parameters
imagearray
pooldict
maskarray or None, optional

must have same shape as image

Returns
adapted_imagearray

Examples

If the image is RGB, first convert to perceptual space. Finally, before visualizing, convert back.

>>> rgb(adapt_to_pool(perceptual(image), pool)
photomosaic.color_palette(image, bins=256, mask=None, **kwargs)[source]

Compute the distribution of each color channel.

This wraps numpy.histogram, providing data munging relevant to image array with color channels. See numpy documentation for details on the meaning of the parameters.

Parameters
imagearray

The last axis is expected to be the color axis.

binsint or list

default 256; passed through to numpy.historgram

maskarray or None, optional

must have same shape as image

kwargs :

passed through to numpy.histogram

Returns
tuple :

((counts, bins), (counts, bins), ...) – one pair for color channel

photomosaic.palette_map(old_palette, new_palette)[source]

Build a function that maps from one color palette onto another.

These is wrapper around hist_map() that applies it to each color channel.

Parameters
old_palette: tuple

list of histogram arrays (count, bins) for each color channel

new_palettetuple

list of histogram arrays (count, bins) for each color channel

Returns
ffunction
photomosaic.hist_map(old_hist, new_hist)[source]

Build a function that maps from one distribution onto another.

Parameters
old_histtuple

Histogram arrays (count, bins) like those from numpy.histogram, where bins give edges, such that len(bins) == 1 + len(counts).

new_histtuple

Histogram arrays (count, bins) like those from numpy.histogram, where bins give edges, such that len(bins) == 1 + len(counts).

Returns
ffunction
photomosaic.plot_palette(palette, **kwargs)[source]

Plot color palette (histograms of each channel).

Parameters
palettetuple

color palette, such as created by color_palette()

**kwargs

passed through to matplotlib.Axes.plot

Returns
linesline artists created by matplotlib

Tiles

photomosaic.partition(image, grid_dims, mask=None, depth=0, split_thresh=10)[source]

Parition the target image into tiles.

Optionally, subdivide tiles that straddle a mask edge or contain high contrast, creating a grid with tiles of varied size.

Parameters
imagearray
grid_dimsint or tuple

number of (largest) tiles along each dimension

maskarray or None, optional

Tiles that straddle a mask edge will be subdivided, creating a smooth edge.

depthint, optional

Default is 0. Maximum times a tile can be subdivided.

split_threshfloat or None, optional

Threshold of standard deviation in color above which tile should be subdivided. This only applies if depth > 0. The (somewhat arbitrary) default is 10; a lower value leads to more aggressive splitting.

Returns
tileslist

list of pairs of slice objects

photomosaic.translate(tile, offset)[source]

Move a tile. This returns a moved copy; the original is unchaged.

Parameters
tiletuple

containing y and x slice objects

offsettuple

translation, given as (y, x)

Returns
tiletuple

a copy; the input is unchaged

photomosaic.pad(tile, padding)[source]

Shrink a tile in place, leaving a padding. This returns a copy.

Parameters
tiletuple

containing y and x slice objects

paddingtuple

number of pixels to leave along each side, given as (y, x)

Returns
tiletuple

a copy; the input is unchaged

photomosaic.scatter(tiles, margin)[source]

Randomly nudge the tiles off center within a given margin.

Also, shift all tiles in the positive direction by margin so that no slices are randomly placed < 0.

Parameters
tileslist

list of tuples of slices

margintuple

maximum distance off tile center, given as (y, x)

Returns
tileslist

a copy; the input is unchaged

Matching

photomosaic.simple_matcher(pool)[source]

Build a matching function that simply matches to the closest color.

It maintains an internal tree representation of the pool for fast lookups.

Parameters
pooldict
Returns
match_funcfunction

function that accepts a color vector and returns a match

photomosaic.simple_matcher_unique(pool, limit=1)[source]

Build a matching function that matches to the closest color not yet used.

It maintains an internal copy of the pool to track which items have been used.

Parameters
pooldict
limitinteger

Number of instances of each pool image allowed. Default is 1 (unique).

Returns
match_funcfunction

function that accepts a color vector and returns a match

Drawing

photomosaic.basic_mosaic(image, pool, grid_dims, *, mask=None, depth=0)[source]

Make a mosaic in one step with some basic settings.

See documentation (or the source code of this function) for more powerful features and customization.

Parameters
imagearray
pooldict-like

output from make_pool(); or any mapping of arguments for opening an image file to a vector characterizing it: e.g., {(filename,): [1, 2, 3]}

grid_dimstuple

Number of tiles along height, width.

maskarray or None, optional

must have same shape as image

depthint, optional

Each tile can be subdividing this many times in regions of high contrast or along mask edges (if applicable). Default is 0.

Returns
mosaicarray

Examples

Before making the mosaic, you need a collection of images to use as tiles. A collection of analyzed images is a “pool”. Analyzing the images takes much more time that making the mosaic, so it is a separate step.

>>> pool = make_pool('directory_of_images/*.jpg')

Load an image to turn into mosaic.

>>> from skimage.io import imread, imsave
>>> my_image = imread('my_image.jpg')

Make the mosaic and save it.

>>> mosaic = basic_mosaic(my_image, pool, (15, 15))
>>> imsave('my_mosaic.jpg', mosaic)
photomosaic.draw_mosaic(image, tiles, matches, scale=1, resized_copy_cache=None)[source]

Assemble the mosaic, the final result.

Parameters
imagearray

the “canvas” on which to draw the tiles, modified in place

tileslist

list of pairs of slice objects

matcheslist

for each tile in tiles, a tuple of arguments for opening the matching image file

scaleint, optional

Scale up tiles for higher resolution image; default is 1. Any not-integer input will be cast to int.

resized_copy_cachedict or None, optional

cache of images from the pool, sized to fit tiles entries look like: (pool_key, (height, width))

Returns
imagearray

Examples

Basic usage:

>>> draw_mosaic(image, tiles, matches)

Cache the resized pool images to speed up repeated drawings:

>>> cache = {}  # any mutable mapping
>>> draw_mosiac(image, tiles, matches, resized_copy_cache=cache)

The above populated cache with every resized pool image used in a tile. Now, draw_mosaic will check the cache before loading the pool image and resizing it, which is the most expensive step.

>>> draw_mosiac(image, tiles, matches, resized_copy_cache=cache)
photomosaic.draw_tile_layout(image, tiles, color=1)[source]

Draw the tile edges on a copy of image. Make a dot at each tile center.

This is a utility for inspecting a tile layout, not a necessary step in the mosaic-building process.

Parameters
imagearray
tileslist

list of pairs of slices, as generated by partition()

colorint or array

value to “draw” onto image at tile boundaries

Returns
annotated_imagearray

Color Characterization

This seems to perform worse than simply using numpy.mean().

photomosaic.dominant_color(pixels, n_clusters=5)[source]

Cluster colors and identify the “central” color of the largest cluster.

Parameters
pixelsarray

List of pixels. The second axis is expected to be the color axis.

n_clustersint, optional

number of clusters; default 5

Returns
dominant_colorarray