Reputation: 13743
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
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