If you are limited to using numpy, TheodrosZelleke's answer is the way to go. But if you allow other modules, cv2
is a useful module for interacting with image data, and it accepts numpy arrays as input. A big limitation is that the image array must have dtype='uint8'
, but as long as that is OK, the function cv2.LUT
does exactly what we want, and it provides a significant speedup:
>>> import numpy as np
>>> import cv2
>>> lut = np.arange(256, dtype='uint8')
>>> image = np.random.randint(256, size=(5000, 5000), dtype='uint8')
>>> np.all(lut[image] == cv2.LUT(image, lut))
True
>>> import timeit
>>> timeit.timeit('lut[image]', 'from __main__ import lut, image', number=10)
0.5747578000000431
>>> timeit.timeit('cv2.LUT(image, lut)',
... 'from __main__ import cv2, lut, image', number=10)
0.07559149999997317
Your lookup table can be some other datatype, but you loose a lot of the speed improvement (although numpy indexing takes a performance hit as well). For example, with dtype='float64'
:
>>> lut = np.arange(256, dtype='float64')
>>> timeit.timeit('lut[image]', 'from __main__ import lut, image', number=10)
1.068468699999812
>>> timeit.timeit('cv2.LUT(image, lut)',
... 'from __main__ import cv2, lut, image', number=10)
0.41085720000000947