Use np.unique
.
The following is some boilerplate code for testing.
IMAGE_SHAPE = (224, 224) # Given image shape
# Given colors.
colors = np.array([
[ 0, 0, 0], [128, 0, 0], [ 0, 128, 0], [128, 128, 0], [ 0, 0, 128],
[128, 0, 128], [ 0, 128, 128], [128, 128, 128], [ 64, 0, 0], [192, 0, 0],
[ 64, 128, 0], [192, 128, 0], [ 64, 0, 128], [192, 0, 128], [ 64, 128, 128],
[192, 128, 128], [ 0, 64, 0], [128, 64, 0], [ 0, 192, 0], [128, 192, 0],
[ 0, 64, 128]], dtype=np.uint8)
# Generate a random image with pixel colors taken from 'colors'.
image = colors[np.random.randint(0, colors.shape[0], IMAGE_SHAPE)]
Running print(image)
will produce a (224, 224, 3)
array that looks something like
array([[[128, 128, 0],
[ 0, 128, 0],
[192, 0, 0],
...,
[192, 0, 0],
[128, 0, 0],
[ 64, 0, 128]],
...,
[[ 64, 128, 0],
[128, 128, 128],
[ 0, 64, 128],
...,
[ 64, 0, 0],
[192, 128, 128],
[192, 0, 0]]], dtype=uint8)
To convert the image to an array of pixel-color indices, invoke np.unique
as
_colors, index_image = np.unique(image.reshape(-1, 3), return_inverse=True)
index_image = index_image.reshape(IMAGE_SHAPE)
The array _colors
will contain the same pixel values as colors
(though likely in a different order), and index_image
will be a (224, 224)
array with entries that give the index of each pixel in _colors
:
print(_colors)
print(index_image.shape)
print(index_image)
results in
array([[ 0, 0, 0],
[ 0, 0, 128],
[ 0, 64, 0],
[ 0, 64, 128],
[ 0, 128, 0],
[ 0, 128, 128],
[ 0, 192, 0],
[ 64, 0, 0],
[ 64, 0, 128],
[ 64, 128, 0],
[ 64, 128, 128],
[128, 0, 0],
[128, 0, 128],
[128, 64, 0],
[128, 128, 0],
[128, 128, 128],
[128, 192, 0],
[192, 0, 0],
[192, 0, 128],
[192, 128, 0],
[192, 128, 128]], dtype=uint8)
(224, 224)
array([[14, 4, 17, ..., 17, 11, 8],
[ 9, 7, 11, ..., 5, 17, 7],
...,
[ 8, 10, 0, ..., 1, 6, 16],
[ 9, 15, 3, ..., 7, 20, 17]])
The mapping can be reversed simply by indexing _colors
:
print(_colors[index_image])
print(np.all(_color[index_image] == image))
produces
array([[[128, 128, 0],
[ 0, 128, 0],
[192, 0, 0],
...,
[192, 0, 0],
[128, 0, 0],
[ 64, 0, 128]],
...,
[[ 64, 128, 0],
[128, 128, 128],
[ 0, 64, 128],
...,
[ 64, 0, 0],
[192, 128, 128],
[192, 0, 0]]], dtype=uint8)
True