Tonechas
Tonechas

Reputation: 13743

How to apply a multidimensional look up table to a color image?

For the sake of simplicity, let us assume that the image has two rows and four columns, and pixel colors are represented by a triplet of intensity levels (intensity is quantized to five different integer values). I want to transform such color image into a single-channel image through a 3D look up table by using the intensity levels of each pixel as indices. This toy example can be implemented as follows:

import numpy as np
levels = 5
rows, columns, channels = 2, 4, 3

lut = np.arange(levels**channels).reshape([levels for n in range(channels)])
np.random.seed(0)
img = np.random.randint(low=0, high=levels, size=(rows, columns, channels))

I'm aware that I can hardcode the indexing like this:

red = img[:, :, 0]
green = img[:, :, 1]
blue = img[:, :, 2]
indexed = lut[red, green, blue]

The code above can be generalized to work with multi spectral images:

indexed = lut[[img[:, :, i] for i in range(channels)]]

Both approaches yield the same result:

In [931]: indexed
Out[931]: 
array([[103,  91,  89,   4],
       [ 55,  30,  48,  15]])

My question: Is there a more elegant way to obtain the same result? More concretely, I'm looking for a NumPy function that splits a color image (3D array) into a list of its chromatic channels (2D arrays). Alternatively I've thought that the transformation could be carried out through matplotlib using lut as a colormap.

Upvotes: 0

Views: 1372

Answers (1)

fferri
fferri

Reputation: 18950

Is this:

red, green, blue = img.transpose()

lut[red, green, blue].transpose()

what you are looking for?

The img.transpose() needed for rearranging the axes expected for channel unpack.

For an arbitrary number of channels:

lut[tuple(img.transpose())].transpose()

Upvotes: 1

Related Questions